Sunday, October 14, 2007

Assembly Tutorial Part II - User Input

Assembly Tutorial 2


Press Any Key

I hope you enjoyed our first little foray into assembly with the obligatory "hello world" example. We're going to take a few things as given from here on out:


  • we're not concerned with the segment in debug

  • we'll assume you either remember how to create and save a file in debug or that you may refer to the first example

  • further discussion of the particulars of debug will be handled as the need arises or will be the subject of a separate tutorial page


I will also be including links to some external resources in a future post and as I get more of these short tutorials online I will have a proper table of contents in place for them. For now, though, we're going to proceed on an item-by-item basis with the int 21h features and hopefully end up with enough knowledge to build some semi-practical programs.



The Example


mov   dx, _message
mov ah, 09h
int 21h
mov ah, 01h
int 21h
mov ax, 4c00h
int 21h
_message "Press any key to continue...",
0ah, 0dh, 24h

A few things we need to address before proceeding:

a) you probably recognize the structure of the _message variable by now; but, where did our string terminator go?

b) further more, we seem to have some extraneous characters after our string

c) you're probably also wondering why we're not exiting our program in the same way as our last example


Well, these are all valid observations and speak to another facet of assembly programming. Since we're at such a low level-- really just above the actual processor level itself-- we see things much differently than a normal compiler. Whereas a C++ or BASIC compiler would just have our variable stored as a single type, we're combining a few elements: the string itself in quotes and the control codes in their native ASCII hexadecimal representation.

Remember that in C++ and BASIC, the string terminator is implied; that is to say that the compiler takes care of the boundaries for us. Here, we have to tell the machine-- or in this case, DOS, through the interrupts (or API, from our first lesson)-- where our string ends. So, the 0ah and 0dh are in fact a carriage return and line feed in ASCII. In Visual Basic this would simply be one character: VbCrLf; but, we're very low-level, remember.

The 24h character is actually the '$' in its native ASCII hexadecimal (ergo the 'h' in 24h). So, as you can see, we do have our string terminator, we've just chosen to represent it a bit differently for our example.


We're also not exiting our program in quite the same way as our last example. We're, in fact, using a different, more generally accepted, method for quitting our program. It's another service of DOS: 4ch. Remember that a service is basically a subroutine of the API. What we're actually doing when we call the DOS API with int 21h is asking it to perform a service. The number of the service is stored in the ax register and any information the service needs is provided either by filling the accompanying registers with the salient information or by pointing to the information using one of the registers. In this case we're calling service 4ch by filling the ah portion of the ax register with 4ch and the al portion with 00h. The al section (or nibble) of the ax register contains our return code. When we actually exit the program, we can tell DOS, or the program that called ours, if there was an error and, if so, what was it. So, this is a more accepted method of leaving a program: calling int 21h with ax = 4c00h.


The Process


Remember, we're taking as given that the segment in debug is superfluous information and I'm trusting that if you don't recall how to change file name and size you will refer to the first post. I hope that in this way we can keep the new information flowing as quickly and efficaciously as possible. So, with that having been said, let's open up our debug.exe again:


C:\>debug
-a
13E9:0100

And we'll begin assembling at our usual offset of 0100h, the standard for all .com files we'll be working with.


13E9:0100 mov dx,0110
13E9:0103 mov ah,09
13E9:0105 int 21
13E9:0107 mov ah,01
13E9:0109 int 21
13E9:010b mov ax,4c00
13E9:010e int 21
13E9:0110 db "Press any key to move on...",0a,0d,24
13E9:012e _

That's it. If you've entered everything correctly you should end up with 012e being the last line of code. Remember that we use this offset to determine our file size. We just subtract 0100 from it to get a file size of 2eh (46 decimal) bytes. I'll leave it to you to name the file what you want and save it.


The Explanation


We've upped the ante in this example and shown 3 procedures, or services, within DOS's int 21h API: service 09h from our first example - the print string service; service 01h - the read character input service (or one of the character input services as we'll find out shortly); and finally service 4ch - the terminate program with error code service. We refer to the service by its number which is what we use to populate the ah portion of the ax register prior to calling int 21h. Some services request information be passed via other registers or even memory addresses. We'll just learn one bit a time and by the time you're done with the full tutorial, you'll be expert in exactly which data are requested by which service.


In Summary


I said in the beginning that we're not concerned with the segment when working with int 21h or, more specifically, debug.exe. We're creating .com files which, by their very definition, can only occupy 1 segment. Again, the segment are those 4 hex characters before the colon on each line we input. The final file size will be determined by subtracting the last unused offset address from 0100h, which by default is the start offset for every .com file. The offset, remember, is the set of 4 characters after the colon so that our address in debug is:

{segment}:{offset}

We will continually reinforce many of the key aspects as well as introducing new elements so don't worry too much about being overwhelmed. As long as you can input the programs into debug as outlined in each tutorial section you'll be able to get "instant gratification" with working program segments. Feel free to play around with things like changing strings that are printed and where they're located in memory, etc. You'll be an assembly expert before you know it!



Saturday, October 6, 2007

Coffee! French Press How-To

In response to a tutorial request, I've prepared a simple how-to video for using a French press. All I have to say is: "Mmmm, coffee...".



Things to remember:
  • French press coffee is typically stronger than that made in a conventional coffee maker. This is because you let the grounds actually steep in the water directly and for minutes at a time versus slowly dripping water once through as with a conventional coffee maker. You may even expect to use less ground coffee this way.

  • There are no electrical or electronic components; it just needs a source of hot water. This makes a French press ideal for use as an emergency backup, or 'disaster recovery' system. Believe me I wish I'd had my French press during that big storm that knocked out all of our power; since our stove is gas and still worked despite there being no electricity. It can also come in handy for camping (even if it does seem a little less "masculine").

  • The carafe in the French press is glass. It's fragile, it can break if it's subjected to wild swings in temperature. Most importantly, it "remembers" flavors. If you plan on using a French press for coffee and tea-- or anything else for that matter-- plan on getting multiple presses or risk the flavors bleeding through (unless that's what you're after; in which case, game on!).

  • There's a little more work associated with properly cleaning and caring for a French press. The grounds like to get stuck between the filter mesh and the frame, so plan on having a few extra dishes and spending a little longer cleaning the filter.

  • Because there's no consumable filters, a French press is very "green"! There, I've said it. I've used the buzz word to end all buzz words; but, it's true. It uses less electricity or gas-- especially if you're using your hot water for other things. And there's less waste. Don't forget: coffee grounds make great compost fodder and are perfect for lowering soil pH. If you're going for blue hydrangeas, look no further!


And, while I realize I may not have a pretty mug-- at least I have a pretty mug to make up for it.

Wednesday, August 29, 2007

Assembly Tutorial Part I - Hello World!

Assembly Tutorial 1


Hello World!

This set of tutorials assumes that you have access to some version of DOS or Windows with the program debug.exe. We'll move from elementary level assembly which is based on operating system components and then move further into file access, hardware manipulation and computer science theory. We'll start with the ubiquitous and compulsory "Hello World!" programming example as a good, quick way to dive right into assembly coding with "instant gratification". First, the code itself:


The Example


mov   dx, _message
mov ah, 09h
int 21h
_message "Hello World!$"

There we have a working program which prints the sentence "Hello World!" to the screen. A few things to note about this program:



a) it may run properly and spit the text to the screen, but will most likely bomb immediately afterward

b) the "$" doesn't actually get printed-- it's what's called a string terminator

c) we're actually piggybacking existing library code in DOS with what is referred to as int 21

d) we have our first foray into pointers with this code

The Process


With all that having been said, let's move along full steam with our "instant gratification" portion. Don't worry as we'll gloss over many of the details under the assumption that you will continue reading this set of tutorials and will eventually acclimate by repetition, reinforcement and redundancy. On to debug.exe!


At the command prompt, type debug and hit enter. At the - prompt, type 'a' and hit enter. You should now see:



C:\>debug
-a
135C:0100

I'll spare you the full explanation this time around since we're not primarily concerned with debug.exe itself. Just take it as given that this is what we see when we open up debug to create a program. We'll come back to the specifics at a later time, I promise! For now, we can ignore the 4 digits before the colon on each line since it will usually be different for each machine and different each time we run debug.


At this point, we're ready to begin porting our code from the top of the page:


C:\>debug
-a
135C:0100 mov dx,0109
135C:0103 mov ah,09
135C:0105 int 21
135C:0107 int 20
135C:0109
-

On the last line (XXXX:0109; we're ignoring the first 4 digits, remember?) we'll just hit enter to skip past it. Again, we'll ignore the int 20 and we'll ignore the fact that this looks different from the code at the top of the page. You'll understand in due time, let's just get a working program!


Now we'll input the string to print. Let's start with the (now-familiar) 'a' at the prompt, this time with an address afterward:


-a 0109
135C:0109 db "Hello World!$"
135C:0116
-

We've almost got a fully working program. Actually, allow me to rephrase that: we have a fully working program, it's just that it only exists in memory and not on the disk. We'll use a couple of debug.exe-specific codes to actually save this program to disk and give it a test-drive!



-r cx
CX 0000
:0016
-n hello.com
-w
Writing 00016 bytes
-

All right, now we have a fully working program saved to disk and ready to go! Let's give it a test-drive and then, if you're at all interested, we'll go into some more detail about what makes this process tick!


-q

C:\>hello
Hello World!
C:\>

The Explanation


Success! We've covered some very basic assembly here and I believe we'll want to familiarize a little further with some key concepts before continuing. Let's return to that list of notes from earlier in the document and address those briefly.


a) the example program may run properly but will most likely bomb immediately afterward if it runs at all

  • This is because the example code was missing its end line. We corrected this with our debug version (and thus our saved program) by adding the 'int 20' line. More on this later.

b) the "$" doesn't actually get printed-- it's a terminator
  • In 16-bit DOS (which is what we're using or emulating to write our programs in debug.exe) strings end with a "$" character. This is ASCII code 24h (or 36 in decimal). You'll definitely want to remember that for future reference; but, don't worry, we'll touch on this several times in the future. This is just something Microsoft came up with to make sure the operating system knew when a sentence was finished so the program could stop printing. Think of the $STRING variables in BASIC.

c) we're actually piggybacking an existing library by running the int 21h functions
  • That's right. We're using Microsoft's API for 16-bit DOS. We start by loading values into the registers and then calling interrupt 21h to make it work. With DOS and int 21h, the AX register is used to select the procedure to run. In this case, we're using AH=09 which tells DOS to print text to the screen. More later on why it's called AX sometimes and AH others.

d) we have our first foray into pointers with this example
  • Yes, as scary as it sounds we've actually just jumped right into programming using pointers in our first example! Like the previous entry said, we use registers to select our procedure before "invoking" the DOS API with int 21h. In this example the DX register is a pointer to the start of our print string. Start at DX=0109 and stop when you get to the "$". That's it!



In Summary


That's enough for our first tutorial. We still have some ground to cover before this example is even fully explained; but, I hope I've whet your appetite for knowledge with this article. We'll hone in a little more on the 'why's and 'wherefore's of debug.exe, 16-bit DOS and assembly as well as some CPU and other hardware-related facets. Maybe if you stay tuned I'll be nice and throw in some crypto code and theory! Stay tuned!



Tuesday, August 28, 2007

Hello World!

Gotta start out with the compulsory classic. Here's the scoop: I'm not making any promises about what you'll find on this blog. If everything goes according to my (lack of a) very loose "plan" there will be some coding tutorials, some photos from my environment and just some random checking in with whatever's going on upstairs.
So check back in whenever you feel like it and I'll try to have some new content. Until then: cheers!