【问题标题】:Infinite loops seemingly not working in NASM?无限循环似乎在 NASM 中不起作用?
【发布时间】:2021-03-31 13:00:51
【问题描述】:

我正在尝试在 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 下运行的过时 16 位 DOS 代码有什么好处。

标签: graphics nasm dos x86-16 bios


【解决方案1】:

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

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

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

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

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


脚注

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

【讨论】:

  • 啊,我明白了。没想到我糟糕的 NASM 代码能正常工作,我的汇编语言技能至少可以说是生疏了。现在我需要睡觉,明天我会检查你的回答是否真的解决了任何问题。另外,是的,我知道它应该在 100,100 处写入像素。不知道我在写作时怎么没有注意到这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-03
  • 1970-01-01
  • 2019-05-24
  • 2013-05-30
  • 2011-07-23
相关资源
最近更新 更多