代码之家  ›  专栏  ›  技术社区  ›  ridhomblr

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

  •  0
  • ridhomblr  · 技术社区  · 1 年前

    我有一个16位汇编程序(NASM),它切换到VGA图形模式,并试图用纯色填充整个屏幕,但我最多只能填充32767(0x7fff)像素(而不是64000(0xfa00)像素的完整320x200显示器),如果再多,所有白色像素都会因某种原因消失。我假设这是某种有符号的增量,但我不太确定,因为我还在学习。否则,像素可能会出现并被绘制到屏幕上(我使用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
    
    
    1 回复  |  直到 1 年前
        1
  •  4
  •   Nate Eldredge    1 年前

    jge .fill_screen_done 基于之间不平等的跳跃 签署 价值观为了进行有符号二补运算, 0xfa00 是数字-1536。值0到0x7fff为正,因此在 di 在这个范围内,我们确实有 di >= cx 因此循环继续。但之后你会增加到 0x8000 ,在有符号算术中为-32768,并且条件不再为真。

    你想使用 jae .fill_screen_done 基于之间的不平等 无符号的 价值观(中有更多信息 this answer ; 我似乎在某个地方记得一个更好的,但我现在找不到了。)甚至只是 je .fill_screen_done ; 你递增 di 在每一步上增加一个,所以在相等之前不可能变得“高于”。

    另一个小错误是 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 ,我会让你自己研究的。

    推荐文章