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

Infinite loops seemingly not working in 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。如果没有这个,您的数据偏移量将不正确,导致数据 read/written 来自错误的内存位置。

  • 您对 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,0ch
      mov al,[pixelcolor]
      mov cx,[pixelx]
      mov dx,[pixely]
      int 10h
      inc byte[pixelcolor]
    
  • 需要注意的是,默认情况下定时器的分辨率只会是每秒18.2次(~55ms)。这比您想要的 1/100 秒的分辨率要低。

  • 某些版本的 DOS 可能总是 return 0 作为秒值的 1/100。

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

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


脚注

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