无限循环似乎在 NASM 中不起作用?

问题描述

我正在尝试在 NASM 中制作一个 DOS 程序,该程序使用中断 10h 来显示左上角的 16 种可用颜色中循环的像素。我还使用中断 21h 使程序每 1/100 秒(100 fps)运行一次。

segment .data
    pixelcolor: db 0
    pixelx: dw 100
    pixely: dw 100
    timeaux: db 0 ; used later on to force the program to run at 100fps
segment .text
    global _start
    
_start:
    mov ah,00h
    mov al,0dh
    int 10h
    
    mov ah,0bh
    mov bh,00h
    mov bl,00h
    int 10h
    
    .infinite:
        mov ah,2ch
        int 21h ; get system time
        cmp dl,timeaux ; if 1/100 seconds haven't passed yet...
        je .infinite ; ...skip current frame
        ; else,continue normally
        mov byte[timeaux],dl
        
        mov ah,00h
        mov al,0dh
        int 10h
        mov ah,0bh
        mov bh,00h
        mov bl,00h
        int 10h
        
        mov ah,0ch
        mov al,pixelcolor
        mov cx,pixelx
        mov dx,pixely
        int 10h
        inc byte[pixelcolor]
        
        jmp .infinite

然而,当我在 DOSBox 中实际运行程序时,像素只是保持红色。有谁知道为什么我的无限循环不起作用? (注意:我对 NASM 很陌生,所以老实说,我什至不惊讶我的程序只能在 15% 的时间内运行。)

解决方法

问题实际上不在于循环本身。循环在每次迭代中所做的事情就是问题所在。我的一些问题和观察是:

  • 由于这是一个 DOS COM 程序,您将需要在顶部添加一个 org 100h,因为 DOS 加载程序加载了一个 COM 程序以偏移当前程序段的 100h。否则,您的数据偏移量将不正确,从而导致从错误的内存位置读取/写入数据。

  • 您的 mov al,pixelcolor 有问题。它必须是 mov al,[pixelcolor]。如果没有方括号1pixelcolor 的偏移量将移动到 AL,而不是存储在 pixelcolor 偏移量处的内容。 pixelxpixely 也是如此。您的代码将相同的像素颜色(在您的情况下为红色)重复打印到屏幕上错误的位置2。这段代码:

      mov ah,0ch
      mov al,pixelcolor
      mov cx,pixelx
      mov dx,pixely
      int 10h
      inc byte[pixelcolor]
    

    应该是:

      mov ah,[pixelcolor]
      mov cx,[pixelx]
      mov dx,[pixely]
      int 10h
      inc byte[pixelcolor]
    
  • 需要注意的是,定时器的分辨率默认仅为每秒 18.2 次(~55ms)。这比您要达到的 1/100 秒分辨率还低。

  • 某些版本的 DOS 可能总是为 1/100 的第二个值返回 0。

  • 使用 BIOS 将像素写入屏幕可能会使编码更简单(它抽象出视频模式中的差异),但与将像素直接写入内存相比,速度会相当慢。

  • 我会推荐 Borland 的 Turbo Debugger (TD) 来调试 DOS 软件。 Turbo Debugger 包含在许多 Borland's DOS C/C++ compiler suites 中。


脚注

  • 1在 NASM 中括号 [] 的使用与 MASM/TASM/JWASM 不同。
  • 2虽然您的问题说您想写到屏幕的左上角,但代码表明您确实打算在坐标 100,100 处写入像素。