Because I used to do a lot of graphics programming in inline assembly, I wanted to get back into doing work with video memory directly. Below is a simple program that will simply change the video mode to 320x200 256 colors and set the screen to whatever is in the 3rd palette entry (in my case, it was a baby blue).
0BD0:0100 B81300 MOV AX,0013
0BD0:0103 CD10 INT 10
0BD0:0105 B800A0 MOV AX,A000
0BD0:0108 8EC0 MOV ES,AX
0BD0:010A 31FF XOR DI,DI
0BD0:010C B80303 MOV AX,0303
0BD0:010F B9007D MOV CX,7D00
0BD0:0112 F3 REPZ
0BD0:0113 AB STOSW
0BD0:0114 B410 MOV AH,10
0BD0:0116 CD16 INT 16
0BD0:0118 B80300 MOV AX,0003
0BD0:011B CD10 INT 10
0BD0:011D B8004C MOV AX,4C00
0BD0:0120 CD21 INT 21
Lets look at the program piece by piece.
MOV AX,0013
INT 10
The video mode to set gets stored into register AX, and interrupt 10 will call the video interrupt to change it. There is a more thorough list of graphics modes can be found here.
MOV AX,A000
MOV ES,AX
XOR DI,DI
What I am doing here is setting up ES:DI to point to video memory at A000:0000. I need this set up in order to use the STOSB/STOSW instruction. A000:0000 is different than the video memory at B800:0000, so don’t confuse the 2. The video memory at A000:0000 stores pixel information, 1 byte for each pixel, which relates to a palette entry. So if A000:0001 is equal to 3, this is the 3rd palette entry.
MOV AX,0303
MOV CX,7D00
REP STOSW
What I have done here is set AX to 0303, which is basically 2 bytes of value 3, and this will get transferred to video memory to set all elements to point to the 3rd palette entry. CX then gets set to 7D00, which is the hex value for the number of pixels, divided by 2. The reason I divide these by 2 is so I can use a word operation instead of a byte operation. So I will copy the entire value of AX to ES:DI the number of times stored in register CX, which is what the REP prefix will do on the STOSW instruction. Note, once saved and unassembled, DEBUG puts REP and STOSW as two separate instructions, however I keyed them into debug as 1 line.
MOV AH,10
INT 16
This will wait for a key press from the user, to keep the color up on the screen.
MOV AX,0003
INT 10
This will set the video mode back to mode 3, which is the 80x25 text mode normally used in DOS.
MOV AX,4C00
INT 21
And this will return up to DOS.
This program works directly with the video memory, it doesn’t rely on interrupts to set the color at a particular pixel, which can be a slow process. Back in the old days of DOS programming, this was a trick that game programmers used in order to keep the latency of screen draws down. There are other techniques that are used, such as double buffering, but I won’t get into those since they are outside of the scope of my interest. In my next article, I will take off this idea, and have each column on the screen show 1 color in the palette, and have the palette displayed across the screen. This will demonstrate how to use the push and pop instructions to allow for controlled inner loops.
Subscribe to:
Post Comments (Atom)
2 comments:
Great information, Good Job!
Could you please put up info regarding bios interrupt routines.
I need to codeup a few interrupt routines similar to those in BIOS.
Post a Comment