执行tasm程序时更改dosbox控制台的背景颜色

时间:2016-03-25 11:58:36

标签: assembly screen tasm dosbox x86-16

我试图在屏幕中央显示x,然后将控制台的背景颜色更改为蓝色。我有以下代码来完成除更改背景颜色之外的所有内容:

    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

代码清除屏幕,在dosbox窗口的中心显示x并将控制权交还给DOS。我试图找出将窗口(不是文本)的背景颜色更新为蓝色所需的更改。

4 个答案:

答案 0 :(得分:3)

清除屏幕时,移动bh=17h而不是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

答案 1 :(得分:2)

我对您的代码的第一印象,以及促使我第一次评论的原因是您可能使用了错误的前景色和背景色。你有:

MOV BH,07h

黑色为浅灰色。蓝色的白色本来就是:

MOV BH,1fh 

可以找到有关BIOS颜色属性的信息here

您的问题不明确,但此示例中的代码将更新当前文本模式的背景颜色,但保留前景色和字符。在运行screen1之前,我假设文本模式为80x25。

该程序直接更新显示内存。文本模式的第0页通常从物理地址0xB8000开始。我将 ES 设置为0xB800来进行视频更新,因为0xB800:0x0000 segment:offset pair与物理地址相同(0xB800<< 4)+ 0x0000 = 0xB8000。

屏幕上的每个字符占用2个字节(或一个16位字)。 80x25文本模式是2000个单元(每个2个字节)或总共4000个字节的视频RAM。字符位于第一个字节中,属性位于第二个字节中。您可以获得有关此视频布局here的更多信息。

以下代码读取屏幕上每个字符的每个属性,清除背景颜色(高4位),然后将高4位设置为新的背景颜色。 0x01是蓝色。更新背景颜色后,代码会将新属性写回视频内存。

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

运行此程序前的屏幕示例:

enter image description here

之后:

enter image description here

在更新背景颜色时保留所有文本(和前景色)。

执行背景颜色更新的代码中的循环也可以写为:

    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

如果您不熟悉x86程序集,我原始示例中的代码可能更容易理解。

更新前景&整个屏幕的背景颜色

如果您不需要为屏幕上的每个字符保留前景色,则只需使用新值更新属性,并保留现有字符。我的第一个代码示例中的循环可以修改为:

    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

这会将屏幕上的所有字符更改为蓝色的白色,并显示如下:

enter image description here

在没有BIOS中断的情况下清除整个屏幕

为了完整起见,还可以使用角色清除整个屏幕。 space 字符有效地充当了清晰的字符。我们可以使用REP STOSW更新字符和属性。我们希望使用 STOSW 向前移动内存,因此我们使用CLD向前设置方向标记。 STD会在内存中向后移动。 STOSW 被描述为:

REP STOS   m16    Fill (E)CX words at ES:[(E)DI] with AX.

用蓝色背景和白色前景清除屏幕的代码可以这样做:

    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

此代码与您使用视频BIOS服务的代码相同:

MOV AX,0600h
MOV BH,1Fh
MOV CX,0000h
MOV DX,184Fh
INT 10h

上面带有此代码的程序输出如下所示:

enter image description here

答案 2 :(得分:1)

您必须手动设置每个字符的颜色。使用INT 0x10 / AH=0x09,或直接写入屏幕缓冲区(B800:xxxx)。

屏幕缓冲区中的每个字符占用两个字节,低字节包含字符,高字节是颜色属性。

答案 3 :(得分:-1)

要更改背景并显示x,请检查此资源http://ss64.com/nt/color.html。我希望它有所帮助