3

我正在制作一个用户输入数字的程序,该程序从零打印到该数字。这是我的代码:

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或类似的东西。

4

2 回答 2

10

首先,它应该是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 位或其他方式)。

于 2012-10-12T07:32:49.623 回答
-1

您需要弹出到一个临时寄存器,然后移动到您的内存目的地:

POP EAX
MOV myVar,EAX

或者,您需要使用一些显式语法弹出:

POP WORD PTR[<word_sized_var>]

至于将 a 移入内存,有几种语法方式:

MOV <var name>,<value>

MOV [<var name>],<value>

在您的情况下,您可能想要第一个:MOV other,EBP

于 2012-10-12T07:33:09.860 回答