Change the background color of dosbox console when

2019-05-07 09:55发布

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.

4条回答
叼着烟拽天下
2楼-- · 2019-05-07 10:42

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.

查看更多
淡お忘
3楼-- · 2019-05-07 10:50

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

enter image description here

查看更多
Ridiculous、
4楼-- · 2019-05-07 10:50

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:

enter image description here

And after:

enter image description here

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:

enter image description here


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:

enter image description here

查看更多
forever°为你锁心
5楼-- · 2019-05-07 10:54

To change the background and display x, check this resource http://ss64.com/nt/color.html. I hope it helps

查看更多
登录 后发表回答