Friday, February 24, 2006

ASM Hello World

I decided to do some more work with Assembly, and since I haven’t shown how to do a basic “Hello World” application, I decided I would (the graphical one I showed previously was a little too complex to qualify as Hello World). I will demonstrate two versions, one that uses DOS Interrupt 09, and another that will write directly to video memory (which I feel is much cooler than calling interrupts).

First, the easy one:
0BD0:0100 mov ah, 09
0BD0:0102 mov dx, 010C
0BD0:0105 int 21
0BD0:0107 mov ax, 4c00
0BD0:010A int 21
0BD0:010C db 'Hello World', '$'

This one is pretty basic. All it does is call the DOS interrupt with the memory address of the “Hello World” string in register DX. Then it exits back to DOS. The next program is a little more interesting:

0BD0:0100 mov si, 0119
0BD0:0103 mov di, 140
0BD0:0106 mov ax, b800
0BD0:0109 mov es, ax
0BD0:010B mov ah, 07
0BD0:010D mov cx, B
0BD0:0110 lodsb
0BD0:0111 stosw
0BD0:0112 loop 110
0BD0:0114 mov AX, 4c00
0BD0:0117 int 21
0BD0:0119 db 'Hello World'

First, we set the Source Index register with the location of the Hello World string, in this case at DS:0119 (remember, in Debug COM files, the Code Segment and Data Segment are set initially to the same location). We then set DI to 140h, which is a few lines down on the screen.

0BD0:0106 mov ax, b800
0BD0:0109 mov es, ax

Next we are setting AX to the location of the video memory. We then copy register AX to ES.  The reason for this is because we cannot access register ES directly, so we have to do it through one of the general purpose registers first, in this case AX.

0BD0:010B mov ah, 07

Here we set AH to the value of our character attribute information, which is a white text on a black background. Remember that in video memory, character information is stored in two bytes, the first being the character value, and the second being the attribute information. I stored the attribute information in the high order register since I will do a word move, and word moves reverse bytes. In other words, if AX is set to 0765, when I copy it to video memory, it gets copied as 6507.

0BD0:010D mov cx, B

This is setting up a loop that will run 11 times. 11 are the size of the string “Hello World”.

0BD0:0110 lodsb
0BD0:0111 stosw
0BD0:0112 loop 110

The first command loads a byte at location DS:SI into register AL. Now I have the word combination I will copy to video memory, so I use stosw to copy the entire AX register to the memory location pointed to by ES:DI. I then loop this from address 110. This loop will repeat 10 more times.

0BD0:0114 mov AX, 4c00
0BD0:0117 int 21

Exit to DOS.

0BD0:0119 db 'Hello World'

This defines the string “Hello World” starting at address 119.

The only drawback to this program is that the string prints in the same location on the screen every time you run it. I would recommend clearing the screen with the DOS Clear Screen command (cls). There are other options internal to the program itself, such as retrieving the cursor location, or clearing the screen itself. But this demonstrates how you can use lodsb/lodsw and stosb/stosw to quickly copy memory chunks between addresses.

2 comments:

Vanuan said...

0BD0:010D mov cx, B
Mistake? Maybe
0BD0:010D mov cx, 0Bh

John Ward said...

Using an assembler, 0Bh would be correct. I was actually using the DOS Debug in this example :)