<--- Turn the page
   
(contents page)
   
Turn the page ---> Assembler |
Have you ever go dumped back in to dos and the colors are not what they should be. On DOS user told me a little while ago that a program he was using SHELLed to DOS with the color attribute set to Black text on Black Background. A CLS would take of of this, however he was asking about programming it rather than calling the DOS CLS command. DOS prints to the screen memory two bytes for each character. The first byte is the ascii char while the second byte is the color attribute. To easily change the color of the screen without modifying the existing text, simply modify this second byte. The color is specified in AH with the background in the HI nibble and the text color in the LO nibble. Please note with the background color. If you set the HI nibble to a value with the HI bit set, the video card will take the LO 3 bits as the color and blink. To stop the blinking, you must call INT 10h, service 1003h, with BL cleared. .model tiny .code mov di,00h ; di = 0 mov cx,2000 ; cx = 2000 mov ax,0B800h ; es = 0B800h mov es,ax loop1: mov ax,es:[di] ; get the word mov ah,07h ; ah = 07h stosw ; put it back loop loop1 ; loop cx times ret ; exit .endThat is all we have to do. It is fairly quick too. Keep reading to find out how to optimize this snippet of code for size and speed. With assembler, it is very easy to optimize your code. First of all, if we look at the code above, we get the WORD of the character in memory rather than just the attribute byte. This takes time to get the word and set AH to the color attribute 2000 times. Also, if we rely on the initial registers at .COM file startup, we can do a few tricks to make our code smaller. |
Look at the following: .model tiny .code xchg di,ax ; di = 0, ax = 0FFFEh xchg cx,ax ; cx = 0FFFEh, ax = 00FFh mov bh,0B8h ; bx = 0B800h mov es,bx ; es = bx mov al,07h ; al = 07h loop1: inc di ; di += 1 stosb ; put it loop loop1 ; cx -= 1 ret ; exit .end Let us assume the following values for each of the registers we use above. AX and BX = 0000h CX = 00FFh DI = FFFEh ES = CSFirst of all we exchange DI and AX. This sets DI to zero, or offset 00h. Next we exchange CX and AX. This sets CX to 0FFFEh, more than enough to change all 2000 bytes. (Don't need to worry about changing any of the memory past the 2000 bytes in segment 0B800h.) Now we need to point ES to 0B800h. Since we can not MOV an immediate into a segment register, we must use a general purpose register. It is one byte smaller to set BH to 0B8h then BX to 0B800h. We will do this since BX = zero on start up. Now set AL to the color attribute specified and start our loop. INC DI to the second byte and store our value using STOSB which also increments DI to the first of the next character word. The optimized code is 6 bytes smaller and considerably faster. Please don't send me "flame" mail about how you can make it smaller and faster, or how I should use actual memory modification rather than STOSB on Pentiums. I did this optimize bit to show that it can be done easily without getting out that spec sheet on clock counts and processor types. ¥ |
<--- Turn the page
   
(contents page)
   
Turn the page ---> Page 9