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!
No comments:
Post a Comment