问题
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.
回答1:
When clearing the screen move bh=17h
instead of 07h
TITLE screen1.ASM
.MODEL SMALL
.STACK 0100h
.DATA
.CODE
start:
MOV AX,@DATA
MOV DS,AX
MOV AX,0600h
MOV BH,17h
MOV CX,0000h
MOV DX,184Fh
INT 10h
MOV AH,02h ;settin cursor position
MOV BH,00h ;page number
MOV DH,0Ch ;row
MOV DL,28h ;column
INT 10h
MOV AH,02h
MOV DL,'x'
INT 21h
MOV AX,4C00h
INT 21h
END start
回答2:
My 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:
MOV BH,07h
Which is light gray on black. White on blue would have been:
MOV BH,1fh
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.
TITLE screen1.ASM
.MODEL SMALL
.STACK 0100h
.DATA
.CODE
start:
MOV AX,@DATA
MOV DS,AX
MOV AX,0B800h
MOV ES,AX ; Set ES to text video memory segment
MOV SI,1 ; Attributes are on odd addresses
MOV CX,2000 ; 2000 2-byte cells on an 80x25 display
L1:
MOV AL,ES:[SI] ; Get cell attribute
AND AL,0Fh ; Clear the current background
OR AL,10h ; Set the background to 1 (1=blue)
MOV ES:[SI],AL ; Update the attribute on screen with new background color
ADD SI,2 ; Go to next cell's attribute
DEC CX
JNZ L1 ; Loop for entire display
MOV AH,02h
MOV BH,00h
MOV DH,0Ch
MOV DL,28h
INT 10h ; Set cursor
MOV AH,02h
MOV DL,'x'
INT 21h ; Write character at cursor using the current
; foreground and background colors at that position
MOV AX,4C00h
INT 21h ; Exit Program
END start
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:
MOV AX,0B800h
MOV ES,AX ; Set ES to text video memory segment
MOV SI,4000 ; 4000 bytes with each screen cell on an 80x25 display
; taking 2 bytes each. 80*25*2 = 4000
L1:
MOV AL,ES:[SI-1] ; Get cell attribute
AND AL,0Fh ; Clear the current background color bits
OR AL,10h ; Set the background color bits to 1 (1=blue)
MOV ES:[SI-1],AL ; Update the attribute with new background color
SUB SI,2 ; Go to next cell (move backwards)
JG L1 ; Loop for entire display
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:
MOV AX,0B800h
MOV ES,AX ; Set ES to text video memory segment
MOV SI,4000 ; 2000 2-byte cells on an 80x25 display
L1:
MOV BYTE PTR ES:[SI-1],01Fh
; Set attribute to 1F (1=blue background, F=white foreground)
SUB SI,2 ; Go to next attribute(backwards)
JG L1 ; Loop for entire display
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:
REP STOS m16 Fill (E)CX words at ES:[(E)DI] with AX.
The code to clear the screen with a blue background and a white foreground could be done similar to this:
MOV AX,0B800h
MOV ES,AX ; Set ES to text video memory segment
XOR DI,DI ; Starting offset = 0 for STOSW
MOV CX,2000 ; 2000 2-byte (16-bit WORD) cells on an 80x25 display
MOV AX,1F20h ; 20h = ASCII value for space character
; 1Fh = attribute (white on blue)
CLD ; Set direction flag forward (used by STOSW etc)
REP STOSW ; Copy AX (attribute and char) to ES:DI, Repeat CX (2000) times
This code does the equivalent of your code that utilized the video BIOS services:
MOV AX,0600h
MOV BH,1Fh
MOV CX,0000h
MOV DX,184Fh
INT 10h
The output of the program with this code above would look like:
回答3:
You have to set the colour for each character manually. Either use INT 0x10 / AH=0x09, or just write directly to the screen buffer (at B800:xxxx
).
Each character in the screen buffer takes two bytes, the low byte contains the character, the high byte is the colour attribute.
回答4:
To change the background and display x, check this resource http://ss64.com/nt/color.html. I hope it helps
来源:https://stackoverflow.com/questions/36219498/change-the-background-color-of-dosbox-console-when-executing-a-tasm-program