Coding and testing the procedure show_string

In this post, I will write about how I made the code of show_string in DEBUG.EXE and how to print a message on screen using INT 10h in 8086 assembly language.

In Fig. A you can see the coding of the show_string procedure. I started coding at address 0x0120 and, as usual, I couldn't guess the address of the jump ahead of the code while I was writing so I jumped to the same location where the jump instruction was (red) and then I fixed it at the end (light green). The backwards jump was immediately correct since the address location of the jump destination was available at the moment of coding (green).

Best practice with DEBUG.EXE
Fig. A

In the conclusion of the post "Coding and testing the procedure nibble_to_ASCII", I was commenting about the fact that a piece of code can be memory location independent or not. One feature that allows a piece of code to be memory location independent is the fact that some LOOP, CALL and JMP instructions (but not all of them) are expressed as a relative position to the IP value. With other words I coded at memory address SEG:012C in DEBUG the instruction JMP 0125 (and the u command showed it back as a string on the screen), but what happened in machine code was 0xEBF7. 0xEB stands for JMP and 0xF7 is a signed integer byte that translated to decimal is equal to -91. In other terms, the assembly version that we humans write says "jump to the following memory_location:" (something like IP = memory_location: where memory_location: = 0x0125 in this case), and the CPU understands "jump backwards 9 bytes from where you currently are" (something like IP = IP - 9). In fact, what the CPU does when it finds the instruction at memory location 0x012C is to take the value of IP, which is equivalent to 0x012E (remember that IP always points to the beginning of the next instruction) and add the value of -9 (in decimal) which brings the IP back to 0x0125 so that the next instruction to fetch end execute for the CPU is the one at address 0x0125. The fact that some of the JMP, CALL and LOOP instructions are implemented in the CPU circuitry in such a strange way, was (maybe) a design complication of the CPU which led to a very great and important feature in software coding. Thanks to this feature I could build up a piece of code and test it at the beginning of my test area and, when I was done, pile it up one over the others at the end of the master boot record knowing that they keep working anywhere in memory. I had read about code relocation in many of my reading before. It seems to be a very important topic: one can never be sure which portion of memory will be free in the PC and at which point in time. It happens that the Operative System (the OS in short form) takes care of this. It may be the case that the OS needs to shift or relocate portions of code in memory, but, to do so, the pieces of code must be memory location independent, or memory position ignorant. And here came the very nice point for me, because I said: "it was worth to take this journey by myself". Even though I read about this problem; I meant I understood it; I agreed it was an important feature to take care of; only when I was coding it by hand in DEBUG (when I was making my hand dirty with oil and fat in the garage) I could feel and see indeed what did it mean and how a piece of code could be made memory location independent. Wasn't this a good learning? Yes, it was for me!

Now let´s go back on track.
In Fig. B you see that I took a quick look in memory to see the starting position of my string (0x0250 in green) and I took care of point SI there2 (green). Then, I used the command p since I was pretty confident that the code would work and I didn't want to step inside the procedure for each and every step. The result is that the complete string "Press any key to reboot..." is now on the screen (green). Note that IP was equal to 0x0106 (green) meaning that we called the procedure (yellow), DEBUG executed it and returned to the right point.

Best practice with DEBUG.EXE
Fig. B

So everything was fine and smooth until now and in Fig. C I made a double-check with the second string. Again I gave a quick look on the memory to find the initial position of the string (0x0270 in orange), then I took care that SI was pointing there (orange) before I called the procedure (blue) using the command p. This displayed immediately the pre-formatted string (orange). I could also see that the formatting looked pretty much ok when the string went on screen.

Best practice with DEBUG.EXE
Fig. C

At the end of coding and testing, I piled up the procedure "show_string" over the others as you can see in Fig. D.

Best practice with DEBUG.EXE
Fig. D


  1. Maybe you want to refresh the two's complement on my previous post. [click back]
  2. The string needs to be pointed with DS:[SI] before calling show_string, but since we are inside DEBUG (CS = DS = ED = SS) it is sufficient to set just SI to have a complete pointing. [click back]

<PREV.  -  ALL  -  NEXT>

Comments