我正在尝试在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]
。如果没有方括号1,则将的偏移量pixelcolor
移至AL,而不是将偏移量移至ALpixelcolor
。这同样适用于pixelx
和pixely
。你的代码将相同的像素颜色(在你的情况下为红色)重复打印到屏幕上的错误位置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的DOS C / C ++编译器套件中。
[]
在NASM中,括号的使用不同于MASM / TASM / JWASM。
啊,我明白了。没想到我糟糕的NASM代码根本无法正常工作,我的汇编语言技能至少可以说是生锈的。现在我需要睡觉,明天我将检查您的答案是否确实可以解决任何问题。另外,是的,我知道应该以100,100写入像素。不知道我在写作时没有注意到这一点。
好的,现在可以使用。谢谢!