我正在将程序从EMU8086环境转换为NASM。组装NASM时出现以下错误:
system \ kernel.asm:14:错误:操作码和操作数的无效组合
system \ kernel.asm:20:错误:操作码和操作数的无效组合
system \ kernel.asm:28:错误:操作码和操作数的无效组合
我的代码是:
jmp start ;============================== ;Draws a horiz and vert line ;============================== startaddr dw 0a000h ;start of video memory colour db 1 ;============================== start: mov ah,00 mov al,19 int 10h ;switch to 320x200 mode ;============================= horiz: mov es, startaddr ;put segment address in es *** 1st ERROR HERE! mov di, 32000 ;row 101 (320 * 100) add di, 75 ;column 76 mov al,colour mov cx, 160 ;loop counter hplot: mov es:[di],al ;set pixel to colour *** 2nd ERROR HERE! inc di ;move to next pixel loop hplot vert: mov di, 16000 ;row 51 (320 * 50) add di, 160 ;column 161 mov cx, 100 ;loop counter vplot: mov es:[di],al ; *** 3rd ERROR HERE! add di, 320 ;mov down a pixel loop vplot
我已经用错误标记了行。为什么这在NASM中不起作用?
由于0xA000是一个常数,因此可以这样定义它,然后将其用作立即值而不是内存操作数。为了使这种方法起作用,您需要将常量放置在中间寄存器中,然后将其移动到段寄存器中。
您可以将startaddr定义为常量(而不是包含段值的内存地址)。您可以使用EQU创建常量(立即值)。更改此行:
startaddr dw 0a000h ;start of video memory
至
startaddr EQU 0a000h ;start of video memory
由于您不能直接将立即值MOV移至DS,ES和SS,因此您需要将该值放入中间寄存器,然后将其移至段寄存器。所以这段代码:
mov es, startaddr ;put segment address in es
可能:
mov ax, startaddr mov es, ax ;put segment address in es
注意:如果创建可读代码,并且使用上述方法-我建议将startaddr重命名为STARTADDR。全大写标识符的约定向读者表明,它是一个常量(立即数)而不是变量。
您遇到的其他错误与EMU8086和NASM之间的语法差异有关。这些行:
mov es:[di],al ;set pixel to colour
和
vplot: mov es:[di],al
需要用方括号内的句段书写。它们应如下所示:
mov [es:di],al ;set pixel to colour
和
vplot: mov [es:di],al
我强烈建议您阅读有关生成DOS COM和EXE程序的NASM文档