I am trying to display x
in the center of the screen and then change the background color of the console to blue. I have the following code that accomplishes everything except for changing the background color:
TITLE screen1.ASM
.MODEL SMALL
.STACK 0100h
.DATA
.CODE
start:
MOV AX,@DATA
MOV DS,AX
MOV AX,0600h
MOV BH,07h
MOV CX,0000h
MOV DX,184Fh
INT 10h
MOV AH,02h
MOV BH,00h
MOV DH,0Ch
MOV DL,28h
INT 10h
MOV AH,02h
MOV DL,'x'
INT 21h
MOV AX,4C00h
INT 21h
END start
The code clears the screen, displays x
at the center of the dosbox window and gives control back to DOS. I'm trying to find out what change I would need to just update the background color of the window (not the text) to blue.
You have to set the colour for each character manually. Either use
INT 0x10 / AH=0x09
, or just write directly to the screen buffer (atB800:xxxx
).Each character in the screen buffer takes two bytes, the low byte contains the character, the high byte is the colour attribute.
When clearing the screen move
bh=17h
instead of 07hMy first impression of your code, and what prompted my first comment was that you may have been using the wrong foreground and background color. You had:
Which is light gray on black. White on blue would have been:
Information on the BIOS color attributes can be found here.
Your question is ambiguous, however the code in this example will update the background color of the current text mode, but maintain the foreground color and character. I assume the text mode is 80x25 before running
screen1
.This program updates the display memory directly. Page 0 of text modes generally start at physical address 0xB8000. I set ES to 0xB800 to do the video updates because the 0xB800:0x0000 segment:offset pair is the same as physical address (0xB800<<4)+0x0000=0xB8000.
Each character on the screen takes 2 bytes (or one 16-bit word). An 80x25 text mode is 2000 cells (of 2 bytes each) or a total of 4000 bytes of video ram. The character is in the first byte and the attribute is in the second byte. You can get more information on this video layout here.
The following code reads each attribute for each character on the screen, clears the background color (upper 4 bits) and then sets those upper 4 bits to the new background color. 0x01 is the color blue. After updating the background color the code writes the new attribute back to video memory.
An example of a screen before running this program:
And after:
All of the text (and the foreground colors) are retained while the background color has been updated.
The loop in the code that does the background color update could have also been written as:
The code in my original example may be easier to understand if you are new to x86 assembly.
Update Foreground & Background Colors For Entire Screen
If you don't need to preserve the foreground color for each character on the screen, you can simply update the attributes with a new value, and retain the existing character. The loop in my first code example could be modified to look like:
This would change all the characters on the screen to white on blue, and would appear something like:
Clear the Entire Screen without a BIOS Interrupt
For completeness, it is also possible to clear the entire screen with a character. The space character effectively acts as a clear character. We can update the character and attribute by using REP STOSW. We want to move forward through memory with STOSW so we set the direction flag forward using CLD. STD would have moved backward through memory. STOSW is described as:
The code to clear the screen with a blue background and a white foreground could be done similar to this:
This code does the equivalent of your code that utilized the video BIOS services:
The output of the program with this code above would look like:
To change the background and display x, check this resource http://ss64.com/nt/color.html. I hope it helps