如果 DI > 32767,则不显示 VGA 输出

问题描述 投票:0回答:1

我有一个 16 位汇编程序 (NASM),它会更改为 VGA 图形模式并尝试用纯色填充整个屏幕,但我只能填充最多 32767 (0x7fff) 像素(而不是完整的 320x200 显示屏,是 64000 (0xfa00) 像素),如果再多,所有白色像素都会因某种原因消失。我假设它是某种带符号的增量,但我不太确定,因为我还在学习一点。否则,像素可以显示并绘制到屏幕上(我使用 QEMU)

init.asm:

org 0h
bits 16

%define ENDL 0dh, 0ah

jmp _entry

_entry:
    push msg_hello
    call puts

    jmp entry
entry:
    call toggle_vga
    
    push 0fh
    push 07fffh
    call fill_screen
    
    jmp endp

toggle_vga:
    push ax
    mov ah, 0fh
    mov al, 0h
    int 10h

    cmp al, 13h
    je .toggle_vga_off
    jne .toggle_vga_on
.toggle_vga_on:
    mov ah, 00h
    mov al, 13h
    int 10h
    jmp .toggle_vga_end
.toggle_vga_off:
    mov ah, 00h
    mov al, 03h
    int 10h
    jmp .toggle_vga_end
.toggle_vga_end:
    pop ax
    ret
    
fill_screen:
    push bp
    mov bp, sp
    
    push es
    push ax
    push dx
    push cx
    push di
    
    mov ax, 0a000h
    mov es, ax
    mov dl, [bp + 6]
    mov cx, [bp + 4]
    mov di, 0
.fill_screen_loop:
    cmp di, cx
    jge .fill_screen_done
    
    mov [es:di], dx
    inc di
    
    jmp .fill_screen_loop
.fill_screen_done:
    pop di
    pop cx
    pop dx
    pop ax
    pop es

    pop bp
    ret

puts:
    push bp
    mov bp, sp

    push bx
    push ax
    mov bx, [bp + 4]
.puts_loop:
    cmp byte [bx], 0
    je .puts_done

    mov ah, 0eh
    mov al, [bx]
    int 10h

    inc bx
    jmp .puts_loop
.puts_done:
    pop ax
    pop bx
    pop bp
    ret

endp:
    cli
    hlt

msg_hello: db 'init: loaded successfully.', ENDL, 0

assembly operating-system 16-bit
1个回答
0
投票

jge .fill_screen_done
根据 signed 值之间的不等式跳转。对于有符号补码算术,
0xfa00
是数字 -1536。值 0 到 0x7fff 都是正数,因此当
di
在此范围内时,我们确实有
di >= cx
,因此循环继续。但随后您递增到
0x8000
,在有符号算术中为 -32768,并且条件不再为真。

您想使用

jae .fill_screen_done
,它根据 unsigned 值之间的不等式进行跳转。 (这个答案中有更多信息;我似乎记得在某个地方有一个更好的答案,但现在找不到了。)或者甚至只是
je .fill_screen_done
;每一步将
di
加一,因此在相等之前不可能变为“上方”。

另一个小bug是

mov [es:di], dx
;由于
dx
是一个 16 位寄存器,因此它存储一个字(两个字节)。但您只想存储
dl
中的一个字节(您已将
dh
保留为未初始化),所以将其设为
mov [es:di], dl


您可以通过将字节复制到

dx
的两半 (
mov dh, dl
) 来提高效率,然后一次存储一个单词 (
mov [es:di], dx
) 并将
di
加 2(
add di, 2
,或
inc di
两次)。确保
cx
始终为偶数。

更好的是使用

rep stosw
,我会让你自己研究。

© www.soinside.com 2019 - 2024. All rights reserved.