<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-5089178761965217498</id><updated>2011-12-29T15:03:21.381-06:00</updated><category term='linux'/><category term='ruby'/><category term='apache'/><category term='buzzwords'/><category term='scripting'/><category term='xml'/><category term='nasm'/><category term='mysql'/><category term='java'/><category term='cloud computing'/><category term='law'/><category term='portable apps'/><category term='php'/><category term='usb'/><category term='apple'/><category term='programming'/><category term='analogx'/><category term='tablet pc'/><category term='mac os x'/><category term='open source'/><category term='freeware'/><category term='bash'/><category term='eyeos'/><category term='Google'/><category term='c'/><category term='c#'/><category term='powershell'/><category term='python'/><category term='unix'/><category term='administration'/><category term='server'/><category term='lamp'/><category term='code bloat'/><category term='network'/><category term='dos'/><category term='bofh'/><category term='assembly language'/><category term='database'/><category term='profile'/><title type='text'>a traveller from an antique land</title><subtitle type='html'>a brief and biased look at the state of computer technology today.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://mechatechzilla.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://mechatechzilla.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>mechatechzilla</name><uri>http://www.blogger.com/profile/17585447008783853422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://1.bp.blogspot.com/_jbCdMAhJU58/SpM-dMKvHKI/AAAAAAAABCw/fJGkIdcMqCE/S220/red_shirt.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>21</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5089178761965217498.post-8953638708775092839</id><published>2011-12-27T20:43:00.001-06:00</published><updated>2011-12-29T15:03:21.390-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='open source'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='buzzwords'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='Google'/><category scheme='http://www.blogger.com/atom/ns#' term='cloud computing'/><title type='text'>love my chromebook, but...</title><content type='html'>it was 2002 when i installed &lt;a href="http://www.thinkfree.com/"&gt;thinkfree office&lt;/a&gt; as a cross-platform alternative to a popular proprietary office suite. that is when i began moving my life to the cloud. i realized that having to manage data on several computers running different operating systems was silly. i needed access to much of the same stuff on my mac, sparcstation, linux and windows pcs, and i didn't want to have to maintain multiple copies. the cloud made sense to me, though it wasn't then quite the buzzword that it has since become.&lt;br /&gt;&lt;br /&gt;back then i predicted that we would one day run most of our software over the internet on a subscription basis. while we haven't arrived there yet, we're certainly going that way. i can now edit documents, touch up photos, record music and video, take notes, send email and text messages, make phone calls, listen to music, read books, watch movies and television shows, and write code all online. since that pretty well sums up most everything i do on a computer today i decided to take the plunge and pick up a &lt;a href="http://goo.gl/BYpdZ"&gt;chromebook&lt;/a&gt;, the samsung series 5 with 3g (in a lovely arctic white.) i have to say, i'm loving it, and i will keep you posted here about my adventures in google's vision of the cloud.&lt;br /&gt;&lt;br /&gt;before i wrap up this post, i'll share my impressions after my first week with chromebook. i have to say, there are so many things i love about this device that i can't list them all. speed and convenience are at the top, though. but i have two needs that the chromebook doesn't address. one, i must have a local rdp client. i need to communicate with my company's terminal server from the public internet, but i also need to talk to &lt;a href="http://goo.gl/r47Ep"&gt;virtualbox&lt;/a&gt; machines that are running on private networks. web-based rdp-to-html5 services can't access my private ip addresses, so a local client is a must. word is, &lt;a href="http://goo.gl/nMU8j"&gt;google is working on this&lt;/a&gt;, so i'll wait. the second is java. now, if the chromebook had a jre then my first concern might disappear—i've found a very fine &lt;a href="http://goo.gl/GFuEC"&gt;java rdp client&lt;/a&gt;. but there are many web sites that use java, not the least of which are those that host games like minecraft and runescape. after all, all work and no play...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5089178761965217498-8953638708775092839?l=mechatechzilla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mechatechzilla.blogspot.com/feeds/8953638708775092839/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mechatechzilla.blogspot.com/2011/12/love-my-chromebook-but.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/8953638708775092839'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/8953638708775092839'/><link rel='alternate' type='text/html' href='http://mechatechzilla.blogspot.com/2011/12/love-my-chromebook-but.html' title='love my chromebook, but...'/><author><name>mechatechzilla</name><uri>http://www.blogger.com/profile/17585447008783853422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://1.bp.blogspot.com/_jbCdMAhJU58/SpM-dMKvHKI/AAAAAAAABCw/fJGkIdcMqCE/S220/red_shirt.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5089178761965217498.post-4035710237239314569</id><published>2011-03-30T08:19:00.003-05:00</published><updated>2011-03-30T16:05:13.653-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cloud computing'/><title type='text'>deploying to the cloud: a white paper</title><content type='html'>some folks have more experience with "cloud computing" than others. stretching back into the days of green screens and mainframes, ibm is arguably the most prolific player on the block, and they bring that 40-years of experience to you in this informative &lt;a href="http://goo.gl/hxnJH"&gt;white paper&lt;/a&gt;. the link requires free registration&amp;mdash;a small price to pay for some valuable information.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;until next time.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5089178761965217498-4035710237239314569?l=mechatechzilla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mechatechzilla.blogspot.com/feeds/4035710237239314569/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mechatechzilla.blogspot.com/2011/03/deploying-to-cloud-white-paper.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/4035710237239314569'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/4035710237239314569'/><link rel='alternate' type='text/html' href='http://mechatechzilla.blogspot.com/2011/03/deploying-to-cloud-white-paper.html' title='deploying to the cloud: a white paper'/><author><name>mechatechzilla</name><uri>http://www.blogger.com/profile/17585447008783853422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://1.bp.blogspot.com/_jbCdMAhJU58/SpM-dMKvHKI/AAAAAAAABCw/fJGkIdcMqCE/S220/red_shirt.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5089178761965217498.post-5295534565323243240</id><published>2010-12-25T10:00:00.004-06:00</published><updated>2010-12-28T09:49:04.047-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='xml'/><category scheme='http://www.blogger.com/atom/ns#' term='scripting'/><title type='text'>"ruby, any messages for me?"</title><content type='html'>i have successfully consolidated all of my email accounts to gmail. this makes it easy for me to read all my messages from my android phone or other portable internet devices. during the work week i'm rather tied to my email, but it does no good to leave a web browser tab open on the gmail site while i'm teaching class, and it eats up resources unnecessarily. so, i knocked off this little ruby script to check the google xml feed and determine if i have any new mail messages. this simply displays in my &lt;a href="http://goo.gl/Mtcv9"&gt;conky&lt;/a&gt; resource monitor on my desktop, but you can do something fancier, even use this in a more elaborate mail fetching script, if you wish.&lt;br /&gt;&lt;pre style="color: white; background-color: #000033; width: 93ex; padding: 1ex;"&gt;&lt;br /&gt;01 &lt;span style="color: #0066ff; font-style: italic;"&gt;#!/usr/bin/ruby&lt;/span&gt;&lt;br /&gt;02 &lt;span style="color: #0066ff; font-style: italic;"&gt;# gmail.rb&lt;/span&gt;&lt;br /&gt;03 &lt;span style="color: #0066ff; font-style: italic;"&gt;# Checks a gmail account and displays the number of unread (new) messages&lt;/span&gt;&lt;br /&gt;04 &lt;span style="color: #0066ff; font-style: italic;"&gt;# waiting on the server.&lt;/span&gt;&lt;br /&gt;05 &lt;span style="color: #0066ff; font-style: italic;"&gt;# Robert Ritter &amp;lt;rritter@centriq.com&gt;&lt;/span&gt;&lt;br /&gt;06 &lt;span style="color: #0066ff; font-style: italic;"&gt;# December 20, 2010&lt;/span&gt;&lt;br /&gt;07&lt;br /&gt;08 &lt;span style="color: #0066ff; font-style: italic;"&gt;# Use 'nokogiri' to parse XML.&lt;/span&gt;&lt;br /&gt;09 &lt;span style="color: cyan;"&gt;require&lt;/span&gt; &lt;span style="color: #00ff00;"&gt;'nokogiri'&lt;/span&gt;&lt;br /&gt;10 &lt;span style="color: cyan;"&gt;require&lt;/span&gt; &lt;span style="color: #00ff00;"&gt;'open-uri'&lt;/span&gt;&lt;br /&gt;11&lt;br /&gt;12 username = &lt;span style="color: #00ff00;"&gt;'not_a_real_user@gmail.com'&lt;/span&gt;&lt;br /&gt;13 password = &lt;span style="color: #00ff00;"&gt;'not_a_real_password_either'&lt;/span&gt;&lt;br /&gt;13&lt;br /&gt;14 tree = Nokogiri.XML(open(&lt;span style="color: #00ff00;"&gt;'https://mail.google.com/mail/feed/atom'&lt;/span&gt;,&lt;br /&gt;15     &lt;span style="color: magenta;"&gt;:http_basic_authentication&lt;/span&gt;=&gt;[username, password]))&lt;br /&gt;16 &lt;br /&gt;17 puts tree.xpath(&lt;span style="color: #00ff00;"&gt;'//xmlns:fullcount'&lt;/span&gt;).first.content&lt;br /&gt;18&lt;br /&gt;&lt;/rritter@centriq.com&gt;&lt;/pre&gt;&lt;br /&gt;until next time!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5089178761965217498-5295534565323243240?l=mechatechzilla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mechatechzilla.blogspot.com/feeds/5295534565323243240/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mechatechzilla.blogspot.com/2010/12/ruby-any-messages-for-me.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/5295534565323243240'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/5295534565323243240'/><link rel='alternate' type='text/html' href='http://mechatechzilla.blogspot.com/2010/12/ruby-any-messages-for-me.html' title='&quot;ruby, any messages for me?&quot;'/><author><name>mechatechzilla</name><uri>http://www.blogger.com/profile/17585447008783853422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://1.bp.blogspot.com/_jbCdMAhJU58/SpM-dMKvHKI/AAAAAAAABCw/fJGkIdcMqCE/S220/red_shirt.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5089178761965217498.post-6829699650664325864</id><published>2010-12-20T11:10:00.004-06:00</published><updated>2010-12-20T11:27:36.126-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='powershell'/><category scheme='http://www.blogger.com/atom/ns#' term='administration'/><category scheme='http://www.blogger.com/atom/ns#' term='scripting'/><title type='text'>three wee scripts in powershell 2...</title><content type='html'>'tis the season of giving. several of my students have been asking for advanced user interface examples in powershell, so here are &lt;a href="http://ritterhaus.public.s3.amazonaws.com/UIScripts.zip"&gt;three scripts&lt;/a&gt; (and a module) for them, you, and anyone else who cares to look. they are heavily commented so i'll not go into details, but this is what i got you for christmas...&lt;br /&gt;&lt;br /&gt;&lt;b&gt;screenctl.psm1&lt;/b&gt; is a module that contains three useful functions used by the scripts in this set. &lt;i&gt;set-cursor&lt;/i&gt; places the cursor exactly where you want it on the screen, so that whatever you print starts displaying there. &lt;i&gt;clear-lines&lt;/i&gt; clears a specific number of lines from the screen, rather than the whole thing. combined with set-cursor you can clear just a small section of the screen if you wish. &lt;i&gt;out-wrappedstring&lt;/i&gt; is a variation of the text-wrapping function i talked about &lt;a href="http://mechatechzilla.blogspot.com/2010/07/powershell-my-3-favorite-functions-2-of.html"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;addusers.ps1&lt;/b&gt; walks you through adding a user account to active directory. it uses the screenctl module to customize the output and the activedirectory module to read and write the database.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;get-weather.ps1&lt;/b&gt; provides current conditions and forecast from an internet xml stream. it uses the screenctl module to wrap long forecast strings.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;netcfg.ps1&lt;/b&gt; provides a graphical interface to the network information for machines listed in active directory. it uses the active directory module to locate computers.&lt;br /&gt;&lt;br /&gt;read the example scripts, improve them, have fun with them this holiday season. it's better than listening to uncle lloyd snore in front of the television, right?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5089178761965217498-6829699650664325864?l=mechatechzilla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mechatechzilla.blogspot.com/feeds/6829699650664325864/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mechatechzilla.blogspot.com/2010/12/three-wee-scripts-in-powershell-2.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/6829699650664325864'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/6829699650664325864'/><link rel='alternate' type='text/html' href='http://mechatechzilla.blogspot.com/2010/12/three-wee-scripts-in-powershell-2.html' title='three wee scripts in powershell 2...'/><author><name>mechatechzilla</name><uri>http://www.blogger.com/profile/17585447008783853422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://1.bp.blogspot.com/_jbCdMAhJU58/SpM-dMKvHKI/AAAAAAAABCw/fJGkIdcMqCE/S220/red_shirt.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5089178761965217498.post-2205403936521736339</id><published>2010-08-26T08:43:00.007-05:00</published><updated>2010-08-26T11:28:51.369-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='powershell'/><category scheme='http://www.blogger.com/atom/ns#' term='administration'/><category scheme='http://www.blogger.com/atom/ns#' term='scripting'/><title type='text'>random passwords in powershell</title><content type='html'>&lt;style&gt;#pscode{ font-weight: bold; background-color: palegoldenrod; color: black; padding: 1em; width: 51em; } #command{ font-weight: bold; background-color: navy; color: silver; padding: 1em; width: 51em;} .comment{ color: darkgreen;} .keyword{ color: navy; } .function{ color: teal; } .var { color: magenta; } .string{ color: maroon; } .op{ color: red; } .option{ color: darkcyan; font-style: oblique; } .optname{ color: purple; font-style: oblique; } .num {color: purple}&lt;/style&gt;&lt;br /&gt;recently i was teaching my students how to read hundreds of user accounts from a text file and create them in active directory in seconds with a powershell script. to the script we added a nifty function to generate random initial passwords that meet the complexity requirements of windows. here's our function:&lt;br /&gt;&lt;pre id="pscode"&gt;&lt;br /&gt;9  &lt;span class="comment"&gt;# new_password&lt;/span&gt;&lt;br /&gt;10 &lt;span class="comment"&gt;#       Returns a string.&lt;/span&gt;&lt;br /&gt;11 &lt;span class="comment"&gt;# Generates a random password for the user that meets Windows' complexity&lt;/span&gt;&lt;br /&gt;12 &lt;span class="comment"&gt;# requirements.&lt;/span&gt;&lt;br /&gt;13 &lt;span class="keyword"&gt;function&lt;/span&gt; &lt;span class="function"&gt;new_password&lt;/span&gt; {&lt;br /&gt;14         &lt;span class="var"&gt;$randomizer&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="function"&gt;New-Object&lt;/span&gt; &lt;span class="function"&gt;System.Random&lt;/span&gt;&lt;br /&gt;15         &lt;span class="var"&gt;$password&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt;  [&lt;span class="function"&gt;char&lt;/span&gt;] &lt;span class="var"&gt;$randomizer&lt;/span&gt;.next(&lt;span class="num"&gt;65&lt;/span&gt;,&lt;span class="num"&gt;91&lt;/span&gt;)     &lt;span class="comment"&gt;# Uppercase letters&lt;/span&gt;&lt;br /&gt;16         &lt;span class="var"&gt;$password&lt;/span&gt; &lt;span class="op"&gt;+=&lt;/span&gt; [&lt;span class="function"&gt;char&lt;/span&gt;] &lt;span class="var"&gt;$randomizer&lt;/span&gt;.next(&lt;span class="num"&gt;48&lt;/span&gt;,&lt;span class="num"&gt;58&lt;/span&gt;)     &lt;span class="comment"&gt;# Numbers&lt;/span&gt;&lt;br /&gt;17         &lt;span class="var"&gt;$password&lt;/span&gt; &lt;span class="op"&gt;+=&lt;/span&gt; [&lt;span class="function"&gt;char&lt;/span&gt;] &lt;span class="var"&gt;$randomizer&lt;/span&gt;.next(&lt;span class="num"&gt;91&lt;/span&gt;,&lt;span class="num"&gt;127&lt;/span&gt;)    &lt;span class="comment"&gt;# Lowercase letters&lt;/span&gt;&lt;br /&gt;18                                                         &lt;span class="comment"&gt;# and punctuation&lt;/span&gt;&lt;br /&gt;19         &lt;span class="keyword"&gt;foreach&lt;/span&gt; (&lt;span class="var"&gt;$time&lt;/span&gt; &lt;span class="keyword"&gt;in&lt;/span&gt; &lt;span class="num"&gt;1&lt;/span&gt;..&lt;span class="num"&gt;7&lt;/span&gt;) {&lt;br /&gt;20                 &lt;span class="var"&gt;$password&lt;/span&gt; &lt;span class="op"&gt;+=&lt;/span&gt; [&lt;span class="function"&gt;char&lt;/span&gt;] &lt;span class="var"&gt;$randomizer&lt;/span&gt;.next(&lt;span class="num"&gt;32&lt;/span&gt;,&lt;span class="num"&gt;127&lt;/span&gt;)&lt;br /&gt;21         }&lt;br /&gt;22         &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="var"&gt;$password&lt;/span&gt;&lt;br /&gt;23 } &lt;span class="comment"&gt;# end function new_password&lt;/span&gt;&lt;br /&gt;24&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;don't forget to write the passwords out to a file when you're done so that you can tell users what they are:&lt;br /&gt;&lt;pre id="pscode"&gt;&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;62 &lt;span class="comment"&gt;# Write the username and password to a file.&lt;/span&gt;&lt;br /&gt;63 &lt;span class="string"&gt;"{0,-19} {1}"&lt;/span&gt; &lt;span class="op"&gt;-f&lt;/span&gt; &lt;span class="var"&gt;$samAccountName&lt;/span&gt;, &lt;span class="var"&gt;$password&lt;/span&gt; &lt;span class="op"&gt;&gt;&gt;&lt;/span&gt; userspass.txt&lt;br /&gt;64 &lt;span class="string"&gt;"-"&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="num"&gt;30&lt;/span&gt; &lt;span class="op"&gt;&gt;&gt;&lt;/span&gt; userspass.txt&lt;br /&gt;65&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;until next time.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5089178761965217498-2205403936521736339?l=mechatechzilla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mechatechzilla.blogspot.com/feeds/2205403936521736339/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mechatechzilla.blogspot.com/2010/08/random-passwords-in-powershell.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/2205403936521736339'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/2205403936521736339'/><link rel='alternate' type='text/html' href='http://mechatechzilla.blogspot.com/2010/08/random-passwords-in-powershell.html' title='random passwords in powershell'/><author><name>mechatechzilla</name><uri>http://www.blogger.com/profile/17585447008783853422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://1.bp.blogspot.com/_jbCdMAhJU58/SpM-dMKvHKI/AAAAAAAABCw/fJGkIdcMqCE/S220/red_shirt.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5089178761965217498.post-4401830627208469204</id><published>2010-07-29T20:59:00.026-05:00</published><updated>2010-08-03T19:35:11.973-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='xml'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><category scheme='http://www.blogger.com/atom/ns#' term='c'/><title type='text'>xml 2: and now, a word from our compilers...</title><content type='html'>&lt;style&gt;#cscode{ font-weight: bold; background-color: #303030; color: #aaaaaa; padding: 1em; width: 53em; } #command{ font-weight: bold; background-color: navy; color: silver; padding: 1em; width: 51em;} .dcomment{ color: #666666;} .dkeyword{ color: mediumorchid; } .function{ color: teal; } .var { color: magenta; } .dstring{ color: gold; } .op{ color: red; } .option{ color: darkcyan; font-style: oblique; } .optname{ color: purple; font-style: oblique; } .dnum { color: gold} .type { color: lime; } .null { color: chocolate; } .if { color: white; } .include { font-style: oblique; color: cornflowerblue; }&lt;/style&gt;&lt;br /&gt;last time i demonstrated how to read xml data from a file, looking at the xml support in a few scripting languages. so that we might round out this discussion i will now show how to do the exact same thing with the exact same data using a handful of compiled languages. refer to my &lt;a href="http://goo.gl/opbp"&gt;previous post&lt;/a&gt; to get the xml file and view what the program output should be.&lt;br /&gt;&lt;br /&gt;the first language we'll look at is the one of the three that i am least familiar with: c#. despite the fact that i've never used the language outside the classroom and never written a line of &amp;ldquo;real&amp;rdquo; production code with it, this was the easiest to use. c# reads and writes much like the scripting languages we looked at last time.&lt;br /&gt;&lt;br /&gt;&lt;pre id="cscode"&gt;&lt;br /&gt;1  &lt;span class="dcomment"&gt;// xmlsearch.cs&lt;/span&gt;&lt;br /&gt;2&lt;br /&gt;3  &lt;span class="dcomment"&gt;// Demonstrates how to parse data in an XML file using C-sharp's XPath&lt;/span&gt;&lt;br /&gt;4  &lt;span class="dcomment"&gt;// implementation. The file is a collection of books, tech_books.xml.&lt;/span&gt;&lt;br /&gt;5&lt;br /&gt;6  &lt;span class="dkeyword"&gt;using&lt;/span&gt; System;&lt;br /&gt;7  &lt;span class="dkeyword"&gt;using&lt;/span&gt; System.Xml;&lt;br /&gt;8&lt;br /&gt;9&lt;br /&gt;10 &lt;span class="dkeyword"&gt;class&lt;/span&gt; XmlSearch {&lt;br /&gt;11    &lt;br /&gt;12     &lt;span class="dkeyword"&gt;static&lt;/span&gt; void Main(&lt;span class="type"&gt;string&lt;/span&gt;[] args) {&lt;br /&gt;13         String separator = &lt;span class="dstring"&gt;"- - - - - - - - - - - - - - - - - - - - - - - - -"&lt;/span&gt;;&lt;br /&gt;14         XmlDocument tree = new XmlDocument();&lt;br /&gt;15         tree.Load(&lt;span class="dstring"&gt;"tech_books.xml"&lt;/span&gt;);&lt;br /&gt;16        &lt;br /&gt;17         &lt;span class="dcomment"&gt;// List all the books by title and author from the XML data.&lt;/span&gt;&lt;br /&gt;18         XmlNodeList books = tree.SelectNodes(&lt;span class="dstring"&gt;"//publisher//book"&lt;/span&gt;);&lt;br /&gt;19         &lt;span class="dkeyword"&gt;foreach&lt;/span&gt;(XmlNode book &lt;span class="dkeyword"&gt;in&lt;/span&gt; books) {&lt;br /&gt;20             Console.WriteLine(&lt;span class="dstring"&gt;"Title: {0}"&lt;/span&gt;, &lt;br /&gt;21                 book.SelectSingleNode(&lt;span class="dstring"&gt;"title"&lt;/span&gt;).InnerText);&lt;br /&gt;22             &lt;span class="if"&gt;if&lt;/span&gt;(book.SelectSingleNode(&lt;span class="dstring"&gt;"subtitle"&lt;/span&gt;) != &lt;span class="null"&gt;null&lt;/span&gt;) {&lt;br /&gt;23                 Console.WriteLine(&lt;span class="dstring"&gt;"Subtitle: {0}"&lt;/span&gt;,&lt;br /&gt;24                     book.SelectSingleNode(&lt;span class="dstring"&gt;"subtitle"&lt;/span&gt;).InnerText);&lt;br /&gt;25             }&lt;br /&gt;26             &lt;span class="dkeyword"&gt;foreach&lt;/span&gt;(XmlNode author &lt;span class="dkeyword"&gt;in&lt;/span&gt; book.SelectNodes(&lt;span class="dstring"&gt;"author"&lt;/span&gt;)){&lt;br /&gt;27                 Console.WriteLine(&lt;span class="dstring"&gt;"Author: {0}"&lt;/span&gt;, author.InnerText);&lt;br /&gt;28             }&lt;br /&gt;29             Console.WriteLine(separator);&lt;br /&gt;30         }&lt;br /&gt;31        &lt;br /&gt;32         &lt;span class="dcomment"&gt;// Get the ISBN and publisher for a book called "Writing Solid Code."&lt;/span&gt;&lt;br /&gt;33         Console.WriteLine(separator);&lt;br /&gt;34         String search = &lt;span class="dstring"&gt;"Writing Solid Code"&lt;/span&gt;;&lt;br /&gt;35         &lt;span class="dkeyword"&gt;foreach&lt;/span&gt;(XmlNode book &lt;span class="dkeyword"&gt;in&lt;/span&gt; books) {&lt;br /&gt;36             &lt;span class="if"&gt;if&lt;/span&gt;(book.SelectSingleNode(&lt;span class="dstring"&gt;"title"&lt;/span&gt;).InnerText == search) {&lt;br /&gt;37                 Console.WriteLine(&lt;span class="dstring"&gt;"{0} [{1}] published by {2}"&lt;/span&gt;, search,&lt;br /&gt;38                     book.SelectSingleNode(&lt;span class="dstring"&gt;"isbn"&lt;/span&gt;).InnerText,&lt;br /&gt;39                     book.ParentNode.Attributes[&lt;span class="dstring"&gt;"name"&lt;/span&gt;].Value);&lt;br /&gt;40             }&lt;br /&gt;41         }&lt;br /&gt;42         Console.WriteLine(separator);&lt;br /&gt;43     }   &lt;span class="dcomment"&gt;// end method Main&lt;/span&gt;&lt;br /&gt;44    &lt;br /&gt;45 }   &lt;span class="dcomment"&gt;// end class XmlSearch&lt;/span&gt;&lt;br /&gt;46&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;the next example is in java. while i have worked with java, i've never had to make it read xml before. i was a little disappointed. with factory classes and old-fashioned for loops it's more like c than c#.&lt;br /&gt;&lt;br /&gt;&lt;pre id="cscode"&gt;&lt;br /&gt;1  &lt;span class="dcomment"&gt;/* XmlSearch.java&lt;/span&gt;&lt;br /&gt;2  &lt;span class="dcomment"&gt;**&lt;/span&gt;&lt;br /&gt;3  &lt;span class="dcomment"&gt;** Demonstrates how to parse data in an XML file using Java's XPath API.&lt;/span&gt;&lt;br /&gt;4  &lt;span class="dcomment"&gt;** The file is a collection of books, tech_books.xml.&lt;/span&gt;&lt;br /&gt;5  &lt;span class="dcomment"&gt;*/&lt;/span&gt;&lt;br /&gt;6&lt;br /&gt;7  &lt;span class="dkeyword"&gt;import&lt;/span&gt; javax.xml.parsers.*;&lt;br /&gt;8  &lt;span class="dkeyword"&gt;import&lt;/span&gt; javax.xml.xpath.*;&lt;br /&gt;9  &lt;span class="dkeyword"&gt;import&lt;/span&gt; org.w3c.dom.*;&lt;br /&gt;10&lt;br /&gt;11&lt;br /&gt;12 &lt;span class="dkeyword"&gt;public class&lt;/span&gt; XmlSearch {&lt;br /&gt;13    &lt;br /&gt;14     &lt;span class="dkeyword"&gt;public static&lt;/span&gt; void main(String[] args) &lt;br /&gt;15         &lt;span class="dkeyword"&gt;throws&lt;/span&gt; ParserConfigurationException, XPathExpressionException,&lt;br /&gt;16             org.xml.sax.SAXException, java.io.IOException {&lt;br /&gt;17                &lt;br /&gt;18         String separator = &lt;span class="dstring"&gt;"- - - - - - - - - - - - - - - - - - - - - - - - -"&lt;/span&gt;;&lt;br /&gt;19         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();&lt;br /&gt;20         Document tree = factory.newDocumentBuilder().parse(&lt;span class="dstring"&gt;"tech_books.xml"&lt;/span&gt;);&lt;br /&gt;21         XPath xp = XPathFactory.newInstance().newXPath();&lt;br /&gt;22        &lt;br /&gt;23         &lt;span class="dcomment"&gt;// List all the books by title and author from the XML data.&lt;/span&gt;&lt;br /&gt;24         NodeList books = (NodeList)xp.evaluate(&lt;span class="dstring"&gt;"//publisher//book"&lt;/span&gt;, tree, &lt;br /&gt;25             XPathConstants.NODESET);&lt;br /&gt;26         &lt;span class="dkeyword"&gt;for&lt;/span&gt;(int i = &lt;span class="dnum"&gt;0&lt;/span&gt;; i &lt; books.getLength(); i++) {&lt;br /&gt;27             Node book = books.item(i);&lt;br /&gt;28             System.out.printf(&lt;span class="dstring"&gt;"Title: %s\n"&lt;/span&gt;,&lt;br /&gt;29                 xp.evaluate("title", book, XPathConstants.STRING));&lt;br /&gt;30             &lt;span class="if"&gt;if&lt;/span&gt;((xp.evaluate(&lt;span class="dstring"&gt;"subtitle"&lt;/span&gt;, book, XPathConstants.NODE)) != &lt;span class="null"&gt;null&lt;/span&gt;) {&lt;br /&gt;31                 System.out.printf(&lt;span class="dstring"&gt;"Subtitle: %s\n"&lt;/span&gt;,&lt;br /&gt;32                     xp.evaluate(&lt;span class="dstring"&gt;"subtitle"&lt;/span&gt;, book, XPathConstants.STRING));&lt;br /&gt;33             }&lt;br /&gt;34             NodeList authors = (NodeList)xp.evaluate(&lt;span class="dstring"&gt;"author"&lt;/span&gt;, book,&lt;br /&gt;35                 XPathConstants.NODESET);&lt;br /&gt;36             &lt;span class="dkeyword"&gt;for&lt;/span&gt;(&lt;span class="type"&gt;int&lt;/span&gt; j = &lt;span class="dnum"&gt;0&lt;/span&gt;; j &lt; authors.getLength(); j++) {&lt;br /&gt;37                 System.out.printf(&lt;span class="dstring"&gt;"Author: %s\n"&lt;/span&gt;, &lt;br /&gt;38                     authors.item(j).getTextContent());&lt;br /&gt;39             }&lt;br /&gt;40             System.out.println(separator);&lt;br /&gt;41         }&lt;br /&gt;42        &lt;br /&gt;43         &lt;span class="dcomment"&gt;// Get the ISBN and publisher for a book called "Writing Solid Code."&lt;/span&gt;&lt;br /&gt;44         System.out.println(separator);&lt;br /&gt;45         String search = &lt;span class="dstring"&gt;"Writing Solid Code"&lt;/span&gt;;&lt;br /&gt;46         &lt;span class="dkeyword"&gt;for&lt;/span&gt;(&lt;span class="type"&gt;int&lt;/span&gt; i = &lt;span class="dnum"&gt;0&lt;/span&gt;; i &lt; books.getLength(); i++) {&lt;br /&gt;47             Node book = books.item(i);&lt;br /&gt;48             &lt;span class="if"&gt;if&lt;/span&gt;(search.equals(&lt;br /&gt;49                 xp.evaluate(&lt;span class="dstring"&gt;"title"&lt;/span&gt;, book, XPathConstants.STRING))) {&lt;br /&gt;50                 System.out.printf(&lt;span class="dstring"&gt;"%s [%s] published by %s\n"&lt;/span&gt;, search,&lt;br /&gt;51                     xp.evaluate(&lt;span class="dstring"&gt;"isbn"&lt;/span&gt;, book, XPathConstants.STRING),&lt;br /&gt;52                     ((Element)book.getParentNode()).getAttribute(&lt;span class="dstring"&gt;"name"&lt;/span&gt;));&lt;br /&gt;53             }&lt;br /&gt;54         }&lt;br /&gt;55         System.out.println(separator);&lt;br /&gt;56     }   &lt;span class="dcomment"&gt;// end method main&lt;/span&gt;&lt;br /&gt;57    &lt;br /&gt;58 }   &lt;span class="dcomment"&gt;// end class XmlSearch&lt;/span&gt;&lt;br /&gt;59&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;for the sake of completeness, here is the code to do the same thing in c. i'm using libxml2 for its xdom and xpath capabilities. since this is a short example, i have simplified it by excluding all pointer and memory management. &lt;em&gt;don't ever do that in real life.&lt;/em&gt; be sure to clean up after yourself: your parent object doesn't work here.&lt;br /&gt;&lt;!-- &lt;br /&gt;-------------------------------------- c example --------------------------------------------------&gt;&lt;br /&gt;&lt;pre id="cscode"&gt;&lt;br /&gt;1  &lt;span class="dcomment"&gt;/* xmlsearch.c&lt;/span&gt;&lt;br /&gt;2   &lt;span class="dcomment"&gt;*&lt;/span&gt; &lt;br /&gt;3   &lt;span class="dcomment"&gt;* Demonstrates how to parse data in an XML file using LIBXML2 and XPath in C.&lt;/span&gt;&lt;br /&gt;4   &lt;span class="dcomment"&gt;* The file is a collection of books, tech_books.xml.&lt;/span&gt;&lt;br /&gt;5   &lt;span class="dcomment"&gt;*/&lt;/span&gt;&lt;br /&gt;6&lt;br /&gt;7  &lt;span class="include"&gt;#include &amp;lt;stdio.h&gt;&lt;/span&gt;&lt;br /&gt;8  &lt;span class="include"&gt;#include &amp;lt;stdlib.h&gt;&lt;/span&gt;&lt;br /&gt;9  &lt;span class="include"&gt;#include &amp;lt;libxml/parser.h&gt;&lt;/span&gt;&lt;br /&gt;10 &lt;span class="include"&gt;#include &amp;lt;libxml/xpath.h&gt;&lt;/span&gt;&lt;br /&gt;11&lt;br /&gt;12&lt;br /&gt;13 &lt;span class="type"&gt;int&lt;/span&gt; main(&lt;span class="type"&gt;int&lt;/span&gt; argc, &lt;span class="type"&gt;char&lt;/span&gt; **argv) {&lt;br /&gt;14     xmlDocPtr doc;&lt;br /&gt;15     xmlXPathContextPtr tree;&lt;br /&gt;16     xmlXPathObjectPtr result;&lt;br /&gt;17     xmlNodeSetPtr nodeList;&lt;br /&gt;18     xmlNodePtr book, cursor;&lt;br /&gt;19     xmlChar *title, *subtitle, *author, *search, *isbn, *publisher;&lt;br /&gt;20     &lt;span class="type"&gt;char&lt;/span&gt; *separator = &lt;span class="dstring"&gt;"- - - - - - - - - - - - - - - - - - - - - - - - -";&lt;/span&gt;&lt;br /&gt;21     &lt;span class="type"&gt;int&lt;/span&gt; found = &lt;span class="dnum"&gt;0&lt;/span&gt;;&lt;br /&gt;22     &lt;br /&gt;23     doc = xmlParseFile(&lt;span class="dstring"&gt;"tech_books.xml"&lt;/span&gt;);&lt;br /&gt;24     tree = xmlXPathNewContext(doc);&lt;br /&gt;25     result = xmlXPathEvalExpression((xmlChar *)&lt;span class="dstring"&gt;"//publisher//book"&lt;/span&gt;, tree);&lt;br /&gt;26     nodeList = result-&gt;nodesetval;&lt;br /&gt;27     &lt;br /&gt;28     &lt;span class="dcomment"&gt;// List all the books by title and author from the XML data.&lt;/span&gt;&lt;br /&gt;29     &lt;span class="dkeyword"&gt;for&lt;/span&gt;(&lt;span class="type"&gt;int&lt;/span&gt; i = &lt;span class="dnum"&gt;0&lt;/span&gt;; i &lt; nodeList-&gt;nodeNr; i++) {&lt;br /&gt;30         book = nodeList-&gt;nodeTab[i];&lt;br /&gt;31         cursor = book-&gt;xmlChildrenNode;&lt;br /&gt;32         &lt;span class="dkeyword"&gt;while&lt;/span&gt;(cursor != &lt;span class="null"&gt;NULL&lt;/span&gt;) {&lt;br /&gt;33             &lt;span class="if"&gt;if&lt;/span&gt;((!xmlStrcmp(cursor-&gt;name, (xmlChar *)&lt;span class="dstring"&gt;"title"&lt;/span&gt;))) {&lt;br /&gt;34                 title = xmlNodeListGetString(doc, cursor-&gt;xmlChildrenNode, &lt;span class="dnum"&gt;1&lt;/span&gt;);&lt;br /&gt;35                 printf(&lt;span class="dstring"&gt;"Title: %s\n"&lt;/span&gt;, title);&lt;br /&gt;36             }&lt;br /&gt;37             &lt;span class="if"&gt;if&lt;/span&gt;((!xmlStrcmp(cursor-&gt;name, (xmlChar *)&lt;span class="dstring"&gt;"subtitle"&lt;/span&gt;))) {&lt;br /&gt;38                 subtitle = xmlNodeListGetString(doc,&lt;br /&gt;39                     cursor-&gt;xmlChildrenNode, &lt;span class="dnum"&gt;1&lt;/span&gt;);&lt;br /&gt;40                 printf(&lt;span class="dstring"&gt;"Subtitle: %s\n"&lt;/span&gt;, subtitle);&lt;br /&gt;41             }&lt;br /&gt;42             &lt;span class="if"&gt;if&lt;/span&gt;((!xmlStrcmp(cursor-&gt;name, (xmlChar *)&lt;span class="dstring"&gt;"author"&lt;/span&gt;))) {&lt;br /&gt;43                 author = xmlNodeListGetString(doc, cursor-&gt;xmlChildrenNode, &lt;span class="dnum"&gt;1&lt;/span&gt;);&lt;br /&gt;44                 printf(&lt;span class="dstring"&gt;"Author: %s\n"&lt;/span&gt;, author);&lt;br /&gt;45             }&lt;br /&gt;46             cursor = cursor-&gt;next;&lt;br /&gt;47         }&lt;br /&gt;48         puts(separator);&lt;br /&gt;49     }&lt;br /&gt;50     &lt;br /&gt;51     &lt;span class="dcomment"&gt;// Get the ISBN and publisher for a book called "Writing Solid Code."&lt;/span&gt;&lt;br /&gt;52     puts(separator);&lt;br /&gt;53     search = (xmlChar *)&lt;span class="dstring"&gt;"Writing Solid Code"&lt;/span&gt;;&lt;br /&gt;54     result = xmlXPathEvalExpression((xmlChar *)&lt;span class="dstring"&gt;"//publisher"&lt;/span&gt;, tree);&lt;br /&gt;55     nodeList = result-&gt;nodesetval;&lt;br /&gt;56     &lt;br /&gt;57     &lt;span class="dkeyword"&gt;for&lt;/span&gt;(&lt;span class="type"&gt;int&lt;/span&gt; i = &lt;span class="dnum"&gt;0&lt;/span&gt;; i &lt; nodeList-&gt;nodeNr; i++) {&lt;br /&gt;58         cursor = nodeList-&gt;nodeTab[i];&lt;br /&gt;59         publisher = xmlGetProp(cursor, (xmlChar *)&lt;span class="dstring"&gt;"name"&lt;/span&gt;);&lt;br /&gt;60         book = cursor-&gt;xmlChildrenNode;&lt;br /&gt;61         book = book-&gt;next;&lt;br /&gt;62         &lt;span class="dkeyword"&gt;while&lt;/span&gt;(book != &lt;span class="null"&gt;NULL&lt;/span&gt;) {&lt;br /&gt;63             cursor = book-&gt;xmlChildrenNode;&lt;br /&gt;64&lt;br /&gt;65             &lt;span class="dkeyword"&gt;while&lt;/span&gt;(cursor != &lt;span class="null"&gt;NULL&lt;/span&gt;) {&lt;br /&gt;66                 &lt;span class="if"&gt;if&lt;/span&gt;((!xmlStrcmp(cursor-&gt;name, (xmlChar *)&lt;span class="dstring"&gt;"title"&lt;/span&gt;))) {&lt;br /&gt;67                     title = xmlNodeListGetString(doc, &lt;br /&gt;68                         cursor-&gt;xmlChildrenNode, &lt;span class="dnum"&gt;1&lt;/span&gt;);&lt;br /&gt;69                 }&lt;br /&gt;70                 &lt;span class="if"&gt;if&lt;/span&gt;((!xmlStrcmp(cursor-&gt;name, (xmlChar *)&lt;span class="dstring"&gt;"isbn"&lt;/span&gt;))) {&lt;br /&gt;71                     isbn = xmlNodeListGetString(doc, &lt;br /&gt;72                         cursor-&gt;xmlChildrenNode, &lt;span class="dnum"&gt;1&lt;/span&gt;);&lt;br /&gt;73                 }&lt;br /&gt;74                 cursor = cursor-&gt;next;&lt;br /&gt;75             }&lt;br /&gt;76             &lt;span class="if"&gt;if&lt;/span&gt;((!xmlStrcmp(title, search))) {&lt;br /&gt;77                 found = &lt;span class="dnum"&gt;1&lt;/span&gt;;&lt;br /&gt;78                 &lt;span class="dkeyword"&gt;break&lt;/span&gt;;&lt;br /&gt;79             }&lt;br /&gt;80             book = book-&gt;next;&lt;br /&gt;81         }&lt;br /&gt;82         &lt;span class="if"&gt;if&lt;/span&gt;(found) {&lt;br /&gt;83             printf(&lt;span class="dstring"&gt;"%s [%s] published by %s\n"&lt;/span&gt;, title, isbn, publisher);&lt;br /&gt;84             &lt;span class="dkeyword"&gt;break&lt;/span&gt;;&lt;br /&gt;85         }&lt;br /&gt;86     }&lt;br /&gt;87     puts(separator);&lt;br /&gt;88     &lt;br /&gt;89     return &lt;span class="dnum"&gt;0&lt;/span&gt;;&lt;br /&gt;90 }   &lt;span class="dcomment"&gt;// end method main&lt;/span&gt;&lt;br /&gt;91&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5089178761965217498-4401830627208469204?l=mechatechzilla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mechatechzilla.blogspot.com/feeds/4401830627208469204/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mechatechzilla.blogspot.com/2010/07/xml-2-and-now-word-from-our-compilers.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/4401830627208469204'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/4401830627208469204'/><link rel='alternate' type='text/html' href='http://mechatechzilla.blogspot.com/2010/07/xml-2-and-now-word-from-our-compilers.html' title='xml 2: and now, a word from our compilers...'/><author><name>mechatechzilla</name><uri>http://www.blogger.com/profile/17585447008783853422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://1.bp.blogspot.com/_jbCdMAhJU58/SpM-dMKvHKI/AAAAAAAABCw/fJGkIdcMqCE/S220/red_shirt.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5089178761965217498.post-4337530983926249964</id><published>2010-07-25T23:48:00.011-05:00</published><updated>2010-07-25T23:48:00.598-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='powershell'/><category scheme='http://www.blogger.com/atom/ns#' term='xml'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='scripting'/><title type='text'>reading xml 1: powershell, python and ruby, oh my!</title><content type='html'>&lt;style&gt;#pscode{ font-weight: bold; background-color: palegoldenrod; color: black; padding: 1em; width: 51em; } #command{ font-weight: bold; background-color: navy; color: silver; padding: 1em; width: 51em;} .comment{ color: darkgreen;} .keyword{ color: navy; } .function{ color: teal; } .var { color: magenta; } .string{ color: maroon; } .op{ color: red; } .option{ color: darkcyan; font-style: oblique; } .optname{ color: purple; font-style: oblique; } .num {color: purple}&lt;/style&gt;&lt;br /&gt;i was working on a little project that required me to read an xml file from the internet. since i like to have some useful examples to refer to when i'm doing something that i don't often do (and so don't remember how to) i decided to dig into the three scripting languages that i'm most likely to use and learn how to work with xml data.&lt;br/&gt;&lt;br /&gt;you can grab the sample xml file here: &lt;a href="http://ritterhaus.public.s3.amazonaws.com/tech_books.xml"&gt;tech_books.xml&lt;/a&gt;. i recommend that you look it over so you can see what the scripts are doing. we'll be writing scripts to list all the book titles and authors, then search for a specific title and fetch its isbn and its parent publisher's &lt;i&gt;name&lt;/i&gt; attribute. all three should provide the same output, which you can see below:&lt;br /&gt;&lt;pre style="font-size: smaller;"&gt;&lt;br /&gt;Title: The Revolutionary Guide to Assembly Language&lt;br /&gt;Author: Vitaly Maljugin&lt;br /&gt;Author: Jacov Izrailevich&lt;br /&gt;Author: A. Sopin&lt;br /&gt;Author: S. Lavin&lt;br /&gt;- - - - - - - - - - - - - - - - - - - - - - - - - &lt;br /&gt;Title: Writing Solid Code&lt;br /&gt;Subtitle: Microsoft's Techniques for Developing Bug-Free C Programs&lt;br /&gt;Author: Steve Maguire&lt;br /&gt;- - - - - - - - - - - - - - - - - - - - - - - - - &lt;br /&gt;Title: Windows PowerShell Scripting Guide&lt;br /&gt;Subtitle: Automating Administration of Windows Vista and Windows Server 2008&lt;br /&gt;Author: Ed Wilson&lt;br /&gt;- - - - - - - - - - - - - - - - - - - - - - - - - &lt;br /&gt;Title: Practical C Programming&lt;br /&gt;Author: Steve Oualline&lt;br /&gt;- - - - - - - - - - - - - - - - - - - - - - - - - &lt;br /&gt;Title: Programming Python&lt;br /&gt;Author: Mark Lutz&lt;br /&gt;- - - - - - - - - - - - - - - - - - - - - - - - - &lt;br /&gt;Title: The Ruby Way, Second Edition&lt;br /&gt;Author: Hal Fulton&lt;br /&gt;- - - - - - - - - - - - - - - - - - - - - - - - - &lt;br /&gt;Title: LaTeX: A Document Preparation System&lt;br /&gt;Author: Leslie Lamport&lt;br /&gt;- - - - - - - - - - - - - - - - - - - - - - - - - &lt;br /&gt;- - - - - - - - - - - - - - - - - - - - - - - - - &lt;br /&gt;Writing Solid Code [ISBN 1-556-15551-4] published by Microsoft Press&lt;br /&gt;- - - - - - - - - - - - - - - - - - - - - - - - - &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;the first language i turned to is python, an old friend of mine. reading through the xml document object model api made my head swim, but with a little research i came across what used to be a third-party module, elementtree, that has now been incorporated into the core python installation. (this is one of the reasons that i love open source software.)&lt;br/&gt;&lt;br /&gt;elementtree uses &lt;i&gt;parent&lt;/i&gt;.findall(&lt;i&gt;child&lt;/i&gt;) to fetch an array of all nodes of type &lt;i&gt;child&lt;/i&gt; under &lt;i&gt;parent&lt;/i&gt;. the &lt;i&gt;parent&lt;/i&gt;.find(&lt;i&gt;child&lt;/i&gt;) method returns only a single element object. &lt;i&gt;parent&lt;/i&gt;.findtext(&lt;i&gt;child&lt;/i&gt;) returns the child node data. it is similar to &lt;i&gt;parent&lt;/i&gt;.find(&lt;i&gt;child&lt;/i&gt;).text: the former returns an empty string if the element is not found, the latter raises an exception. &lt;i&gt;element&lt;/i&gt;.get(&lt;i&gt;attribute&lt;/i&gt;) returns a node's attribute value.&lt;br /&gt;&lt;br /&gt;&lt;pre id="pscode"&gt;&lt;br /&gt;1  &lt;span class="comment"&gt;# xmlsearch.py&lt;/span&gt;&lt;br /&gt;2&lt;br /&gt;3  &lt;span class="keyword"&gt;import&lt;/span&gt; &lt;span class="function"&gt;xml.etree.ElementTree&lt;/span&gt;&lt;br /&gt;4&lt;br /&gt;5&lt;br /&gt;6  tree &lt;span class="op"&gt;=&lt;/span&gt; xml.etree.ElementTree.ElementTree()&lt;br /&gt;7  tree.parse(&lt;span class="string"&gt;'tech_books.xml'&lt;/span&gt;)&lt;br /&gt;8&lt;br /&gt;9  &lt;span class="comment"&gt;# List all the books by title and author from the XML data.&lt;/span&gt;&lt;br /&gt;10 books &lt;span class="op"&gt;=&lt;/span&gt; tree.findall(&lt;span class="string"&gt;'publisher/book'&lt;/span&gt;)&lt;br /&gt;11 &lt;span class="keyword"&gt;for&lt;/span&gt; book &lt;span class="keyword"&gt;in&lt;/span&gt; books:&lt;br /&gt;12     &lt;span class="keyword"&gt;print&lt;/span&gt; &lt;span class="string"&gt;"Title: %s"&lt;/span&gt; &lt;span class="op"&gt;%&lt;/span&gt; book.findtext(&lt;span class="string"&gt;'title'&lt;/span&gt;)&lt;br /&gt;13    &lt;span class="keyword"&gt;if&lt;/span&gt; book.findtext(&lt;span class="string"&gt;'subtitle'&lt;/span&gt;):&lt;br /&gt;14        &lt;span class="keyword"&gt;print&lt;/span&gt; &lt;span class="string"&gt;"Subtitle: %s"&lt;/span&gt; &lt;span class="op"&gt;%&lt;/span&gt; book.findtext(&lt;span class="string"&gt;'subtitle'&lt;/span&gt;)&lt;br /&gt;15    authors &lt;span class="op"&gt;=&lt;/span&gt; book.findall(&lt;span class="string"&gt;'author'&lt;/span&gt;)&lt;br /&gt;16    &lt;span class="keyword"&gt;for&lt;/span&gt; author &lt;span class="keyword"&gt;in&lt;/span&gt; authors:&lt;br /&gt;17        &lt;span class="keyword"&gt;print&lt;/span&gt; &lt;span class="string"&gt;"Author: %s"&lt;/span&gt; &lt;span class="op"&gt;%&lt;/span&gt; author.text&lt;br /&gt;18    &lt;span class="keyword"&gt;print&lt;/span&gt; &lt;span class="string"&gt;'- '&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="num"&gt;25&lt;/span&gt;&lt;br /&gt;19  &lt;br /&gt;20 &lt;span class="comment"&gt;# Get the ISBN and publisher for a book called "Writing Solid Code."&lt;/span&gt;&lt;br /&gt;21 &lt;span class="keyword"&gt;print&lt;/span&gt; &lt;span class="string"&gt;'- '&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="num"&gt;25&lt;/span&gt;&lt;br /&gt;22 search &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="string"&gt;'Writing Solid Code'&lt;/span&gt;&lt;br /&gt;23 publishers &lt;span class="op"&gt;=&lt;/span&gt; tree.findall(&lt;span class="string"&gt;'publisher'&lt;/span&gt;)&lt;br /&gt;24 &lt;span class="keyword"&gt;for&lt;/span&gt; publisher &lt;span class="keyword"&gt;in&lt;/span&gt; publishers:&lt;br /&gt;25     books &lt;span class="keyword"&gt;=&lt;/span&gt; publisher.findall(&lt;span class="string"&gt;'book'&lt;/span&gt;)&lt;br /&gt;26     &lt;span class="keyword"&gt;for&lt;/span&gt; book &lt;span class="keyword"&gt;in&lt;/span&gt; books:&lt;br /&gt;27         &lt;span class="keyword"&gt;if&lt;/span&gt; book.findtext(&lt;span class="string"&gt;'title'&lt;/span&gt;) &lt;span class="op"&gt;==&lt;/span&gt; search:&lt;br /&gt;28             &lt;span class="keyword"&gt;print&lt;/span&gt; &lt;span class="string"&gt;"%s [ISBN %s] published by %s"&lt;/span&gt; &lt;span class="op"&gt;%&lt;/span&gt; (search, &lt;br /&gt;29                 book.findtext(&lt;span class="string"&gt;'isbn'&lt;/span&gt;), publisher.get(&lt;span class="string"&gt;'name'&lt;/span&gt;))&lt;br /&gt;30 &lt;span class="keyword"&gt;print&lt;/span&gt; &lt;span class="string"&gt;'- '&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="num"&gt;25&lt;/span&gt;&lt;br /&gt;31&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;next i investigated xml under powershell. i was certain that it would be no more difficult than python, and what i found was that basic xml searches worked in a very similar way.&lt;br/&gt;&lt;br /&gt;powershell has xml processing built-in, so no modules have to be included in the source file to make it work. it uses &lt;i&gt;parent&lt;/i&gt;.SelectNodes(&lt;i&gt;child&lt;/i&gt;) to get an array of all nodes called &lt;i&gt;child&lt;/i&gt; under the node &lt;i&gt;parent&lt;/i&gt;. the &lt;i&gt;parent&lt;/i&gt;.SelectNode(&lt;i&gt;child&lt;/i&gt;) method returns only the first node &lt;i&gt;child&lt;/i&gt; that is found under &lt;i&gt;parent&lt;/i&gt;. note the plural &lt;i&gt;SelectNodes&lt;/i&gt; and singular &lt;i&gt;SelectNode&lt;/i&gt;. &lt;i&gt;element&lt;/i&gt;.GetAttribute(&lt;i&gt;attribute&lt;/i&gt;) returns a node's attribute value.&lt;br /&gt;&lt;br /&gt;&lt;pre id="pscode"&gt;&lt;br /&gt;1  &lt;span class="comment"&gt;# xmlsearch.ps1&lt;/span&gt;&lt;br /&gt;2&lt;br /&gt;3  [&lt;span class="function"&gt;xml&lt;/span&gt;] &lt;span class="var"&gt;$tree&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="function"&gt;Get-Content&lt;/span&gt; tech_books.xml&lt;br /&gt;4&lt;br /&gt;5  &lt;span class="comment"&gt;# List all the books by title and author from the XML data.&lt;/span&gt;&lt;br /&gt;6  &lt;span class="var"&gt;$books&lt;/span&gt; = &lt;span class="var"&gt;$tree&lt;/span&gt;.SelectNodes(&lt;span class="string"&gt;'//publisher//book'&lt;/span&gt;)&lt;br /&gt;7  &lt;span class="keyword"&gt;foreach&lt;/span&gt; (&lt;span class="var"&gt;$book&lt;/span&gt; &lt;span class="keyword"&gt;in&lt;/span&gt; &lt;span class="var"&gt;$books&lt;/span&gt;) {&lt;br /&gt;8      &lt;span class="string"&gt;"Title: {0}"&lt;/span&gt; &lt;span class="op"&gt;-f&lt;/span&gt; &lt;span class="var"&gt;$book&lt;/span&gt;.title&lt;br /&gt;9      &lt;span class="keyword"&gt;if&lt;/span&gt; (&lt;span class="var"&gt;$book&lt;/span&gt;.subtitle) {&lt;br /&gt;10         &lt;span class="string"&gt;"Subtitle: {0}"&lt;/span&gt; &lt;span class="op"&gt;-f&lt;/span&gt; &lt;span class="var"&gt;$book&lt;/span&gt;.subtitle&lt;br /&gt;11     }&lt;br /&gt;12     &lt;span class="var"&gt;$authors&lt;/span&gt; = &lt;span class="var"&gt;$book&lt;/span&gt;.SelectNodes(&lt;span class="string"&gt;'author'&lt;/span&gt;)&lt;br /&gt;13     &lt;span class="keyword"&gt;foreach&lt;/span&gt; (&lt;span class="var"&gt;$author&lt;/span&gt; &lt;span class="keyword"&gt;in&lt;/span&gt; &lt;span class="var"&gt;$authors&lt;/span&gt;) {&lt;br /&gt;14         &lt;span class="string"&gt;"Author: {0}"&lt;/span&gt; &lt;span class="op"&gt;-f&lt;/span&gt; &lt;span class="var"&gt;$author&lt;/span&gt;.&lt;span class="string"&gt;'#text'&lt;/span&gt;&lt;br /&gt;15     }&lt;br /&gt;16     &lt;span class="string"&gt;'- '&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="num"&gt;25&lt;/span&gt;&lt;br /&gt;17 }&lt;br /&gt;18&lt;br /&gt;19 &lt;span class="comment"&gt;# Get the ISBN and publisher for a book called "Writing Solid Code."&lt;/span&gt;&lt;br /&gt;20 &lt;span class="string"&gt;'- '&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="num"&gt;25&lt;/span&gt;&lt;br /&gt;21 &lt;span class="var"&gt;$search&lt;/span&gt; = &lt;span class="string"&gt;'Writing Solid Code'&lt;/span&gt;&lt;br /&gt;22 &lt;span class="var"&gt;$publishers&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="var"&gt;$tree&lt;/span&gt;.SelectNodes(&lt;span class="string"&gt;'//publisher'&lt;/span&gt;)&lt;br /&gt;23 &lt;span class="keyword"&gt;foreach&lt;/span&gt; (&lt;span class="var"&gt;$publisher&lt;/span&gt; &lt;span class="keyword"&gt;in&lt;/span&gt; &lt;span class="var"&gt;$publishers&lt;/span&gt;) {&lt;br /&gt;24     &lt;span class="var"&gt;$books&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="var"&gt;$publisher&lt;/span&gt;.SelectNodes(&lt;span class="string"&gt;'book'&lt;/span&gt;)&lt;br /&gt;22     &lt;span class="keyword"&gt;foreach&lt;/span&gt; (&lt;span class="var"&gt;$book&lt;/span&gt; &lt;span class="keyword"&gt;in&lt;/span&gt; &lt;span class="var"&gt;$books&lt;/span&gt;) {&lt;br /&gt;23         &lt;span class="keyword"&gt;if&lt;/span&gt; (&lt;span class="var"&gt;$book&lt;/span&gt;.title &lt;span class="op"&gt;-eq&lt;/span&gt; &lt;span class="var"&gt;$search&lt;/span&gt;) {&lt;br /&gt;24             &lt;span class="string"&gt;"{0} [ISBN {1}] published by {2}"&lt;/span&gt; &lt;span class="op"&gt;-f&lt;/span&gt; &lt;span class="var"&gt;$search&lt;/span&gt;, &lt;span class="var"&gt;$book&lt;/span&gt;.isbn,&lt;br /&gt;25                 &lt;span class="var"&gt;$publisher&lt;/span&gt;.GetAttribute(&lt;span class="string"&gt;'name'&lt;/span&gt;)&lt;br /&gt;26         }&lt;br /&gt;25     }&lt;br /&gt;26 }&lt;br /&gt;27 &lt;span class="string"&gt;'- '&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="num"&gt;25&lt;/span&gt;&lt;br /&gt;28&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;finally i dusted off ruby, a language that i haven't really touched in more than a year, to see what it would do. again, i wasn't impressed with the general xml documentation, but google searches led me to a ruby gem called nokogiri. i installed it and was very pleased with the result.&lt;br/&gt;&lt;br /&gt;nokogiri uses &lt;i&gt;parent&lt;/i&gt;.xpath(&lt;i&gt;child&lt;/i&gt;) to get an array of &lt;i&gt;child&lt;/i&gt; elements, &lt;i&gt;parent&lt;/i&gt;.at_xpath(&lt;i&gt;child&lt;/i&gt;) to get a single element, and &lt;i&gt;element&lt;/i&gt;.attr(&lt;i&gt;attribute&lt;/i&gt;) to get a node's attribute value. one nifty property lacking in the other two languages is &lt;i&gt;element&lt;/i&gt;.parent, which returns the parent node of the current element. it saves us from having to define multiple &amp;ldquo;books&amp;rdquo; arrays in this example.&lt;br /&gt;&lt;br /&gt;&lt;pre id="pscode"&gt;&lt;br /&gt;1  &lt;span class="comment"&gt;# xmlsearch.rb&lt;/span&gt;&lt;br /&gt;2&lt;br /&gt;3  &lt;span class="keyword"&gt;require&lt;/span&gt; &lt;span class="string"&gt;'rubygems'&lt;/span&gt;&lt;br /&gt;4  &lt;span class="keyword"&gt;require&lt;/span&gt; &lt;span class="string"&gt;'nokogiri'&lt;/span&gt;&lt;br /&gt;5&lt;br /&gt;6&lt;br /&gt;7  tree &lt;span class="op"&gt;=&lt;/span&gt; Nokogiri.XML(open(&lt;span class="string"&gt;'tech_books.xml'&lt;/span&gt;))&lt;br /&gt;8&lt;br /&gt;9  &lt;span class="comment"&gt;# List all the books by title and author from the XML data.&lt;/span&gt;&lt;br /&gt;10 books &lt;span class="op"&gt;=&lt;/span&gt; tree.xpath(&lt;span class="string"&gt;'//publisher//book'&lt;/span&gt;)&lt;br /&gt;11 books.each &lt;span class="keyword"&gt;do&lt;/span&gt; |book|&lt;br /&gt;12   &lt;span class="keyword"&gt;puts&lt;/span&gt; &lt;span class="string"&gt;"Title: %s"&lt;/span&gt; &lt;span class="op"&gt;%&lt;/span&gt; book.at_xpath(&lt;span class="string"&gt;'title'&lt;/span&gt;).content&lt;br /&gt;13   &lt;span class="keyword"&gt;if&lt;/span&gt; book.at_xpath(&lt;span class="string"&gt;'subtitle'&lt;/span&gt;)&lt;br /&gt;14     &lt;span class="keyword"&gt;puts&lt;/span&gt; &lt;span class="string"&gt;"Subtitle: %s"&lt;/span&gt; &lt;span class="op"&gt;%&lt;/span&gt; book.at_xpath(&lt;span class="string"&gt;'subtitle'&lt;/span&gt;).content&lt;br /&gt;15   &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;br /&gt;16   authors &lt;span class="op"&gt;=&lt;/span&gt; book.xpath(&lt;span class="string"&gt;'author'&lt;/span&gt;)&lt;br /&gt;17   authors.each &lt;span class="keyword"&gt;do&lt;/span&gt; |author|&lt;br /&gt;18     &lt;span class="keyword"&gt;puts&lt;/span&gt; &lt;span class="string"&gt;"Author: %s"&lt;/span&gt; &lt;span class="op"&gt;%&lt;/span&gt; author.content&lt;br /&gt;19   &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;br /&gt;20   &lt;span class="keyword"&gt;puts&lt;/span&gt; &lt;span class="string"&gt;'- '&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="num"&gt;25&lt;/span&gt;&lt;br /&gt;21 &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;br /&gt;22&lt;br /&gt;23 &lt;span class="comment"&gt;# Get the ISBN and publisher for a book called "Writing Solid Code."&lt;/span&gt;&lt;br /&gt;24 &lt;span class="keyword"&gt;puts&lt;/span&gt; &lt;span class="string"&gt;'- '&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="num"&gt;25&lt;/span&gt;&lt;br /&gt;25 search &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="string"&gt;'Writing Solid Code'&lt;/span&gt;&lt;br /&gt;26 books.each &lt;span class="keyword"&gt;do&lt;/span&gt; |book|&lt;br /&gt;27   &lt;span class="keyword"&gt;if&lt;/span&gt; book.at_xpath(&lt;span class="string"&gt;'title'&lt;/span&gt;).content &lt;span class="op"&gt;==&lt;/span&gt; search&lt;br /&gt;28     &lt;span class="keyword"&gt;puts&lt;/span&gt; &lt;span class="string"&gt;"%s [ISBN %s] published by %s"&lt;/span&gt; &lt;span class="op"&gt;%&lt;/span&gt; [search, &lt;br /&gt;29       book.at_xpath(&lt;span class="string"&gt;'isbn'&lt;/span&gt;).content, book.parent.attr(&lt;span class="string"&gt;'name'&lt;/span&gt;)]&lt;br /&gt;29   &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;br /&gt;30 &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;br /&gt;31 &lt;span class="keyword"&gt;puts&lt;/span&gt; &lt;span class="string"&gt;'- '&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="num"&gt;25&lt;/span&gt;&lt;br /&gt;32&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;so after doing a little research i find that it's not really too difficult to read xml in my favorite scripting languages, and now i have some nice little examples to look at the next time i need a refresher. until next time.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5089178761965217498-4337530983926249964?l=mechatechzilla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mechatechzilla.blogspot.com/feeds/4337530983926249964/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mechatechzilla.blogspot.com/2010/07/reading-xml-1-powershell-python-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/4337530983926249964'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/4337530983926249964'/><link rel='alternate' type='text/html' href='http://mechatechzilla.blogspot.com/2010/07/reading-xml-1-powershell-python-and.html' title='reading xml 1: powershell, python and ruby, oh my!'/><author><name>mechatechzilla</name><uri>http://www.blogger.com/profile/17585447008783853422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://1.bp.blogspot.com/_jbCdMAhJU58/SpM-dMKvHKI/AAAAAAAABCw/fJGkIdcMqCE/S220/red_shirt.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5089178761965217498.post-9005236025968890469</id><published>2010-07-14T10:25:00.000-05:00</published><updated>2010-07-14T10:25:00.590-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='powershell'/><category scheme='http://www.blogger.com/atom/ns#' term='profile'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='scripting'/><title type='text'>powershell: my 3 favorite functions (2 of 2)</title><content type='html'>&lt;style&gt;#pscode{ font-weight: bold; background-color: palegoldenrod; color: black; padding: 1em; width: 51em; } #command{ font-weight: bold; background-color: navy; color: silver; padding: 1em; width: 51em;} .comment{ color: darkgreen;} .keyword{ color: navy; } .function{ color: teal; } .var { color: magenta; } .string{ color: maroon; } .op{ color: red; } .option{ color: darkcyan; font-style: oblique; } .optname{ color: purple; font-style: oblique; } .num {color: purple}&lt;/style&gt;&lt;br /&gt;you may have noticed that when you print a really, really long string in powershell, the text is wrapped at the edge of the console. if your screen is 80 characters wide, your string gets wrapped at 80 characters. you may also have noticed that this wrapping isn't very intelligent. your string will be wrapped at exactly 80 characters, even if that means that the line gets broken in the middle of a word. just look through the powershell help to see what i mean.&lt;br /&gt;&lt;br /&gt;&lt;em style="font-size:larger;font-weight:bold;color:orangered;"&gt;textwrap&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;python has a nifty little module called &lt;i&gt;textwrap&lt;/i&gt; that wraps a string the smart way. i don't know a lot about it&amp;mdash;i only use the parts i need. it is not my intent to re-write the python module for powershell, only to borrow the concept with my own textwrap function. the idea is to take a long string and a maximum width in characters and return a string formatted so that each line does not exceed the width. whole words should be preserved at the end of each line so that the text is readable. because this is a more complex function, we will build it incrementally and talk about it along the way.&lt;br /&gt;&lt;br /&gt;&lt;pre id="command"&gt;&lt;br /&gt;C:\&gt; function textwrap ($longstring, $width) {&lt;br /&gt;&gt;&gt;&gt;      $word_list = -split $longstring&lt;br /&gt;&gt;&gt;&gt;      $out_strings = @("")&lt;br /&gt;&gt;&gt;&gt;      $i = 0&lt;br /&gt;&gt;&gt;&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;the simple way to begin is to take the long string and convert into an array of words using the string &lt;i&gt;split()&lt;/i&gt; method or, if you're using powershell 2, the &lt;i&gt;split&lt;/i&gt; operator as i did here. we're going to convert the string to an array of strings, each no longer than the desired width. we'll store this in &lt;b&gt;$out_strings&lt;/b&gt;. notice we initialized the array with an empty string. that way we can write to &lt;b&gt;$out_strings[0]&lt;/b&gt; without getting errors about non-existent array elements. we'll start indexing our array at zero with our good buddy &lt;b&gt;$i&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;&lt;pre id="command"&gt;&lt;br /&gt;&gt;&gt;&gt;      foreach ($word in $word_list) {&lt;br /&gt;&gt;&gt;&gt;          if ($out_strings[$i].Length + $word.Length -gt $width) {&lt;br /&gt;&gt;&gt;&gt;              $i++&lt;br /&gt;&gt;&gt;&gt;              $out_strings += ""&lt;br /&gt;&gt;&gt;&gt;          }&lt;br /&gt;&gt;&gt;&gt;          $out_strings[$i] += $word&lt;br /&gt;&gt;&gt;&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;what we want to do is concatenate each word to the end of the string in our array as long as that wouldn't make the string longer than our maximum width. we use the &lt;i&gt;foreach&lt;/i&gt; loop to fetch each word from the list. in the loop we test to see if we can safely add the word to the end of the string in the first array element. once we've added as many words to the string as we can, we increment the array index and append a new empty string to the array. then we add the next word to the end of the new string.&lt;br /&gt;&lt;br /&gt;&lt;pre id="command"&gt;&lt;br /&gt;&gt;&gt;&gt;          if ($out_strings[$i].Length + 1 -le $width) {&lt;br /&gt;&gt;&gt;&gt;              $out_strings[$i] += " "&lt;br /&gt;&gt;&gt;&gt;          }&lt;br /&gt;&gt;&gt;&gt;      }&lt;br /&gt;&gt;&gt;&gt;      return ($out_strings -join "`n")&lt;br /&gt;&gt;&gt;&gt;  }&lt;br /&gt;&gt;&gt;&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;before we leave the &lt;i&gt;foreach&lt;/i&gt; loop we need to add a space to the end of the word we just concatenated onto our string. that is, as long as it doesn't put us above our width. the &lt;i&gt;if&lt;/i&gt; statement above adds a space if there is room to do so. finally, we return our array of strings as a single string with the &lt;i&gt;join&lt;/i&gt; operator. we separate them with a &lt;i&gt;newline&lt;/i&gt; character so that the new string prints on multiple lines. given a long string stored in &lt;b&gt;$ls&lt;/b&gt; a sample run of this function might look like this:&lt;br /&gt;&lt;br /&gt;&lt;pre id="command"&gt;&lt;br /&gt;C:\&gt; "-" * 25&lt;br /&gt;-------------------------&lt;br /&gt;C:\&gt; textwrap $ls 25&lt;br /&gt;This is a really long&lt;br /&gt;string. It is wrapped in&lt;br /&gt;a way that doesn't chop&lt;br /&gt;up words.&lt;br /&gt;C:\&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;the finished function appears below. i've added code so that it can even deal with hyphenated words and do the right thing. i'll let you examine that to see how it works. until next time.&lt;br /&gt;&lt;br /&gt;&lt;pre id="pscode"&gt;&lt;br /&gt;33&lt;br /&gt;34 &lt;span class="comment"&gt;# textwrap:&lt;/span&gt;&lt;br /&gt;35 &lt;span class="comment"&gt;#   expects a string and an int&lt;/span&gt;&lt;br /&gt;36 &lt;span class="comment"&gt;#   returns a string&lt;/span&gt;&lt;br /&gt;37 &lt;span class="comment"&gt;# Intelligently wraps a long string to a maximum width.&lt;/span&gt;&lt;br /&gt;38&lt;br /&gt;39 &lt;span class="keyword"&gt;function&lt;/span&gt; &lt;span class="function"&gt;textwrap&lt;/span&gt; (&lt;span class="var"&gt;$long_string&lt;/span&gt;, &lt;span class="var"&gt;$width&lt;/span&gt;) {&lt;br /&gt;40     &lt;span class="var"&gt;$word_list&lt;/span&gt; &lt;span class="op"&gt;= -split&lt;/span&gt; &lt;span class="var"&gt;$long_string&lt;/span&gt;&lt;br /&gt;41     &lt;span class="var"&gt;$out_strings&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; @(&lt;span class="string"&gt;""&lt;/span&gt;)&lt;br /&gt;42     &lt;span class="var"&gt;$i&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="num"&gt;0&lt;/span&gt;&lt;br /&gt;43 &lt;br /&gt;44     &lt;span class="keyword"&gt;foreach&lt;/span&gt; (&lt;span class="var"&gt;$word&lt;/span&gt; &lt;span class="keyword"&gt;in&lt;/span&gt; &lt;span class="var"&gt;$word_list&lt;/span&gt;) {&lt;br /&gt;45         &lt;span class="comment"&gt;# If adding the word would make the final string too long, start a&lt;/span&gt;&lt;br /&gt;46         &lt;span class="comment"&gt;# new string:&lt;/span&gt;&lt;br /&gt;47         &lt;span class="keyword"&gt;if&lt;/span&gt; (&lt;span class="var"&gt;$out_strings&lt;/span&gt;[&lt;span class="var"&gt;$i&lt;/span&gt;].Length &lt;span class="op"&gt;+&lt;/span&gt; &lt;span class="var"&gt;$word&lt;/span&gt;.Length &lt;span class="op"&gt;-gt&lt;/span&gt; &lt;span class="var"&gt;$width&lt;/span&gt;) {&lt;br /&gt;48             &lt;span class="comment"&gt;# If the word is hyphenated, try just the first part:&lt;/span&gt;&lt;br /&gt;49             &lt;span class="keyword"&gt;if&lt;/span&gt; (([&lt;span class="function"&gt;regex&lt;/span&gt;] &lt;span class="string"&gt;"\w+\-\w+"&lt;/span&gt;).IsMatch(&lt;span class="var"&gt;$word&lt;/span&gt;)) {&lt;br /&gt;50                 &lt;span class="keyword"&gt;if&lt;/span&gt; (&lt;span class="var"&gt;$out_strings&lt;/span&gt;[&lt;span class="var"&gt;$i&lt;/span&gt;].Length &lt;span class="op"&gt;+&lt;/span&gt; &lt;span class="num"&gt;1&lt;/span&gt; &lt;span class="op"&gt;+&lt;/span&gt;&lt;br /&gt;51                     &lt;span class="var"&gt;$word&lt;/span&gt;.Split(&lt;span class="string"&gt;"-"&lt;/span&gt;)[&lt;span class="num"&gt;0&lt;/span&gt;].Length &lt;span class="op"&gt;-le&lt;/span&gt; &lt;span class="var"&gt;$width&lt;/span&gt;) {&lt;br /&gt;52                     &lt;span class="var"&gt;$out_strings&lt;/span&gt;[&lt;span class="var"&gt;$i&lt;/span&gt;] &lt;span class="op"&gt;+=&lt;/span&gt; &lt;span class="var"&gt;$word&lt;/span&gt;.Split(&lt;span class="string"&gt;"-"&lt;/span&gt;)[&lt;span class="num"&gt;0&lt;/span&gt;]&lt;br /&gt;53                     &lt;span class="var"&gt;$out_strings&lt;/span&gt;[&lt;span class="var"&gt;$i&lt;/span&gt;] &lt;span class="op"&gt;+=&lt;/span&gt; &lt;span class="string"&gt;"-"&lt;/span&gt;&lt;br /&gt;54                     &lt;span class="var"&gt;$word&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="var"&gt;$word&lt;/span&gt;.SubString(&lt;span class="var"&gt;$word&lt;/span&gt;.IndexOf(&lt;span class="string"&gt;"-"&lt;/span&gt;) &lt;span class="op"&gt;+&lt;/span&gt; &lt;span class="num"&gt;1&lt;/span&gt;)&lt;br /&gt;55                 }&lt;br /&gt;56             }&lt;br /&gt;57             &lt;span class="var"&gt;$i++&lt;/span&gt;&lt;br /&gt;58             &lt;span class="var"&gt;$out_strings&lt;/span&gt; &lt;span class="op"&gt;+=&lt;/span&gt; &lt;span class="string"&gt;""&lt;/span&gt;&lt;br /&gt;59         }&lt;br /&gt;60         &lt;span class="var"&gt;$out_strings&lt;/span&gt;[&lt;span class="var"&gt;$i&lt;/span&gt;] &lt;span class="op"&gt;+=&lt;/span&gt; &lt;span class="var"&gt;$word&lt;/span&gt;&lt;br /&gt;61   &lt;br /&gt;62         &lt;span class="comment"&gt;# Add a space if it doesn't make the string too long.&lt;/span&gt;&lt;br /&gt;63         &lt;span class="keyword"&gt;if&lt;/span&gt; (&lt;span class="var"&gt;$out_strings&lt;/span&gt;[&lt;span class="var"&gt;$i&lt;/span&gt;].Length &lt;span class="op"&gt;+&lt;/span&gt; &lt;span class="num"&gt;1&lt;/span&gt; &lt;span class="op"&gt;-le&lt;/span&gt; &lt;span class="var"&gt;$width&lt;/span&gt;) {&lt;br /&gt;64             &lt;span class="var"&gt;$out_strings&lt;/span&gt;[&lt;span class="var"&gt;$i&lt;/span&gt;] &lt;span class="op"&gt;+=&lt;/span&gt; &lt;span class="string"&gt;" "&lt;/span&gt;&lt;br /&gt;65         }&lt;br /&gt;66     }&lt;br /&gt;67 &lt;br /&gt;68     &lt;span class="keyword"&gt;return&lt;/span&gt; (&lt;span class="var"&gt;$out_strings&lt;/span&gt; &lt;span class="op"&gt;-join&lt;/span&gt; &lt;span class="string"&gt;"`n"&lt;/span&gt;)&lt;br /&gt;69 }   &lt;span class="comment"&gt;# end function textwrap&lt;/span&gt;&lt;br /&gt;70&lt;br /&gt;&lt;/pre&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5089178761965217498-9005236025968890469?l=mechatechzilla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mechatechzilla.blogspot.com/feeds/9005236025968890469/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mechatechzilla.blogspot.com/2010/07/powershell-my-3-favorite-functions-2-of.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/9005236025968890469'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/9005236025968890469'/><link rel='alternate' type='text/html' href='http://mechatechzilla.blogspot.com/2010/07/powershell-my-3-favorite-functions-2-of.html' title='powershell: my 3 favorite functions (2 of 2)'/><author><name>mechatechzilla</name><uri>http://www.blogger.com/profile/17585447008783853422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://1.bp.blogspot.com/_jbCdMAhJU58/SpM-dMKvHKI/AAAAAAAABCw/fJGkIdcMqCE/S220/red_shirt.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5089178761965217498.post-2520475976593982414</id><published>2010-07-12T06:31:00.003-05:00</published><updated>2010-07-12T08:36:02.481-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='powershell'/><category scheme='http://www.blogger.com/atom/ns#' term='profile'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='scripting'/><title type='text'>powershell: my 3 favorite functions (1 of 2)</title><content type='html'>&lt;style&gt;#pscode{ font-weight: bold; background-color: palegoldenrod; color: black; padding: 1em; width: 51em; } #command{ font-weight: bold; background-color: navy; color: silver; padding: 1em; width: 51em;} .comment{ color: darkgreen;} .keyword{ color: navy; } .function{ color: teal; } .var { color: magenta; } .string{ color: maroon; } .op{ color: red; } .option{ color: darkcyan; font-style: oblique; } .optname{ color: purple; font-style: oblique; }&lt;/style&gt;&lt;br /&gt;i have every intention of continuing our lessons in x86 assembler and &lt;i&gt;nasm,&lt;/i&gt; but right now there is something else on my mind. let's pause our look at assembler for a little while and discuss powershell.&lt;br /&gt;&lt;br /&gt;powershell is a very powerful scripting language for managing windows hosts. in fact, &lt;a href="http://mechatechzilla.blogspot.com/2009/10/its-law-1-of-2.html"&gt;somewhere else&lt;/a&gt; i've gone on record saying, &amp;#147;if you administer a windows network, you &lt;i&gt;must&lt;/i&gt; learn powershell.&amp;#148; i meant that.&lt;br /&gt;&lt;br /&gt;powershell is very flexible and much easier to customize than dos batch files of yore. the powershell profile, reminiscent of the &lt;i&gt;.profile&lt;/i&gt; used in the unix bourne shell, allows you to collect your personal preferences and code where they will always be available when you run a script. to that end there are three functions that, for me and my profile, are “must-haves.” i'll share them with you here.&lt;br /&gt;&lt;br /&gt;&lt;em style="font-size:larger;font-weight:bold;color:orangered;"&gt;pause&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;the first is the simple dos &lt;b&gt;pause&lt;/b&gt; command. i'm not sure why powershell doesn't have such a useful command. it has proven its worth through decades of batch files. nevertheless, the powershell team has left it out. no matter. we can write our own with hardly any effort at all.&lt;br /&gt;&lt;br /&gt;&lt;pre id="pscode"&gt;5&lt;br /&gt;6&lt;br /&gt;7  &lt;span class="comment"&gt;# pause:&lt;/span&gt;&lt;br /&gt;8  &lt;span class="comment"&gt;#   accepts a string&lt;/span&gt;&lt;br /&gt;9  &lt;span class="comment"&gt;# Prints a message on the screen, then waits until a key is pressed before&lt;/span&gt;&lt;br /&gt;10 &lt;span class="comment"&gt;# proceeding. If a string is not passed to the function the default string&lt;/span&gt;&lt;br /&gt;11 &lt;span class="comment"&gt;# will be used. Simulates the "pause" command in DOS.&lt;/span&gt;&lt;br /&gt;12&lt;br /&gt;13 &lt;span class="keyword"&gt;function&lt;/span&gt; &lt;span class="function"&gt;pause&lt;/span&gt; (&lt;span class="var"&gt;$msg&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="string"&gt;"Press any key to continue..."&lt;/span&gt;) {&lt;br /&gt;14     &lt;span class="var"&gt;$msg&lt;/span&gt;&lt;br /&gt;15     &lt;span class="var"&gt;$Host&lt;/span&gt;&lt;span class="function"&gt;.UI.RawUI.ReadKey&lt;/span&gt;(&lt;span class="string"&gt;"NoEcho, IncludeKeyDown"&lt;/span&gt;) | &lt;span class="function"&gt;Out-Null&lt;/span&gt;&lt;br /&gt;16 }   &lt;span class="comment"&gt;# end function pause&lt;/span&gt;&lt;br /&gt;17&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;this function will accept a string to print as your pause message, but will default to the old dos standard “press any key” in absence of one. it uses the console's &lt;i&gt;ui.rawui.readkey&lt;/i&gt; method to capture a raw key press, and redirects the output to the &lt;i&gt;out-null&lt;/i&gt; cmdlet to avoid echoing the key's character on screen. a sample run of this function should look like this:&lt;br /&gt;&lt;br /&gt;&lt;pre id="command"&gt;C:\&gt; pause&lt;br /&gt;Press any key to continue...&lt;br /&gt;C:\&gt; pause "I can't do that, Dave."&lt;br /&gt;I can't do that, Dave.&lt;br /&gt;C:\&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;em style="font-size:larger;font-weight:bold;color:orangered;"&gt;test&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;the second function is &lt;b&gt;test,&lt;/b&gt; borrowed from the linux bourne-again shell, or &lt;i&gt;bash.&lt;/i&gt; the test command takes an expression and determines whether the result is true or false. now, the bash command isn't really intended to be user-friendly: the result of the test is stored in the program's exit code. this is useful in a shell script, but i like to use test to help me debug scripts and check that my expressions are giving me the results i expect, so i've expanded it a little for powershell.&lt;br /&gt;&lt;br /&gt;&lt;pre id="pscode"&gt;18&lt;br /&gt;19 &lt;span class="comment"&gt;# test:&lt;/span&gt;&lt;br /&gt;20 &lt;span class="comment"&gt;#   expects an expression&lt;/span&gt;&lt;br /&gt;21 &lt;span class="comment"&gt;# Accepts any valid expression and evalutes it for truth. Prints a message&lt;/span&gt;&lt;br /&gt;22 &lt;span class="comment"&gt;# indicating that the expression evaluated true or false.&lt;/span&gt;&lt;br /&gt;23&lt;br /&gt;24 &lt;span class="keyword"&gt;function&lt;/span&gt; &lt;span class="function"&gt;test&lt;/span&gt; (&lt;span class="var"&gt;$expr&lt;/span&gt;) {&lt;br /&gt;25     &lt;span class="keyword"&gt;if&lt;/span&gt; (&lt;span class="var"&gt;$expr&lt;/span&gt;) {&lt;br /&gt;26         &lt;span class="function"&gt;Write-Host&lt;/span&gt; &lt;span class="option"&gt;-ForegroundColor&lt;/span&gt; &lt;span class="optname"&gt;Green&lt;/span&gt; &lt;span class="string"&gt;"True"&lt;/span&gt;&lt;br /&gt;27     }&lt;br /&gt;28     &lt;span class="keyword"&gt;else&lt;/span&gt; {&lt;br /&gt;29         &lt;span class="function"&gt;Write-Host&lt;/span&gt; &lt;span class="option"&gt;-ForegroundColor&lt;/span&gt; &lt;span class="optname"&gt;Red&lt;/span&gt; &lt;span class="string"&gt;"False"&lt;/span&gt;&lt;br /&gt;30     }&lt;br /&gt;31 }   &lt;span class="comment"&gt;# end function test&lt;/span&gt;&lt;br /&gt;32&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;we can use this function from the interactive prompt to determine if some logical expression does what we think it does. a sample run of the function would look like this:&lt;br /&gt;&lt;br /&gt;&lt;pre id="command"&gt;C:\&gt; test (3 -gt 4)&lt;br /&gt;&lt;span style="color:red;"&gt;False&lt;/span&gt;&lt;br /&gt;C:\&gt; test ("Bill" -is [string])&lt;br /&gt;&lt;span style="color:lime;"&gt;True&lt;/span&gt;&lt;br /&gt;C:\&gt; test (42 - 6 -lt 30 -or 56 + 9 -gt 70)&lt;br /&gt;&lt;span style="color:red;"&gt;False&lt;/span&gt;&lt;br /&gt;C:\&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;now we can easily test even a complex expression to see whether it should be true or false when we use it in a script.&lt;br /&gt;&lt;br /&gt;be sure to check back next time for the coolest of my three favorite functions.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5089178761965217498-2520475976593982414?l=mechatechzilla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mechatechzilla.blogspot.com/feeds/2520475976593982414/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mechatechzilla.blogspot.com/2010/07/powershell-my-3-favorite-functions-1-of.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/2520475976593982414'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/2520475976593982414'/><link rel='alternate' type='text/html' href='http://mechatechzilla.blogspot.com/2010/07/powershell-my-3-favorite-functions-1-of.html' title='powershell: my 3 favorite functions (1 of 2)'/><author><name>mechatechzilla</name><uri>http://www.blogger.com/profile/17585447008783853422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://1.bp.blogspot.com/_jbCdMAhJU58/SpM-dMKvHKI/AAAAAAAABCw/fJGkIdcMqCE/S220/red_shirt.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5089178761965217498.post-5990263756854111113</id><published>2010-04-30T00:17:00.027-05:00</published><updated>2010-07-07T20:18:16.068-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dos'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='nasm'/><category scheme='http://www.blogger.com/atom/ns#' term='assembly language'/><title type='text'>assembler tutorial: 2 - goodbye, mr. chips</title><content type='html'>&lt;style&gt;#code{ padding: 1em; background: blue; color: white; width: 51em; }&lt;/style&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-style:italic; font-weight: bold; color: darkviolet"&gt;and bade them curt 'hello,' and then 'good-bye.'&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;for our second heavily-annotated example, we'll modify the 'hello world' program a bit. beyond simply saying "goodbye" this new app will allow the user to provide a name on the command line to which we may bid adieu. if no argument is provided, the program will simply say &lt;a href="http://www.imdb.com/title/tt0031385/"&gt;goodbye to mr. chips.&lt;/a&gt; this time we will be assembling a dos com file.&lt;br/&gt;&lt;br /&gt;in dosbox, move to the mycode directory and launch editv to create a new file called goodbye.asm.&lt;br/&gt;&lt;br /&gt;comment, comment, comment. note that this file will not require a linker.&lt;br/&gt;&lt;br /&gt;&lt;pre id="code"&gt;&lt;br /&gt;1   ; goodbye.asm&lt;br /&gt;2   ; This variation on the 'Hello World' program expands upon the original&lt;br /&gt;3   ; a little by accepting a name from the command line and printing that &lt;br /&gt;4   ; in the message. If no parameter is supplied, the program will use a&lt;br /&gt;5   ; default value. This one is written as a COM file, so it doesn't&lt;br /&gt;6   ; require linking.&lt;br /&gt;7   ; To assemble: nasm -o goodbye.com goodbye.asm&lt;br /&gt;8   ;&lt;br /&gt;9   ; Robert Ritter &lt;rritter@centriq.com&gt;&lt;br /&gt;10  ; 25 Apr 2010&lt;br /&gt;11  &lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;we begin with a directive for the assembler. &lt;span style="font-weight:bold;"&gt;org&lt;/span&gt; is not a machine instruction, but rather a note to the assembler so that it can configure all of the segment addresses for you. in a dos com file the entire program fits into a single 64kb segment, so loading up all those segment registers seems rather silly. &lt;span style="font-weight:bold;"&gt;org 100h&lt;/span&gt; tells nasm that this is a com file, so all segments are at exactly the same address, and the program starts at offset &lt;span style="font-weight:bold;"&gt;100h&lt;/span&gt;. why this offset? well the first 256 bytes (&lt;span style="font-weight:bold;"&gt;0h&lt;/span&gt; through &lt;span style="font-weight:bold;"&gt;ffh&lt;/span&gt;) makes up the &lt;span style="font-style:italic;"&gt;program segment prefix&lt;/span&gt;, or psp. byte &lt;span style="font-weight:bold;"&gt;100h&lt;/span&gt; is the first place real code can be loaded. since i'm defining my data at the top of my source file, i'm putting a &lt;span style="font-weight:bold;"&gt;jmp&lt;/span&gt; (&lt;span style="font-style:italic;"&gt;unconditional jump&lt;/span&gt;) at this address to tell the system to skip right to the good stuff. &lt;span style="font-weight:bold;"&gt;jmp&lt;/span&gt; works like the much-maligned &lt;span style="font-weight:bold;"&gt;goto&lt;/span&gt; statement in other languages: it transfers execution to the code found at the given label. we're going to let the program flow jump to the label called 'Start' and we'll catch up in a bit.&lt;br/&gt;&lt;br /&gt;&lt;pre id="code"&gt;&lt;br /&gt;12  ; ----------------------------------------------------------------------&lt;br /&gt;13  org 100h&lt;br /&gt;14  ; We set up a COM file by defining the address of the program location&lt;br /&gt;15  ; in memory, which will always be 100h. Then we jump to the start of &lt;br /&gt;16  ; the code block.&lt;br /&gt;17  ;&lt;br /&gt;18                  jmp     Start&lt;br /&gt;19  &lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;you've seen data before, and you will recognize &lt;span style="font-weight:bold;"&gt;db&lt;/span&gt; from our last program. one new thing here is the &lt;span style="font-weight:bold;"&gt;equ&lt;/span&gt; directive. this creates a constant. data defined with &lt;span style="font-weight:bold;"&gt;db&lt;/span&gt; may be modified during program execution, but data defined with &lt;span style="font-weight:bold;"&gt;equ&lt;/span&gt; cannot. any attempt to change the value stored in endMsgLen in this program will cause the assembler to balk with the message that the label has been redefined.&lt;br/&gt;&lt;br /&gt;another new thing is the use of the dollar sign &lt;span style="font-style:italic;"&gt;outside&lt;/span&gt; the quotation marks. what does that mean? well, we're going to be copying strings into a buffer and we'll need to tell the cpu exactly how many bytes to copy. it's easy to find the size of the beginMsg string: we subtract its address from the address of defaultMsg. &lt;pre&gt;defaultMsg - beginMsg&lt;/pre&gt; will give us the length of beginMsg. remember that labels are just aliases for memory addresses. we can use the same technique to find the length of defaultMsg. to find the length of the last string, endMsg, we subtract endMsg from $. the dollar sign in line 31 means "this byte right here." so endMsgLen will contain the difference between endMsgLen and endMsg. that's pretty cool.&lt;br/&gt;&lt;br /&gt;&lt;pre id="code"&gt;&lt;br /&gt;20  ; ----------------------------------------------------------------------&lt;br /&gt;21  section .data&lt;br /&gt;22  ; DOS COM files don't use segmented memory. The whole program fits&lt;br /&gt;23  ; into a single 64KB block, so there's no need to worry about segments&lt;br /&gt;24  ; at all. The assembler still expects to find defined data and code&lt;br /&gt;25  ; sections, though, and it helps us to organize our source if we keep&lt;br /&gt;26  ; things compartmentalized like this.&lt;br /&gt;27  ;&lt;br /&gt;28  beginMsg        db      'Goodbye, '&lt;br /&gt;29  defaultMsg      db      'Mr. Chips'&lt;br /&gt;30  endMsg          db      '!', 0dh, 0ah, '$'&lt;br /&gt;31  endMsgLen       equ     $ - endMsg&lt;br /&gt;32  &lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;the bss section (so named for historic reasons) contains data that is not initialized to a specific value; at least, no value that we care about. here we're creating a working buffer to which we may copy the elements of our final string before we send it to standard output.&lt;br/&gt;&lt;br /&gt;&lt;pre id="code"&gt;&lt;br /&gt;33  ; ----------------------------------------------------------------------&lt;br /&gt;34  section .bss&lt;br /&gt;35  ; This section contains unintialized storage space. We allocate space&lt;br /&gt;36  ; here for data that we won't have until runtime. COM files don't&lt;br /&gt;37  ; require an explicit STACK section. The assembler will take care of&lt;br /&gt;38  ; the stack for us.&lt;br /&gt;39  ;&lt;br /&gt;40  fullMsg         resb    1024    ; This is the message we will print.&lt;br /&gt;41                                  ; We'll assemble it from parts and&lt;br /&gt;42                                  ; copy each part into this memory area.&lt;br /&gt;43 &lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;the &lt;b&gt;rep movsb&lt;/b&gt; instructions copy a sequence of bytes from one place in memory to another. the number of bytes that get copied is found in the &lt;b&gt;cx&lt;/b&gt; register. so what we're doing here is concatenating strings and storing the result in fullMsg. first strings first...&lt;br/&gt;&lt;br /&gt;&lt;pre id="code"&gt; &lt;br /&gt;44  ; ----------------------------------------------------------------------&lt;br /&gt;45  section .code&lt;br /&gt;46  &lt;br /&gt;47  Start:&lt;br /&gt;48  ; First we'll copy the beginning of the message, 'Goodbye,' to our&lt;br /&gt;49  ; allocated memory. The number of bytes to copy (the length of our&lt;br /&gt;50  ; data) goes into CX.&lt;br /&gt;51                  mov     cx, defaultMsg - beginMsg&lt;br /&gt;52  ; The address of the data goes into SI (think Source Index) and the&lt;br /&gt;53  ; address of the allocated memory into DI (as in Destination Index.)&lt;br /&gt;54                  mov     si, beginMsg&lt;br /&gt;55                  mov     di, fullMsg&lt;br /&gt;56          rep     movsb   ; REP MOVSB copies CX bytes from SI to DI.&lt;br /&gt;57                          ; DI is automatically incremented.&lt;br /&gt;58&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;remember that psp? the first 128 bytes (&lt;b&gt;00h&lt;/b&gt; through &lt;b&gt;7fh&lt;/b&gt;) is full of stuff that we're really not interested in, but the second 128 bytes (&lt;b&gt;80h&lt;/b&gt; through &lt;b&gt;ffh&lt;/b&gt;) contains information from the command line that we used to run our program. since we want to get a name from the parameter list on the command line, we want to read this part of the psp. byte &lt;b&gt;80h&lt;/b&gt; tells us how long the parameter list is, so if it's zero (the program was run without any parameters) we'll say goodbye to the default name; otherwise we'll read the parameter list and take our name from there.&lt;br/&gt; &lt;br /&gt;throughout our sojourn in assembler we've been working with memory addresses. the programming savvy among you may have said to yourself, "ah, these are pointers." most of what we work with in assembler is addresses, or pointers. if you learned in computer programming class that pointers were hard, then you learned them incorrectly; but that's a rant for another post. suffice it to say that pointers are &lt;i&gt;the&lt;/i&gt; way to manipulate data in assembler. however, sometimes we need to get at the data in a memory location directly. on line 71 we need to compare zero to the &lt;i&gt;value at address 80h, not the address itself.&lt;/i&gt; nasm makes this pretty easy: we use square brackets around an address to access the value inside. the instruction in line 69 means, "copy the value stored at address 80h into the cl register." there, you've just dereferenced a pointer. no big deal.&lt;br/&gt; &lt;br /&gt;this section contains a couple of logic branches using the &lt;b&gt;cmp&lt;/b&gt; operator to &lt;i&gt;compare&lt;/i&gt; two values, a &lt;b&gt;jz&lt;/b&gt; operator to &lt;i&gt;jump if zero&lt;/i&gt; to a particular label, and an unconditional &lt;b&gt;jmp&lt;/b&gt; instruction to skip parts of the program that won't be used if a name was given on the command line. remember that labels are just memory addresses in assembler.&lt;br/&gt;&lt;br /&gt;&lt;pre id="code"&gt;&lt;br /&gt;59  ; Next we'll copy the command line parameter into our allocated memory.&lt;br /&gt;60  ; When we start a program, DOS creates a data structure for it called&lt;br /&gt;61  ; the PSP (Program Segment Prefix) that loads ahead of it in the first&lt;br /&gt;62  ; 256 (100h) bytes of memory. (This is why the COM file has to point to&lt;br /&gt;63  ; address 100h to start.) The first 128 bytes of the PSP is "stuff," so&lt;br /&gt;64  ; we won't worry about that. The last half of the PSP contains the&lt;br /&gt;65  ; parameter string. Byte 80h contains the length of the string and the&lt;br /&gt;66  ; remaining bytes contain the parameter string terminated by a carriage&lt;br /&gt;67  ; return (0dh.)&lt;br /&gt;68                  xor     cx, cx          ; Set CX to zero.&lt;br /&gt;69                  mov     cl, [80h]       ; Put the parameter length&lt;br /&gt;70                                          ; into CL.&lt;br /&gt;71                  cmp     cl, 0           ; Test CL to see if it's zero.&lt;br /&gt;72                  jz      NoParam         ; If CL contains zero jump to&lt;br /&gt;73                                          ; another part of the program.&lt;br /&gt;74  ; If the JZ (Jump if Zero) wasn't executed, then the user ran the&lt;br /&gt;75  ; program with a command line parameter. CX now contains the number of&lt;br /&gt;76  ; bytes in the string, but the first byte is always a space, so we'll&lt;br /&gt;77  ; decrement CX and start copying the string from byte 82h. DI already&lt;br /&gt;78  ; points to the end of the last thing we copied to memory.&lt;br /&gt;79                  dec     cx&lt;br /&gt;80                  mov     si, 82h&lt;br /&gt;81          rep     movsb&lt;br /&gt;82                  jmp     FinishString    ; Skip the NoParam part since&lt;br /&gt;83                                          ; there was a parameter.&lt;br /&gt;84  &lt;br /&gt;85  NoParam:&lt;br /&gt;86  ; No parameter was given on the command line. We'll use the default&lt;br /&gt;87  ; goodbye message.&lt;br /&gt;88                  mov     cx, endMsg - defaultMsg&lt;br /&gt;89                  mov     si, defaultMsg&lt;br /&gt;90          rep     movsb&lt;br /&gt;91  &lt;br /&gt;92  FinishString:&lt;br /&gt;93  ; Now we copy the last part of the message to memory.&lt;br /&gt;94                  mov     cx, endMsgLen&lt;br /&gt;95                  mov     si, endMsg&lt;br /&gt;96          rep     movsb&lt;br /&gt;97  &lt;br /&gt;98  ; Use the DOS service call to print the string that is in memory.&lt;br /&gt;99                  mov     dx, fullMsg&lt;br /&gt;100                 mov     ah, 09h&lt;br /&gt;101                 int     21h&lt;br /&gt;102 &lt;br /&gt;103 ; Exit with no error code.&lt;br /&gt;104                 mov     ax, 4c00h&lt;br /&gt;105                 int     21h&lt;br /&gt;106&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;save the file and exit editv. assemble the program directly into a com file: &lt;pre&gt;nasm -o goodbye.com goodbye.asm&lt;/pre&gt; run the program with and without parameters.&lt;br/&gt;&lt;br /&gt;now that was a pretty sophisticated program. you fetched data from the command line and used a condition to branch to a specific part of your program, much like &lt;i&gt;if..then&lt;/i&gt; logic found in so-called high-level languages, and you used a default parameter if one wasn't provided. your skills are progressing nicely, padawan. you're training is almost complete.&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5089178761965217498-5990263756854111113?l=mechatechzilla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mechatechzilla.blogspot.com/feeds/5990263756854111113/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mechatechzilla.blogspot.com/2010/04/assembler-tutorial-2-goodbye-mr-chips.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/5990263756854111113'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/5990263756854111113'/><link rel='alternate' type='text/html' href='http://mechatechzilla.blogspot.com/2010/04/assembler-tutorial-2-goodbye-mr-chips.html' title='assembler tutorial: 2 - goodbye, mr. chips'/><author><name>mechatechzilla</name><uri>http://www.blogger.com/profile/17585447008783853422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://1.bp.blogspot.com/_jbCdMAhJU58/SpM-dMKvHKI/AAAAAAAABCw/fJGkIdcMqCE/S220/red_shirt.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5089178761965217498.post-6115865224073252642</id><published>2010-04-12T08:16:00.012-05:00</published><updated>2010-04-12T10:48:49.809-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dos'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='nasm'/><category scheme='http://www.blogger.com/atom/ns#' term='assembly language'/><title type='text'>assembler tutorial: 1 - hello, world!</title><content type='html'>&lt;style&gt;#code{ padding: 1em; background: blue; color: white; width: 52em; }&lt;/style&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-style:italic; font-weight: bold; color: darkviolet;"&gt;but thunder interrupted all their fears&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;now that you're ready to begin writing we'll dig right in. here is our first heavily-annotated program, hello.exe.&lt;br/&gt;&lt;br /&gt;&lt;hr/&gt;&lt;br /&gt;open up your dosbox and change to the mycode directory.&lt;pre&gt;cd mycode&lt;/pre&gt; run editv with a new file, hello.asm.&lt;pre&gt;editv hello.asm&lt;/pre&gt; i strongly advise you to turn on line numbering. you can do this by pressing &lt;span style="font-weight:bold;"&gt;ctrl-o&lt;/span&gt; followed by &lt;span style="font-weight:bold;"&gt;b&lt;/span&gt;, or you can just select the options menu with &lt;span style="font-weight:bold;"&gt;alt-o&lt;/span&gt;, scroll down to &lt;span style="font-weight:bold;"&gt;line numbers&lt;/span&gt; and press &lt;span style="font-weight:bold;"&gt;enter&lt;/span&gt;.&lt;br/&gt;&lt;br /&gt;we begin with comments. if you've ever read a book on programming it has probably emphasized the need for good comments. in assembler comments are even more important because the language syntax is so terse. a comment begins with a semi-colon and continues to the end of the line of text.&lt;br/&gt;&lt;br /&gt;&lt;pre id="code" style="width: 52em;"&gt;&lt;br /&gt;1  ; hello.asm&lt;br /&gt;2  ; Demonstrates how to write an assembly program for DOS with NASM using&lt;br /&gt;3  ; the ubiquitous 'Hello World' string. To create an EXE file we'll&lt;br /&gt;4  ; first assemble an OBJ file then link it. I'm using the public domain&lt;br /&gt;5  ; linker WarpLink.&lt;br /&gt;6  ; To assemble: nasm -f obj hello.asm&lt;br /&gt;7  ; To link: warplink hello.obj&lt;br /&gt;8  ;&lt;br /&gt;9  ; Robert Ritter &amp;lt;rritter@centriq.com&amp;gt;&lt;br /&gt;10 ; 12 Apr 2010&lt;br /&gt;11 &lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;remember that dos addresses memory in segments. the first thing we'll need to do is reserve some memory for these segments. since this program doesn't work with a lot of data our data segment is pretty small. it defines a label, &lt;span style="font-style:italic;"&gt;message&lt;/span&gt;, that will be the memory address of the first byte of the message that we're going to print out. the &lt;span style="font-weight:bold;"&gt;db&lt;/span&gt; (&lt;span style="font-style:italic;"&gt;define byte&lt;/span&gt;) operator identifies a sequence of bytes that make up our data. there is also a &lt;span style="font-weight:bold;"&gt;dw&lt;/span&gt; (&lt;span style="font-style:italic;"&gt;define word&lt;/span&gt;) for 16-bit values, and &lt;span style="font-weight:bold;"&gt;dd&lt;/span&gt; (&lt;span style="font-style:italic;"&gt;define double word&lt;/span&gt;) for 32-bit values. most of the time you'll probably just treat data as a sequence of bytes, so you'll likely use &lt;span style="font-weight:bold;"&gt;db&lt;/span&gt; more than the others.&lt;br/&gt;&lt;br /&gt;you may have noticed the characters that follow the obvious string, "Hello World." if we want to advance our output to the next line we must insert a newline character. this is like pressing the &lt;span style="font-weight:bold;"&gt;enter&lt;/span&gt; key on a keyboard. in high-level languages like c we use a string like "\n" to represent a newline, but in dos this is actually a two-byte sequence: &lt;span style="font-weight:bold;"&gt;0dh&lt;/span&gt; (&lt;span style="font-style:italic;"&gt;carriage return&lt;/span&gt;) and &lt;span style="font-weight:bold;"&gt;0ah&lt;/span&gt; (&lt;span style="font-style:italic;"&gt;linefeed&lt;/span&gt;.) the dollar sign character is a &lt;span style="font-style:italic;"&gt;terminator&lt;/span&gt; that marks the end of the string. not all strings must be terminated with a dollar sign, but the dos printing service that we're going to use requires it.&lt;br/&gt;&lt;br /&gt;notice that the characters that make up a string are enclosed in quotes. double or single quotes, it makes no difference. those characters &lt;span style="font-style:italic;"&gt;outside&lt;/span&gt; the quotes are treated as literal bytes.&lt;br/&gt;&lt;br /&gt;&lt;pre id="code" style="width: 52em;"&gt;&lt;br /&gt;12 ; ----------------------------------------------------------------------&lt;br /&gt;13 segment data&lt;br /&gt;14 ; DOS EXE files use segmented memory which allows them to address more&lt;br /&gt;15 ; than 64KB at a time. Here we define the data segment to store the&lt;br /&gt;16 ; message that we're going to print on the screen.&lt;br /&gt;17 ;&lt;br /&gt;18 message         db      'Hello World', 0dh, 0ah, '$'&lt;br /&gt;19&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;the next thing that we want to do is reserve some memory for our stack segment. the &lt;span style="font-weight:bold;"&gt;resb&lt;/span&gt; (&lt;span style="font-style:italic;"&gt;reserve byte&lt;/span&gt;) operator is used to set aside an uninitialized piece of memory of a given size. there is also a &lt;span style="font-weight:bold;"&gt;resw&lt;/span&gt; (&lt;span style="font-style:italic;"&gt;reserve word&lt;/span&gt;) for 16-bit values and &lt;span style="font-weight:bold;"&gt;resd&lt;/span&gt; (&lt;span style="font-style:italic;"&gt;reserve double word&lt;/span&gt;) for 32-bit values. we're going to allocate a 64-byte hunk'o'ram for the stack and set the label stackTop to point to the address &lt;span style="font-style:italic;"&gt;immediately following&lt;/span&gt; the stack. for more info on how the stack works, see my previous post.&lt;br/&gt;&lt;br /&gt;&lt;pre id="code" style="width: 52em;"&gt;&lt;br /&gt;20 ; ----------------------------------------------------------------------&lt;br /&gt;21 segment stack stack&lt;br /&gt;22 ; The stack is used as temporary storage for values during the&lt;br /&gt;23 ; program's execution. Sometimes we use it in our code, and sometimes&lt;br /&gt;24 ; DOS uses it, especially when we call DOS interrupts. We'll set up a&lt;br /&gt;25 ; small but serviceable stack for this program since we're going to be&lt;br /&gt;26 ; calling on DOS services.&lt;br /&gt;27 ;&lt;br /&gt;28                 resb    64&lt;br /&gt;29 stackTop        ; The label 'stackTop' is the address of the end (top)&lt;br /&gt;30                 ; of the stack. We'll need this to initialize the&lt;br /&gt;31                 ; stack pointer in the CPU.&lt;br /&gt;32&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;the code segment is where the cool stuff happens. remember that a dos exe file may have more than one code segment to get around that pesky 64kb barrier we discussed last time. though multiple code segments are allowed, only one can be the actual entry point of our program. this is defined with a special label, &lt;span style="font-weight:bold;"&gt;..start&lt;/span&gt;. note that i used a colon at the end of this label. a label may end with a colon, but this is not required. you may find code examples that are pretty inconsistent on the use of colons in labels. even examples in the official nasm documentation waffle a little on this. personally, i choose to use a colon when the label refers to a block of code, and to forgo the colon when the label refers to data. remember, though, that to the assembler they're all just addresses.&lt;br/&gt;&lt;br /&gt;we're giving the &lt;span style="font-weight:bold;"&gt;mov&lt;/span&gt; operator a real workout here. the instruction &lt;pre&gt;mov dest, src&lt;/pre&gt; tells the assembler to copy the data at src into dest. yes, it goes right to left, but you get used to it pretty quickly. in this instance we're loading segment addresses into their respective cpu registers. since we can't copy &lt;span style="font-style:italic;"&gt;immediate&lt;/span&gt; data directly into a segment register, we'll use &lt;span style="font-weight:bold;"&gt;ax&lt;/span&gt; for temporary storage.&lt;br/&gt;&lt;br /&gt;&lt;pre id="code" style="width: 52em;"&gt;&lt;br /&gt;33 ; ----------------------------------------------------------------------&lt;br /&gt;34 segment code&lt;br /&gt;35 ; The code segment is where our program actually does stuff. Executable&lt;br /&gt;36 ; instructions go here. &lt;br /&gt;37 ;&lt;br /&gt;38 ..start:&lt;br /&gt;39 ; First we need to do some housekeeping. Our program needs to know at&lt;br /&gt;40 ; what addresses its segments can be found. The Intel CPU contains some&lt;br /&gt;41 ; special registers just to hold this information, so we'll load them&lt;br /&gt;42 ; up now. Since we can't put addresses directly into these registers,&lt;br /&gt;43 ; we'll copy them to the AX general purpose register first.&lt;br /&gt;44                 mov     ax, data&lt;br /&gt;45                 mov     ds, ax          ; DS: data segment register&lt;br /&gt;46                 mov     ax, stack&lt;br /&gt;47                 mov     ss, ax          ; SS: stack segment register&lt;br /&gt;48                 mov     sp, stackTop    ; SP: stack pointer register&lt;br /&gt;49&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;now we're going to call on dos to print our message on the screen. dos and the system bios have several services that they offer to our programs. these are accessed by triggering an &lt;span style="font-style:italic;"&gt;interrupt&lt;/span&gt; with the &lt;span style="font-weight:bold;"&gt;int&lt;/span&gt; instruction. each service has its own requirements, so we need to look up the particular service we want in our handy dos developer's guide in order to properly use it. the dos service we're using here is service &lt;span style="font-weight:bold;"&gt;09h&lt;/span&gt; of the general purpose interrupt &lt;span style="font-weight:bold;"&gt;21h&lt;/span&gt;. to use it we place the address of a dollar-sign-terminated string into register &lt;span style="font-weight:bold;"&gt;dx&lt;/span&gt;, place the service id &lt;span style="font-weight:bold;"&gt;09h&lt;/span&gt; into register &lt;span style="font-weight:bold;"&gt;ah&lt;/span&gt;, then call interrupt &lt;span style="font-weight:bold;"&gt;21h&lt;/span&gt;.&lt;br/&gt;&lt;br /&gt;&lt;pre id="code" style="width: 52em;"&gt;&lt;br /&gt;50 ; We're going to use a DOS service to write a string to the screen.&lt;br /&gt;51 ; The documentation for this service says that we have to terminate the&lt;br /&gt;52 ; string we want to print with a dollar sign (see how we did this in&lt;br /&gt;53 ; the data segment above) and we must put the address of the string&lt;br /&gt;54 ; into the DX register and call the service. DOS interrupt 21h provides&lt;br /&gt;55 ; all kinds of cool services. To use it we place the service ID in&lt;br /&gt;56 ; register AH and call INT 21h.&lt;br /&gt;57                 mov     dx, message&lt;br /&gt;58                 mov     ah, 09h&lt;br /&gt;59                 int     21h&lt;br /&gt;60&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;finally we exit the program. we'll use service &lt;span style="font-weight:bold;"&gt;4ch&lt;/span&gt; of dos interrupt &lt;span style="font-weight:bold;"&gt;21h&lt;/span&gt;. if you have a specific exit code (for example, to signal an error) you place it into register &lt;span style="font-weight:bold;"&gt;al&lt;/span&gt;. just as before, we put the service id into &lt;span style="font-weight:bold;"&gt;ah&lt;/span&gt; and call the interrupt. since we have no error condition we'll do a clean exit. here we load &lt;span style="font-weight:bold;"&gt;al&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;ah&lt;/span&gt; at the same time by putting &lt;span style="font-weight:bold;"&gt;4c00h&lt;/span&gt; into &lt;span style="font-weight:bold;"&gt;ax&lt;/span&gt;.&lt;br/&gt;&lt;br /&gt;&lt;pre id="code" style="width: 52em;"&gt;&lt;br /&gt;61 ; We also use INT 21h to exit our program. The exit function is 4Ch,&lt;br /&gt;62 ; which goes into AH. The exit code that is used to report errors back&lt;br /&gt;63 ; to the operating system goes into AL. We'll just load both at the&lt;br /&gt;64 ; same time, then call INT 21h.&lt;br /&gt;65                 mov     ax, 4c00h&lt;br /&gt;66                 int     21h&lt;br /&gt;67 &lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;you have just written a program in assembly language. save the file and exit editv. assemble the file with nasm: &lt;pre&gt;nasm -f obj hello.asm&lt;/pre&gt; this will create an object file suitable for linking into a dos exe. link the file with warplink:&lt;pre&gt;warplink hello.obj&lt;/pre&gt; this creates the file hello.exe. notice that i included these instructions in the comments at the top of the source file. this is useful if you come back to the program at a later time and want to make changes. now run your program and bask in the warmth of the knowledge that you have made this cpu do your explicit bidding. a little bit more of this and you'll be ready for live minions.&lt;br/&gt;&lt;br /&gt;next time we'll pass command-line parameters into our program, and we'll shake things up a bit with the dos com file format.&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5089178761965217498-6115865224073252642?l=mechatechzilla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mechatechzilla.blogspot.com/feeds/6115865224073252642/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mechatechzilla.blogspot.com/2010/04/assembler-tutorial-1-hello-world.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/6115865224073252642'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/6115865224073252642'/><link rel='alternate' type='text/html' href='http://mechatechzilla.blogspot.com/2010/04/assembler-tutorial-1-hello-world.html' title='assembler tutorial: 1 - hello, world!'/><author><name>mechatechzilla</name><uri>http://www.blogger.com/profile/17585447008783853422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://1.bp.blogspot.com/_jbCdMAhJU58/SpM-dMKvHKI/AAAAAAAABCw/fJGkIdcMqCE/S220/red_shirt.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5089178761965217498.post-7875456369636539056</id><published>2010-04-05T07:55:00.004-05:00</published><updated>2010-04-12T10:53:36.467-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dos'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='assembly language'/><title type='text'>assembler tutorial: intro 2 of 2</title><content type='html'>&lt;style&gt;#code{ padding: 1em; background: blue; color: white; width: 43em; }&lt;/style&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-style:italic; font-weight: bold; color: darkviolet"&gt;the lovers moved to flee from heaven's tears&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;span style="color: red; font-weight: bold;"&gt;warning: this post contains frequent references to explicit hex, and may be inappropriate for readers under the age of 11h&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;last time i said, "before we begin in earnest, two things." here comes thing number two.&lt;br/&gt;&lt;br /&gt;&lt;hr/&gt;&lt;br /&gt;second, a word about how assembler works. you are no doubt aware that your computer has long-term storage (disks) and short-term storage (random access memory, or ram.) if we use an office allegory to describe a computer, we might say that the disks are like the filing cabinets in the back room: they can hold lots and lots of stuff, and are generally pretty well organized, but inconvenient. constantly going to them to fetch new work or to put something away would be a chore, so we tend to use them only when we need to grab something we plan to use soon or to put something away when we won't be using it for a good long while. ram is like the in/out trays on my desk: i can stack all kinds of stuff there (though much less than i can put in the filing cabinets) and my work is quickly and easily accessible. the cpu is like my desktop, where all the work actually happens. to do some work i have to take it from the trays and move it to the desktop, and to clear the desk for some other task i need to move what's on the desktop back to the trays. so where in the cpu do we store this really temporary stuff while working on it?&lt;br/&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-style:italic; color: navy"&gt;registers&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;cpus have built-in memory storage spaces called &lt;i&gt;registers&lt;/i&gt;. in the intel x86 architecture, 16-bit general purpose registers go by the names &lt;b&gt;ax&lt;/b&gt;, &lt;b&gt;bx&lt;/b&gt;, &lt;b&gt;cx&lt;/b&gt; and &lt;b&gt;dx&lt;/b&gt;. each 16-bit register can be broken into two parts, a high-order byte and a low-order byte. for register &lt;b&gt;ax&lt;/b&gt;, these would be called &lt;b&gt;ah&lt;/b&gt; and &lt;b&gt;al&lt;/b&gt; respectively. the specific meanings of &lt;span style="font-style:italic;"&gt;high-&lt;/span&gt; and &lt;span style="font-style:italic;"&gt;low-order&lt;/span&gt; aren't too important right now, and the topic delves deep into ancient religious wars of cpu design, but suffice it to say that putting the 16-bit word &lt;span style="font-weight:bold;"&gt;c725h&lt;/span&gt; into register &lt;span style="font-weight:bold;"&gt;ax&lt;/span&gt; will load &lt;span style="font-weight:bold;"&gt;c7h&lt;/span&gt; into &lt;span style="font-weight:bold;"&gt;ah&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;25h&lt;/span&gt; into &lt;span style="font-weight:bold;"&gt;al&lt;/span&gt;.&lt;br/&gt;&lt;br /&gt;in modern cpus each 16-bit register is only half of one of the 32-bit registers, which bear the names &lt;b&gt;eax&lt;/b&gt;, &lt;b&gt;ebx&lt;/b&gt;, &lt;b&gt;ecx&lt;/b&gt; and &lt;b&gt;edx&lt;/b&gt;. there are other special purpose registers that we'll talk about as we move along, but you get the idea.&lt;br/&gt;&lt;br /&gt;so writing an assembly language program is like shuffling paperwork around. you copy data into a register, you tell the cpu to process it, then you do something (or nothing, if you wish) with the result. here is a simple set of instructions that you'll see frequently in assembler. we'll talk about what it does next time.&lt;br /&gt;&lt;pre id="code" style="width: 52em;"&gt;&lt;br /&gt;1  ; These instructions are commonly found in DOS programs.&lt;br /&gt;2                  mov     ax, 4c00h&lt;br /&gt;3                  int     21h&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-style:italic; color: navy"&gt;segments&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;another thing you must know is how dos accesses memory. to &lt;span style="font-weight: bold;"&gt;mov&lt;/span&gt; (copy) data to or from ram you need an address. since dos uses 16-bit registers, the largest address it can work with is 16 bits long, so dos can address up to 65,536 (64k) bytes of ram. that's it. a long time ago 64k was a lot. remember all the great programs we ran on the &lt;a href="http://www.commodoreusa.net"&gt;commodore 64&lt;/a&gt;? but as consumers demanded more from their applications 64k became a barrier. dos handles this by viewing memory as a series of segments, each 64kb in size. a program can contain many segments of code and data so long as none of them exceeds 64kb.&lt;br/&gt;&lt;br /&gt;to address memory, then,  we need two registers: a special &lt;span style="font-style:italic;"&gt;segment&lt;/span&gt; register for the segment address and a normal general purpose register for the offset within that segment. if the &lt;span style="font-weight:bold;"&gt;ds&lt;/span&gt; register, which points to a &lt;span style="font-style:italic;"&gt;data segment&lt;/span&gt;, contains &lt;span style="font-weight:bold;"&gt;24a0h&lt;/span&gt; and we &lt;span style="font-weight:bold;"&gt;mov&lt;/span&gt; &lt;span style="font-weight:bold;"&gt;0fh&lt;/span&gt; into register &lt;span style="font-weight:bold;"&gt;dx&lt;/span&gt;, then &lt;span style="font-weight:bold;"&gt;ds:dx&lt;/span&gt; refers to the 16th byte of that segment, written as &lt;span style="font-weight:bold;"&gt;24a0:000fh&lt;/span&gt;. if we later load &lt;span style="font-weight:bold;"&gt;ds&lt;/span&gt; with &lt;span style="font-weight:bold;"&gt;4110h&lt;/span&gt; we'll find that &lt;span style="font-weight:bold;"&gt;ds:dx&lt;/span&gt; now points to &lt;span style="font-weight:bold;"&gt;4110:000fh&lt;/span&gt;. it's not too complicated, but it's up to the programmer to keep track of which segment he's using at any point in time. fortunately you need not know the exact addresses of your segments (dos actually determines that at runtime, so there &lt;em&gt;is&lt;/em&gt; no way you could know as you're writing your source.) in assembler we use &lt;span style="font-style:italic;"&gt;labels&lt;/span&gt;, friendly names to refer to addresses. so you may see code like the following to initialize the data segment register:&lt;br /&gt;&lt;pre id="code" style="width: 52em;"&gt;&lt;br /&gt;4  ; Load the DS register with the address of the data segment.&lt;br /&gt;5                  mov     ax, data        ; "data" is the address of our&lt;br /&gt;6                  mov     ds, ax          ; data segment&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold; font-style:italic; color: navy"&gt;stack&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;finally, there is the stack. this is a handy little place in ram to put things temporarily, such as when you want to pass data from one &lt;span style="font-style:italic;"&gt;procedure&lt;/span&gt; to another. we &lt;span style="font-weight:bold;"&gt;push&lt;/span&gt; data onto the stack to store it, and we &lt;span style="font-weight:bold;"&gt;pop&lt;/span&gt; data off of the stack to retrieve it. the stack is like that little cart with the clean plates at the head of a buffet line. the most recently cleaned plates are warm, damp and on the top of the stack, and the ones that have been there awhile and are much drier are at the bottom. when you take a plate off the top, you're taking the one that was most recently placed on the stack.&lt;br/&gt;&lt;br /&gt;data stacks work the same way. the topmost item is the most recently pushed data, the oldest data is at the bottom. data is always popped in reverse order from how it was pushed onto the stack. &lt;br/&gt;&lt;br /&gt;of course, we all know what happens when you put too many plates in a stack on one of those carts. bad, loud things happen. if we were to overfill our stack segment in our program, we could overwrite some other segment, or worse, some other program's segment. this could also lead to bad, loud things, so the intel cpu does a funny thing when it sets up the stack: it fills it backward, from the top down. you need to see this to get it&amp;#133;&lt;br/&gt;&lt;br /&gt;let's say that you decide to create a stack segment for your program that is only four bytes long (don't use such a small stack in real life.) the &lt;span style="font-weight:bold;"&gt;ss&lt;/span&gt; register (stack segment) will contain the address of the beginning, or bottom of the stack. the first byte would be at &lt;span style="font-weight:bold;"&gt;ss:0h&lt;/span&gt;, the second at &lt;span style="font-weight:bold;"&gt;ss:1h&lt;/span&gt;, the third at &lt;span style="font-weight:bold;"&gt;ss:2h&lt;/span&gt; and the fourth at &lt;span style="font-weight:bold;"&gt;ss:3h&lt;/span&gt;. the &lt;span style="font-style:italic;"&gt;stack pointer&lt;/span&gt; (another register called &lt;span style="font-weight:bold;"&gt;sp&lt;/span&gt;) will point to the top of the stack, &lt;span style="font-weight:bold;"&gt;4h&lt;/span&gt;.&lt;br/&gt;&lt;br /&gt;"wait!" you cry. "4h isn't in the stack segment, because it's only four bytes long!" you're right. what's at the address that &lt;span style="font-weight:bold;"&gt;sp&lt;/span&gt; is pointing to right now? we don't know for sure. "isn't that dangerous?" you ask. perhaps, but wait until you see how the thing comes off.&lt;br/&gt;&lt;br /&gt;when we push a byte onto the stack, &lt;span style="font-weight:bold;"&gt;sp&lt;/span&gt; is first &lt;span style="font-style:italic;"&gt;decremented&lt;/span&gt;, so now it points to &lt;span style="font-weight:bold;"&gt;3h&lt;/span&gt;. then the pushed data is copied to &lt;span style="font-weight:bold;"&gt;3h&lt;/span&gt;. see? everything is okay, because we don't actually write to &lt;span style="font-weight:bold;"&gt;4h&lt;/span&gt;, so we don't corrupt some other program's stuff. when we push a second byte, &lt;span style="font-weight:bold;"&gt;sp&lt;/span&gt; is decremented and the new data is written to &lt;span style="font-weight:bold;"&gt;2h&lt;/span&gt;. when we pop the data off of the stack, the data that &lt;span style="font-weight:bold;"&gt;sp&lt;/span&gt; points to at &lt;span style="font-weight:bold;"&gt;2h&lt;/span&gt; is copied and &lt;span style="font-weight:bold;"&gt;sp&lt;/span&gt; is &lt;span style="font-style:italic;"&gt;incremented&lt;/span&gt; to point to &lt;span style="font-weight:bold;"&gt;3h&lt;/span&gt;. but what if we try to push more than four bytes onto the stack? well, consider that when the fourth byte is pushed &lt;span style="font-weight:bold;"&gt;sp&lt;/span&gt; has been decremented four times, so it now points to &lt;span style="font-weight:bold;"&gt;0h&lt;/span&gt;. any attempt to decrement &lt;span style="font-weight:bold;"&gt;sp&lt;/span&gt; again will set the &lt;span style="font-style:italic;"&gt;overflow flag&lt;/span&gt; in the flags register, and dos will crash your program with a &lt;span style="font-style:italic;"&gt;stack overflow&lt;/span&gt; error. your program valiantly falls on its own sword to keep from doing bad things to other programs. of course, there is nothing to keep you from popping the data at &lt;span style="font-weight:bold;"&gt;4h&lt;/span&gt; before you've pushed anything onto the stack. just expect really bad things to happen when you try to use that unknown value. it's best to not go there.&lt;br/&gt;&lt;br /&gt;why use the stack if it's so much potential trouble? remember that programs love it, more than programmers love their buffets. sometimes procedures pass parameters by the stack so that they can do things.  after branching to another line of execution the stack can act like a trail of breadcrumbs, helping your code to wend its way back to where it came from. even if you never consciously use it, the services you request through dos or bios interrupts will use the stack. buck up, young padawan: you can't escape your destiny.&lt;br/&gt;&lt;br /&gt;now then, you're all set to write your first program in assembly language&amp;#133;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5089178761965217498-7875456369636539056?l=mechatechzilla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mechatechzilla.blogspot.com/feeds/7875456369636539056/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mechatechzilla.blogspot.com/2010/04/assembler-tutorial-intro-2-of-2.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/7875456369636539056'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/7875456369636539056'/><link rel='alternate' type='text/html' href='http://mechatechzilla.blogspot.com/2010/04/assembler-tutorial-intro-2-of-2.html' title='assembler tutorial: intro 2 of 2'/><author><name>mechatechzilla</name><uri>http://www.blogger.com/profile/17585447008783853422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://1.bp.blogspot.com/_jbCdMAhJU58/SpM-dMKvHKI/AAAAAAAABCw/fJGkIdcMqCE/S220/red_shirt.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5089178761965217498.post-8417375472539318862</id><published>2010-03-30T21:42:00.016-05:00</published><updated>2010-04-02T19:55:08.340-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='dos'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='assembly language'/><title type='text'>assembler tutorial: intro 1 of 2</title><content type='html'>&lt;p&gt;&lt;span style="font-style:italic; font-weight: bold; color: darkviolet;"&gt;assembled 'neath a dark, foreboding sky&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;as promised, a little dos and linux assembly language tutorial in several verses for your consideration. mostly dos though, for that is where my dark past lies, but a little linux is good for the soul (and the understanding.) before we begin in earnest, two things:&lt;br/&gt;&lt;hr/&gt;&lt;br /&gt;first, assemble (huh) your 'a' team, the tools you will need to code along with me. since i work on mac, linux and vista platforms i find great comfort in the familiarity of a singular environment across all machines that i (might) happen to be writing code on at the moment. for this, i use &lt;a href="http://www.dosbox.com/download.php?main=1"&gt;dosbox&lt;/a&gt;, a great little dos + x86 emulator. it may have been primarily designed for running classic games like wolfenstein or ega trek, but it makes for a pretty decent development platform, too.&lt;br/&gt;&lt;br /&gt;to write your code you'll need a text editor. alas, a good dos text editor for writing assembler is only a pipe dream (this used to not be the case, but i can't find my old tools anymore.) &lt;a href="http://www.xs4all.nl/~ferguson/freeware/editv41u.zip"&gt;editv&lt;/a&gt;, however, does provide must-have line numbering and is one of the easiest editors to use. i still prefer vim, but the dos version of it is really lame and i don't intend to teach vi editing in this blog.&lt;br/&gt;&lt;br /&gt;we'll be writing code specifically to be assembled by &lt;a href="http://sourceforge.net/projects/nasm/files/DOS%2032-bit%20binaries/2.07/nasm-2.07-dos.zip/download"&gt;nasm, the netwide assembler&lt;/a&gt;. &lt;img src="http://upload.wikimedia.org/wikipedia/commons/thumb/2/28/HelloWorld.svg/200px-HelloWorld.svg.png" alt="Hello World Text" style="float:left; width: 100px; padding: 5px; border: 0px;"&gt; there is no such thing as "standard assembler syntax," so every assembler has its own idiosyncrasies. one of the reasons i'm writing these tutorials is to teach myself nasm: i actually learned on &lt;a href="http://en.wikipedia.org/wiki/Turbo_Assembler"&gt;tasm&lt;/a&gt; and worked on &lt;a href="http://en.wikipedia.org/wiki/MASM"&gt;masm&lt;/a&gt; in the bronze age of computing. the concepts are the same and linguistic differences are often minor, so it's nothing to break a sweat over.&lt;br/&gt;&lt;br /&gt;some of the programs we write will require a &lt;a href="http://en.wikipedia.org/wiki/Linker_(computing)"&gt;linker&lt;/a&gt;. i'm using the public domain &lt;a href="http://www.devoresoftware.com/freesource/wlsrc.htm"&gt;warplink&lt;/a&gt; for this. and finally, since most of these utilities are packaged as .zip files, we'll snag the darling of dos &lt;a href="http://en.wikipedia.org/wiki/Bulletin_board_system"&gt;bbses&lt;/a&gt; the world over, &lt;a href="http://files.oldos.org/files/dos/pk250dos.exe"&gt;pkzip&lt;/a&gt; (the second-finest piece of dos shareware ever written.)&lt;br/&gt;&lt;br /&gt;install dosbox and create a folder in your home directory to keep your work in. i called mine &lt;span style="font-style:italic;"&gt;dos&lt;/span&gt;. edit the dosbox configuration file by adding a few lines after the [autoexec] section at the very end. mine automatically mounts my dos directory as drive c and adds several directories to my path variable, like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;[autoexec]&lt;br /&gt;# Lines in this section will be run at startup.&lt;br /&gt;@echo off&lt;br /&gt;mount c ~/dos&lt;br /&gt;c:&lt;br /&gt;set PATH=%PATH%;C:\NASM;C:\WARPLINK;C:\EDITV;C:\PKZIP;C:\BIN&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;once you've done this you can start dosbox (which should drop you into your c drive) and use the dos command &lt;b&gt;md&lt;/b&gt; to create the directories nasm, warplink, editv, pkzip, bin, and mycode. run the command &lt;b&gt;dir&lt;/b&gt; and ensure that eight directories exist (this number includes the . and the .. directories.)&lt;br/&gt;&lt;br /&gt;copy pk250dos.exe to the dos/PKZIP directory and run the executable inside dosbox. you will find that when you modify the dos filesystem from your host operating system &lt;span style="font-style:italic;"&gt;outside&lt;/span&gt; dosbox, those changes don't appear when you list the directory &lt;span style="font-style:italic;"&gt;inside&lt;/span&gt; dosbox. dos likes to cache the directory lists to speed things along, so if it is unaware of changes you made from outside the environment it pretends that they aren't there (they really are.) to force the changes to appear you can clear the directory cache with the &lt;span style="font-weight:bold;"&gt;rescan&lt;/span&gt; command.&lt;br/&gt;&lt;br /&gt;copy the rest of the programs listed above to their respective directories and, in dos, run &lt;span style="font-weight:bold;"&gt;rescan&lt;/span&gt; and unzip each of them like this example:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;C:\EDITV&gt;pkunzip editv41u.zip&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;when all this is done, close and reopen dosbox (you can type 'exit' at the dos prompt to close) and verify that you can run all these programs from the root directory of drive c by just typing their names: editv, nasm, and warplink. if you run into any dosbox trouble, refer to this &lt;a href="http://ipggi.wordpress.com/2008/02/17/dosbox-beginners-newbie-and-first-timers-guide/"&gt;little article&lt;/a&gt;. if everything works as expected, your path is set up correctly, your team is assembled (huh) and you're&amp;#133; almost&amp;#133; ready to begin&amp;#133;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5089178761965217498-8417375472539318862?l=mechatechzilla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mechatechzilla.blogspot.com/feeds/8417375472539318862/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mechatechzilla.blogspot.com/2010/03/1-assembled-neath-dark-forboding-sky.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/8417375472539318862'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/8417375472539318862'/><link rel='alternate' type='text/html' href='http://mechatechzilla.blogspot.com/2010/03/1-assembled-neath-dark-forboding-sky.html' title='assembler tutorial: intro 1 of 2'/><author><name>mechatechzilla</name><uri>http://www.blogger.com/profile/17585447008783853422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://1.bp.blogspot.com/_jbCdMAhJU58/SpM-dMKvHKI/AAAAAAAABCw/fJGkIdcMqCE/S220/red_shirt.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5089178761965217498.post-1759123919975684902</id><published>2010-03-21T19:59:00.003-05:00</published><updated>2010-03-27T10:44:31.847-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='assembly language'/><category scheme='http://www.blogger.com/atom/ns#' term='c'/><title type='text'>small packages, part 2</title><content type='html'>a while back i said that i like small programs that waste neither space nor cpu cycles. from the file on &lt;i&gt;stupid computer tricks&lt;/i&gt; comes the extreme case: &lt;a href="http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html"&gt;the smallest possible linux program that actually does something.&lt;/a&gt;&lt;br /&gt;&lt;br&gt;the exercise documented in this article (updated for 2009) is purely academic, but it demonstrates some uncommon ingenuity, and i think that's cool. and this recent blog post is moving along the same lines: &lt;a href="http://blog.ksplice.com/2010/03/libc-free-world/"&gt;programming in c with no cumbersome libraries.&lt;/a&gt; not really practical for large projects where the standard library accounts for a negligible part of program size and the benefits far outweigh the drawbacks, but still this is an interesting effort. it also caused me to dig out my old assembly language books. i think i'm going to write some tutorials on intel assembler over the next few months. we'll look at making programs for dos and linux.&lt;br /&gt;&lt;br&gt;aww, c'mon! it'll be fun!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5089178761965217498-1759123919975684902?l=mechatechzilla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mechatechzilla.blogspot.com/feeds/1759123919975684902/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mechatechzilla.blogspot.com/2010/03/small-packages-part-2.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/1759123919975684902'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/1759123919975684902'/><link rel='alternate' type='text/html' href='http://mechatechzilla.blogspot.com/2010/03/small-packages-part-2.html' title='small packages, part 2'/><author><name>mechatechzilla</name><uri>http://www.blogger.com/profile/17585447008783853422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://1.bp.blogspot.com/_jbCdMAhJU58/SpM-dMKvHKI/AAAAAAAABCw/fJGkIdcMqCE/S220/red_shirt.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5089178761965217498.post-7125308597332256747</id><published>2009-10-12T08:45:00.002-05:00</published><updated>2010-03-21T19:53:35.236-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='law'/><category scheme='http://www.blogger.com/atom/ns#' term='network'/><category scheme='http://www.blogger.com/atom/ns#' term='bofh'/><category scheme='http://www.blogger.com/atom/ns#' term='administration'/><category scheme='http://www.blogger.com/atom/ns#' term='usb'/><title type='text'>it's the law (2 of 2)</title><content type='html'>&lt;div style="font-family: sans-serif;"&gt;&lt;br /&gt;&lt;b&gt;ritter's second law of network administration:&lt;/b&gt; &lt;i&gt;if you give a user something to click, they'll click it.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;img style="width: 120px; float: left; padding: 8px;" src="http://geekofriendly.files.wordpress.com/2008/06/no-mouse-allowed.jpg"/&gt;for all the complaints we make about them, users can be a resourceful lot. they seem to find all kinds of ways to get themselves into trouble, from making their desktop fonts so large that windows no longer fit on the screen to sticking a usb drive into the ethernet port on the side of a laptop and griping that the computer doesn't "see" the thumb drive anymore. it's this cleverness for getting themselves into a situation and their unwillingness to extricate themselves from it that leads me to my second law.&lt;br /&gt;&lt;br /&gt;the problem is endemic: humans are attracted to something new and different. i have a ball-point pen that has a little blinking blue light on one end. i have no idea what purpose the cool blinking light serves, except that it made me buy the thing. users, too, will succumb to new icons, buttons, or anything that looks extraordinary, and they often end up sticking their mouse pointer where it doesn't belong.&lt;br /&gt;&lt;br /&gt;the simple administrative solution is to hide things you don't want users to see. both windows and linux have policy tools that allow an administrator to remove features from the user's desktop, reducing the probability that they'll click the wrong thing. this is &lt;em&gt;not&lt;/em&gt; a substitute for security: permissions and rights should still be configured to prevent a user from doing anything to the computer that's not in their job description. but if we can save just one harried help-desk employee the horror of a single clueless call, our work will have been worth the effort.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;corollary to ritter's second law:&lt;/b&gt; &lt;i&gt;all users lie.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;img style="float: right; width: 200px; padding: 8px;" src="http://www.claybennett.com/images/archivetoons/polygraph.jpg"/&gt;as admins, we have all heard, "i didn't do anything. it just started acting like this." this is the silliest game we are forced to play. they know they're lying, and they know that &lt;em&gt;you&lt;/em&gt; know they're lying. even though you're there to help them solve a problem they won't come clean and give you the information you need to fix it. while they wanly try to save face, you have to dig for the data that leads to a solution. the more they try to stroke their self-esteem to come across as "not dumb," the dumber they look. and the higher the position they hold in the company, the more indignant they become with you for giving them a "broken" system and not fixing it faster.&lt;br /&gt;&lt;br /&gt;unfortunately, there is little we can do about this one. you can try the honest approach: let them know that you're there to help, that you know they're not stupid, that you just need to know what they've been doing on the computer to get it into its current state. you can even tell them that you'll find out eventually, so it would be better to just let it come out now. you may even add threats, like "if you can't tell me what you did to the computer, once i find out i'll have to discuss this with your superior to make sure it doesn't happen again." that might scare the pr0n right off of their hard drive.&lt;br /&gt;&lt;br /&gt;or, just do your job, then go to the server room, lock the door and content yourself with fantasizing about doing &lt;a href="http://members.iinet.net.au/~bofh/"&gt;unkind things&lt;/a&gt; to your users.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5089178761965217498-7125308597332256747?l=mechatechzilla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mechatechzilla.blogspot.com/feeds/7125308597332256747/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mechatechzilla.blogspot.com/2009/10/its-law-2-of-2.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/7125308597332256747'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/7125308597332256747'/><link rel='alternate' type='text/html' href='http://mechatechzilla.blogspot.com/2009/10/its-law-2-of-2.html' title='it&apos;s the law (2 of 2)'/><author><name>mechatechzilla</name><uri>http://www.blogger.com/profile/17585447008783853422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://1.bp.blogspot.com/_jbCdMAhJU58/SpM-dMKvHKI/AAAAAAAABCw/fJGkIdcMqCE/S220/red_shirt.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5089178761965217498.post-8628256036700472285</id><published>2009-10-07T12:33:00.003-05:00</published><updated>2009-10-07T14:35:17.136-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='powershell'/><category scheme='http://www.blogger.com/atom/ns#' term='law'/><category scheme='http://www.blogger.com/atom/ns#' term='network'/><category scheme='http://www.blogger.com/atom/ns#' term='bash'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='administration'/><title type='text'>it's the law (1 of 2)</title><content type='html'>&lt;div style="font-family: sans-serif;"&gt;&lt;b&gt;ritter's first law of network administration:&lt;/b&gt; &lt;i&gt;an administrator at rest tends to stay at rest.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;img style="padding: 8px; width: 192px; float: right;" src="http://www.coprolite.com/zhb/pooldog/grnscn.jpg" /&gt;an administrator's day could easily be consumed with all the little, mundane tasks that are necessary to keep things running smoothly. backing up servers, reading log files, preparing reports on resource utilization, playing &lt;a href="http://www.worldofwarcraft.com/index.xml"&gt;world of warcraft&lt;/a&gt;—it all really eats into one's time. that's why i formulated my first law of network administration. i noted that, as a network admin, when things could pretty much take care of themselves, i could relax and better savor the more fulfilling moments of my job, like reducing a user's disk quota or reading a user's more provocative email messages. here is a short alliterative list of tips to help you achieve network nirvana:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;em style="color: maroon;"&gt;aggregate:&lt;/em&gt; duplicating work increases the likelihood that you'll introduce errors and inconsistencies into your network's security, which is a bad idea no matter how you slice it. instead...&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;locate shared resources that have common security requirements in the same directory structure on your file server. set access permissions only once on the highest-level directory that these files have in common. use permission inheritance to ensure consistent security on all the files in the hierarchy.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;don't assign permissions directly to users. add users to appropriate groups and assign permissions to the groups. that way you need only add a user to a group to ensure that all the access they require is properly configured.&lt;/li&gt;&lt;/ol&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;em style="color: green;"&gt;automate:&lt;/em&gt; do nothing by hand if possible, because hands can be so mistake-prone sometimes. learn a scripting language and write (or download and customize) scripts to perform common, repetitive tasks like reading log files and collecting report data. if you administer a windows network, you &lt;em&gt;must&lt;/em&gt; learn &lt;a href="http://www.centriq.com/Courses/MS-50025A.aspx?tID=2146161530"&gt;powershell&lt;/a&gt;. it's available for windows versions from xp onward, and is the "wave of the future." if you administer a linux network, you &lt;em&gt;must&lt;/em&gt; learn &lt;a href="http://tldp.org/LDP/abs/html/"&gt;bash&lt;/a&gt;. if you manage a mixed environment, i strongly recommend that you learn &lt;a href="http://www.greenteapress.com/thinkpython/"&gt;python&lt;/a&gt;—it's sufficiently platform-independent and very mature, with a smörgåsbord of cool features built in.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;em style="color: navy;"&gt;alert:&lt;/em&gt; let your network tell you when there are problems. install a &lt;a href="http://www.bb4.com/"&gt;network monitor system&lt;/a&gt; that's capable of notifying you when your file and email servers run low on disk space, or when your web server stops responding. when you can address a problem before your users even know it's there, they'll come to respect your precognitive powers  and revere you for the system superhero you really are.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;well, that last one, not really, because they won't &lt;em&gt;know&lt;/em&gt; there was a problem in the first place, right? but hey, we're geeks: we're good at fantasy. now roll a d20 to see whether your invisibility-from-lumbergh spell worked before he asks for those tps reports. again.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5089178761965217498-8628256036700472285?l=mechatechzilla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mechatechzilla.blogspot.com/feeds/8628256036700472285/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mechatechzilla.blogspot.com/2009/10/its-law-1-of-2.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/8628256036700472285'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/8628256036700472285'/><link rel='alternate' type='text/html' href='http://mechatechzilla.blogspot.com/2009/10/its-law-1-of-2.html' title='it&apos;s the law (1 of 2)'/><author><name>mechatechzilla</name><uri>http://www.blogger.com/profile/17585447008783853422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://1.bp.blogspot.com/_jbCdMAhJU58/SpM-dMKvHKI/AAAAAAAABCw/fJGkIdcMqCE/S220/red_shirt.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5089178761965217498.post-6633151094694000784</id><published>2009-09-24T21:50:00.007-05:00</published><updated>2009-09-24T22:34:08.560-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='server'/><category scheme='http://www.blogger.com/atom/ns#' term='mysql'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='lamp'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><category scheme='http://www.blogger.com/atom/ns#' term='apache'/><category scheme='http://www.blogger.com/atom/ns#' term='database'/><title type='text'>um, you rub it and make a wish...</title><content type='html'>&lt;div style="font-family: sans-serif;"&gt;today i needed a &lt;a href="http://en.wikipedia.org/wiki/LAMP_(software_bundle)"&gt;lamp&lt;/a&gt;. that's an acronym that refers to a special kind of server, one that contains a server operating system, a database server, a web server, and a web development framework. most of the web servers you interact with on the internet today use a suite, or "stack" of tools like this. and i needed one.&lt;br /&gt;&lt;br /&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 192px; height: 320px;" src="http://2.bp.blogspot.com/_jbCdMAhJU58/Srw2_O1PLGI/AAAAAAAABDU/WnxJYtIZYHA/s320/aladingenie2.gif" border="0" alt="" id="BLOGGER_PHOTO_ID_5385239714369317986" /&gt;now, i can build a lamp server from scratch: configure a base os; install a web service and database; install the web modules to access the database; install the web application framework; install the web modules to interface with the framework; and configure all the pieces to play well together. frankly, i can think of better things to do with my time, so i headed over to &lt;a href="http://www.turnkeylinux.org/"&gt;turnkeylinux.org&lt;/a&gt; and downloaded their prebuilt lamp installer. boy, was i impressed! the installation was fast, painless, and almost hands-free. in less than twenty minutes i had a working server, ready to hand out interactive web pages.&lt;br /&gt;&lt;br /&gt;the webmin administrative interface is really slick: a far cry from where it was when i last used it at the turn of the century (i like saying that.) it took me a couple of minutes of poking around to figure out how to add packages through webmin, which appears to be a necessity since the system didn't seem to recognize the things i installed "manually" using &lt;i&gt;apt-get.&lt;/i&gt;&lt;a href="http://www.turnkeylinux.org/appliances/lamp"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 106px; height: 111px;" src="http://cdn.turnkeylinux.org/files/images/icons/lamp.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;this product really exceeded my expectations. i could install and configure lamp servers all day like this. and considering that this is open source software that's easy on hardware resources, it would be a great virtual server solution and provide an impressive roi. maybe not as cool as rubbing it and having a genie pop out, but almost.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5089178761965217498-6633151094694000784?l=mechatechzilla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mechatechzilla.blogspot.com/feeds/6633151094694000784/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mechatechzilla.blogspot.com/2009/09/um-you-rub-it-and-make-wish.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/6633151094694000784'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/6633151094694000784'/><link rel='alternate' type='text/html' href='http://mechatechzilla.blogspot.com/2009/09/um-you-rub-it-and-make-wish.html' title='um, you rub it and make a wish...'/><author><name>mechatechzilla</name><uri>http://www.blogger.com/profile/17585447008783853422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://1.bp.blogspot.com/_jbCdMAhJU58/SpM-dMKvHKI/AAAAAAAABCw/fJGkIdcMqCE/S220/red_shirt.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_jbCdMAhJU58/Srw2_O1PLGI/AAAAAAAABDU/WnxJYtIZYHA/s72-c/aladingenie2.gif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5089178761965217498.post-5894518333221836236</id><published>2009-09-03T19:19:00.002-05:00</published><updated>2010-03-21T20:36:06.128-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='buzzwords'/><category scheme='http://www.blogger.com/atom/ns#' term='eyeos'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><category scheme='http://www.blogger.com/atom/ns#' term='cloud computing'/><title type='text'>i've looked at clouds from both sides now</title><content type='html'>&lt;span style="font-family:verdana;"&gt;i like saying buzzwords. not because i have any practical use for them, just because it's fun. it's entertaining when standing around at some quasi-professional gathering to work a phrase like "cloud computing" into the conversation. the other person's eyes glaze over, a little dollop of spittle forms at the corner of their mouth, and they become totally engrossed in whatever i have to say. i have become the subject matter expert, and they are now completely in my power. well, we all have our hobbies.&lt;br /&gt;&lt;br /&gt;really, one of mine is finding new and innovative ways to do things. i ran across &lt;a href="http://eyeos.info/"&gt;eyeos&lt;/a&gt; rather by accident, but was intrigued by the possibility of putting the whole os "in the cloud" on a local network. yes, it &lt;em&gt;is&lt;/em&gt; reminiscent of the &lt;a href="http://en.wikipedia.org/wiki/Dumb_terminal#Dumb_terminal"&gt;dumb term&lt;/a&gt;&lt;/span&gt;&lt;span style="font-family:verdana;"&gt;&lt;a href="http://en.wikipedia.org/wiki/Dumb_terminal#Dumb_terminal"&gt;in&lt;/a&gt;&lt;/span&gt;&lt;span style="font-family:verdana;"&gt;&lt;a href="http://en.wikipedia.org/wiki/Dumb_terminal#Dumb_terminal"&gt;als&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Time-sharing"&gt;time-sharing&lt;/a&gt; systems of yore, but still, an operating system that runs in a web browser has some appeal.&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://eyeos.org/"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 120px; height: 86px;" src="http://www.drakonworld.com/files/images/eyeos_1.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;&lt;br /&gt;now, i know that it's not the right call for everyone. i certainly don't have any practical use for this right now, myself. but it &lt;em&gt;has&lt;/em&gt; got me thinking, and i l&lt;/span&gt;&lt;span style="font-family:verdana;"&gt;ike that. it's also caused me to take an interest i&lt;/span&gt;&lt;span style="font-family:verdana;"&gt;n &lt;a href="http://www.php.net/"&gt;php scripting&lt;/a&gt;, the heart of eyeos applications—and being motivated to learn something new is always cool.&lt;br /&gt;&lt;br /&gt;'cause when we stop learning, we start dying.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5089178761965217498-5894518333221836236?l=mechatechzilla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mechatechzilla.blogspot.com/feeds/5894518333221836236/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mechatechzilla.blogspot.com/2009/09/ive-looked-at-clouds-from-both-sides.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/5894518333221836236'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/5894518333221836236'/><link rel='alternate' type='text/html' href='http://mechatechzilla.blogspot.com/2009/09/ive-looked-at-clouds-from-both-sides.html' title='i&apos;ve looked at clouds from both sides now'/><author><name>mechatechzilla</name><uri>http://www.blogger.com/profile/17585447008783853422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://1.bp.blogspot.com/_jbCdMAhJU58/SpM-dMKvHKI/AAAAAAAABCw/fJGkIdcMqCE/S220/red_shirt.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5089178761965217498.post-6214806513171640832</id><published>2009-08-31T18:07:00.003-05:00</published><updated>2009-08-31T18:07:00.295-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='analogx'/><category scheme='http://www.blogger.com/atom/ns#' term='freeware'/><category scheme='http://www.blogger.com/atom/ns#' term='code bloat'/><title type='text'>small packges</title><content type='html'>&lt;font face="verdana"&gt;i never was a fan of code bloat. i've written programs for dos in x86 assembler and for the palm os in c. i've had to deal with some pretty tight constraints, but i don't take space, memory or cpu cycles for granted. and i guess that's what bothers me about the current conventional coding wisdom that seems to be, "if you've got the space, use it." i think it unfortunate that what passes for acceptable code these days is poor planning and laziness on the part of some visual studio jockey who has no clue how a compiler even works—heaven forbid they ever have to compile and link &lt;em&gt;by hand&lt;/em&gt;. i guess this is where i talk about having to write code in hex using only the dos debugger uphill both ways in the snow.&lt;br /&gt;&lt;br /&gt;i'm &lt;/font&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.analogx.com"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 88px; height: 31px;" src="http://www.analogx.com/contents/graphics/linkus/insight-b.gif" alt="" border="0"&gt;&lt;/a&gt;&lt;font face="verdana"&gt;glad i'm not the only one that appreciates a dainty code footprint. &lt;a href="http://www.analogx.com/"&gt;analogx&lt;/a&gt; is the creator of some great and useful (and free) programs that pack heavyweight features into featherweight packages. in my classrooms, for instance, i don't waste time with microsoft's iis: the anaolgx &lt;a href="http://www.analogx.com/contents/download/Network/sswww/Freeware.htm"&gt;simpleserver:www&lt;/a&gt; web server supports mime, logging, server-side scripting and multi-hosting, and it runs on any version of windows from win95 up. did i mention that the whole program is 630k? that's kilobytes, my friend. i've long believed that a web site should be capable of fitting on a 1.44mb floppy disk. how 'bout the server, as well?&lt;br /&gt;&lt;br /&gt;the point is, there is no need for all this bloat. there is no reason an os should require a gigabyte of ram and 15 gigs of hard drive space. today's programmers are a lazy lot, it seems, but there are a few artisans out there who still know how to make good things come in small packages.&lt;br /&gt;&lt;/font&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5089178761965217498-6214806513171640832?l=mechatechzilla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mechatechzilla.blogspot.com/feeds/6214806513171640832/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mechatechzilla.blogspot.com/2009/08/small-packges.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/6214806513171640832'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/6214806513171640832'/><link rel='alternate' type='text/html' href='http://mechatechzilla.blogspot.com/2009/08/small-packges.html' title='small packges'/><author><name>mechatechzilla</name><uri>http://www.blogger.com/profile/17585447008783853422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://1.bp.blogspot.com/_jbCdMAhJU58/SpM-dMKvHKI/AAAAAAAABCw/fJGkIdcMqCE/S220/red_shirt.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5089178761965217498.post-2592402225011143566</id><published>2009-08-28T18:33:00.007-05:00</published><updated>2010-03-21T19:59:27.162-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='open source'/><category scheme='http://www.blogger.com/atom/ns#' term='portable apps'/><category scheme='http://www.blogger.com/atom/ns#' term='usb'/><title type='text'>take your pc everywhere</title><content type='html'>&lt;span style="font-family:verdana;"&gt;we use &lt;a href="http://en-us.www.mozilla.com/en-US/"&gt;firefox&lt;/a&gt;. it has great add-ons like &lt;a href="http://www.zotero.org/"&gt;zotero&lt;/a&gt;, a tool for organizing your online research, or &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/1696"&gt;full screen homestar runner&lt;/a&gt; so you can watch &lt;a href="http://www.homestarrunner.com/"&gt;strong bad emails&lt;/a&gt; in all their glory. we use &lt;a href="http://www.openoffice.org/"&gt;openoffice&lt;/a&gt;. it supports the&lt;a href="http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=office"&gt; open document format&lt;/a&gt;, it allows you to publish your documents as &lt;a href="http://en.wikipedia.org/wiki/Portable_Document_Format"&gt;pdfs&lt;/a&gt;, and it's totally free—not to mention that it's the office suite that's used in the public libraries of our own and neighboring burgs. we also like &lt;a href="http://www.videolan.org/vlc/"&gt;vlc&lt;/a&gt;, which plays about every media format under the sun; &lt;a href="http://audacity.sourceforge.net/"&gt;audacity&lt;/a&gt;, a great audio editor; the &lt;a href="http://www.gimp.org/"&gt;gimp&lt;/a&gt;, every bit as good as photoshop but for one infinite-th the price (i.e. free); and we like to burn optical discs, check email, and so on.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;the problem is, not everyone agrees with our selection of software tools. some draconian schools and offices deploy only one option for a web browser or an office suite, and don't give you any choices. many of these pcs offer no photo or sound editing software at all, and certainly don't allow you to burn a cd. and what about all those customizations you spent hours making so that your software will work &lt;span style="font-style: italic;"&gt;for&lt;/span&gt; you rather than &lt;span style="font-style: italic;"&gt;against&lt;/span&gt; you? they don't just magically follow you to work or school.&lt;br /&gt;&lt;br /&gt;but they could.&lt;br /&gt;&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://portableapps.com/"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer;" src="http://www.thesmilingpirate.com/Blog/wp-content/uploads/2009/09/75px-portable_apps_logo1.png" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;enter &lt;a href="http://portableapps.com/"&gt;portableapps&lt;/a&gt;, the project that takes great open source software and makes it portable: that is, it runs directly off a usb flash drive with no installation required. carry your favorite customized programs and all your data with you everywhere you go. plug your drive into a windows pc and, voila! there are all your apps. the portableapps suite includes a menu that runs in your system tray, so your applications are always at your fingertips. and portableapps also runs on &lt;a href="http://www.winehq.org/"&gt;wine&lt;/a&gt;, so you can run your apps on a linux or mac computer where wine is installed.&lt;br /&gt;&lt;br /&gt;oh, and when you choose which programs to include in your portableapps system, make sure you grab the &lt;a href="http://www.clamwin.com/"&gt;clamwin&lt;/a&gt; virus scanner—you should always check your thumb drive for nastiness after you've plugged it into a strange computer. you never know where that thing's been.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5089178761965217498-2592402225011143566?l=mechatechzilla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mechatechzilla.blogspot.com/feeds/2592402225011143566/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mechatechzilla.blogspot.com/2009/08/take-your-pc-everywhere.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/2592402225011143566'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/2592402225011143566'/><link rel='alternate' type='text/html' href='http://mechatechzilla.blogspot.com/2009/08/take-your-pc-everywhere.html' title='take your pc everywhere'/><author><name>mechatechzilla</name><uri>http://www.blogger.com/profile/17585447008783853422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://1.bp.blogspot.com/_jbCdMAhJU58/SpM-dMKvHKI/AAAAAAAABCw/fJGkIdcMqCE/S220/red_shirt.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5089178761965217498.post-1264081234637384771</id><published>2009-08-24T20:41:00.006-05:00</published><updated>2009-08-26T12:09:29.775-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mac os x'/><category scheme='http://www.blogger.com/atom/ns#' term='unix'/><category scheme='http://www.blogger.com/atom/ns#' term='tablet pc'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>the tablet pc holy grail</title><content type='html'>&lt;span style="font-family:verdana;"&gt;for years i've wanted what i thought was a simple thing: a tablet pc running a unix system. unfortunately, the industry has failed to take notice of those of us who refuse to run the train-wreck-that-is-windows and provide us with a useful alternative. many linux aficionados have tried to take one of the readily-available systems and get this or that distribution to run nicely on it, but with proprietary drivers and a lack of manufacturer support, their efforts have met with varying degrees of (non)success. it seems that the tablet unix pc has become as unattainable as the holy grail, filthy english kiniggits and all.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;then, i hear the rumor: apple is planning a tablet pc, possibly one that runs the freebsd-based os x (&lt;a href="http://www.macrumors.com/2009/08/18/analyst-claims-two-apple-tablets-coming-one-with-6-inch-screen/"&gt;macrumors.com&lt;/a&gt;.) let the drooling begin. now my dilemma is that i don't know if i can wait; the old macbook pro really needs to be upgraded, and i considered buying a new one last week, which would have guaranteed me a permanent place in the doghouse. but, maybe if i hold out just a few more months, i can tell that silly arthur king when he comes around looking for the grail that i've "already got one."&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5089178761965217498-1264081234637384771?l=mechatechzilla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mechatechzilla.blogspot.com/feeds/1264081234637384771/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mechatechzilla.blogspot.com/2009/08/tablet-pc-holy-grail.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/1264081234637384771'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5089178761965217498/posts/default/1264081234637384771'/><link rel='alternate' type='text/html' href='http://mechatechzilla.blogspot.com/2009/08/tablet-pc-holy-grail.html' title='the tablet pc holy grail'/><author><name>mechatechzilla</name><uri>http://www.blogger.com/profile/17585447008783853422</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://1.bp.blogspot.com/_jbCdMAhJU58/SpM-dMKvHKI/AAAAAAAABCw/fJGkIdcMqCE/S220/red_shirt.jpg'/></author><thr:total>0</thr:total></entry></feed>
