我正在制作一个用户输入数字的程序,程序从零打印到该数字。这是我的代码:
SECTION .DATA
len EQU 32
SECTION .bss
data resw len
other resw len
SECTION .TEXT
GLOBAL _start
_start:
input: ; This section gets the integer from the user
mov eax, 3 ; }
mov ebx, 1 ; }
mov ecx, data ; } System_read call
mov edx, len ; }
int 80h ; }
prelim:
mov ebp, 0
setup: ; This section sets up the registers ready for looping
push ebp
pop other ; THIS IS THE ERROR LINE!
mov esi, data
loop: ; This section loops, printing out from zero to the number given
mov eax, 4
mov ebx, 1
mov ecx, other
mov edx, len
int 80h
cmp ebp, esi
je exit
inc ebp
jmp setup
exit: ; Exits the program
mov eax, 1 ; }
mov ebx, 0 ; } System_exit call
int 80h ; }
我遇到的问题是错误invalid combination of opcode and operand
。我已经尝试将变量other
声明为单词,双字,字节,它仍然说明了这一点。为什么呢?
本质上,我的问题是如何将寄存器中的值移动到内存中的值? 如:
mov memorydata, eax
其中memorydata
是在SECTION .data
或类似内容中声明的数据。
答案 0 :(得分:8)
首先,它应该是pop [other]
而不是pop other
。在NASM中,other
只是一个地址,而[other]
表示该地址的内容/数据。这就是NASM与TASM和MASM的不同之处。 pop other
要求NASM生成一个从堆栈弹出数据到......常量的指令!没有这样的指示,制作这样的指令是没有任何意义的。你想把东西放进寄存器或记忆中。
其次,与TASM和MASM(再次)不同,NASM不会将标签名称分配给任何类型或大小。标签只是代码或数据中的命名位置(地址)。
出于这个原因,pop [other]
对于NASM来说是不明确的,因为pop
可以弹出单词或双字而你没有指定你想要的那个,并且NASM无法猜出正确的大小对你而言。
你应该写的是
pop word [other]
或
pop some_32_bit_register ; e.g. pop eax
mov [other], that_same_32_bit_register_s_lower_half ; e.g. mov [other], ax
我强烈建议不要推送或弹出16位寄存器或变量或常量。它们不对齐堆栈,这会导致性能下降和由于注意力丢失导致的愚蠢错误(例如,您推送32位值然后错误地将其弹出为16位或反之)。
答案 1 :(得分:0)
你需要弹出一个临时寄存器,然后移动到你的记忆目的地:
POP EAX
MOV myVar,EAX
或者,您需要弹出一些明确的语法:
POP WORD PTR[<word_sized_var>]
至于将内容移入内存中,有一些语法方法:
MOV <var name>,<value>
MOV [<var name>],<value>
在您的情况下,您可能想要第一个:MOV other,EBP