绘制正方形的汇编代码

-5 assembly

我需要汇编代码来在屏幕中间绘制一个正方形。

\n\n

使用 BIOS 视频服务时,屏幕分辨率应为 320x200。维度\xe2\x80\x99s 长度应为 20 像素。正方形的颜色应为黄色、黑色背景,如下所示:

\n

Bre*_*dan 5

BIOS 服务具有极高的开销,切勿用于绘制单个像素。

对于“模式 0x13”,您可以直接访问显示内存 - 每个像素 1 个字节,从 0xA000:0x0000 开始,其中每条水平线都跟随前一条水平线(没有间隙/填充)。例如:

    mov ax,0xA000
    mov es,ax
    xor di,di           ;es:di = address of top left pixel
Run Code Online (Sandbox Code Playgroud)

要填充屏幕的顶行,您需要将 320 字节(像素)设置为零。所以:

    mov ax,0xA000
    mov es,ax
    xor di,di             ;es:di = address of top left pixel

    xor ax,ax             ;al = ah = black
    mov cx,320/2          ;cx = number of pairs of pixels to set
    cld                   ;Set direction to make sure
    rep stosw             ;Set entire line to black
Run Code Online (Sandbox Code Playgroud)

现在,您需要将顶部的许多行设置为黑色,因此:

    mov ax,0xA000
    mov es,ax
    xor di,di             ;es:di = address of top left pixel

;Do top lines

    mov bx,(200-BOX_Y)/2  ;bx = number of lines at top to make black
    xor ax,ax             ;al = ah = black
.topLoop:
    mov cx,320/2          ;cx = number of pairs of pixels to set
    cld                   ;Set direction to make sure
    rep stosw             ;Set entire line to black
    sub bx,1              ;bx = number of lines left to do
    jne .topLoop          ;Do next line if there are more lines to do
Run Code Online (Sandbox Code Playgroud)

下一部分是盒子本身。对于框所在的每一行,您希望左侧有一些黑色像素,中间有一些黄色像素,右侧有更多黑色像素:

;Do middle lines

    mov bx,BOX_Y          ;bx = number of lines in middle
.middleLoop:
    mov cx,(320-BOX_X)/2  ;cx = number of pixels to set
    rep stosb             ;Set left black
    mov cx,BOX_X
    mov al,BOX_COLOUR     ;al = box colour
    rep stosb             ;Set middle coloured part
    mov cx,320-(320-BOX_X)/2 - BOX_X
    xor al,al             ;al = black
    rep stosb             ;Set right black part
    sub bx,1              ;bx = number of lines left to do
    jne .middleLoop       ;Do next line if there are more lines to do
Run Code Online (Sandbox Code Playgroud)

最后,您也想将底线设置为黑色。这就像做顶线一样。完整的代码最终是这样的:

    mov ax,0xA000
    mov es,ax
    xor di,di             ;es:di = address of top left pixel

;Do top lines

    mov bx,(200-BOX_Y)/2  ;bx = number of lines at top to make black
    xor ax,ax             ;al = ah = black
.topLoop:
    mov cx,320/2          ;cx = number of pairs of pixels to set
    cld                   ;Set direction to make sure
    rep stosw             ;Set entire line to black
    sub bx,1              ;bx = number of lines left to do
    jne .topLoop          ;Do next line if there are more lines to do

;Do middle lines

    mov bx,BOX_Y          ;bx = number of lines in middle
.middleLoop:
    mov cx,(320-BOX_X)/2  ;cx = number of pixels to set
    rep stosb             ;Set left black
    mov cx,BOX_X
    mov al,BOX_COLOUR     ;al = box colour
    rep stosb             ;Set middle coloured part
    mov cx,320-(320-BOX_X)/2 - BOX_X
    xor al,al             ;al = black
    rep stosb             ;Set right black part
    sub bx,1              ;bx = number of lines left to do
    jne .middleLoop       ;Do next line if there are more lines to do

;Do bottom lines

    mov bx,200 - BOX_Y - (200-BOX_Y)/2
    xor ax,ax             ;al = ah = black
.bottomLoop:
    mov cx,320/2          ;cx = number of pairs of pixels to set
    rep stosw             ;Set entire line to black
    sub bx,1              ;bx = number of lines left to do
    jne .bottomLoop       ;Do next line if there are more lines to do
Run Code Online (Sandbox Code Playgroud)

注:以上所有代码均适用于 NASM(不同的汇编器可能不同);并且根本没有经过测试。我假设你处于实模式。您需要定义一些常量才能使其正常工作(BOX_XBOX_YBOX_COLOUR)。在各种情况下都可以更有效地完成。我不关心您正在使用的任何调用约定,或推送和弹出修改的寄存器,或执行ret. 我假设 0x00 是黑色(并且懒得猜测黄色的值是多少);这可能是错误的(值如何映射到颜色取决于您设置调色板的感觉,因此任何值都可以是任何颜色,0x00 可能是亮粉色或其他任何颜色,而不是黑色)

  • @ecm“...错误地初始化`es:di`,但我不知道如何纠正...”类似于*middleloop*如何使用*toploop*中的最后一个DI,*bottomloop*应该使用来自 *middleloop* 的最后一个 DI。该代码不需要在 *bottomloop* 之前初始化 ES 或 DI。如果此代码的用户没有注意到此错误,则可能是因为设置屏幕模式后屏幕已经变黑,并且 *bottomloop* 只是重新绘制了顶部线条(黑色覆盖黑色)。 (2认同)