Assembly 将数据从堆栈中弹出到命名变量中?或者用MOV存储寄存器?

Assembly 将数据从堆栈中弹出到命名变量中?或者用MOV存储寄存器?,assembly,nasm,Assembly,Nasm,我在做一个程序,用户输入一个数字,程序从零到那个数字打印出来。这是我的密码: 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,

我在做一个程序,用户输入一个数字,程序从零到那个数字打印出来。这是我的密码:

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             ; }
我遇到的问题是,它给出的错误是操作码和操作数的组合无效。我尝试过将变量
other
声明为一个字、双字、字节,但它仍然这样说。为什么会这样

本质上,我的问题是如何将寄存器中的值移动到内存中的值? 例如:


其中
memorydata
是在
节中声明的数据。data
或类似的东西。

首先,它应该是
pop[other]
,而不是
pop other
。在NASM中,
other
只是一个地址,而
[other]
表示该地址的内容/数据。这就是NASM与TASM和MASM的不同之处
pop other
要求NASM生成一条指令,将堆栈中的数据弹出到。。。常数没有这样的指示,这样做没有任何意义。您想将内容弹出到寄存器或内存中

其次,与TASM和MASM(同样)不同,NASM不为标签名指定任何类型或大小。标签只是代码或数据中的命名位置(地址)

由于这个原因,
pop[other]
对NASM来说是不明确的,因为
pop
可以弹出一个单词或两个单词,而您没有指定您想要哪一个,并且NASM无法猜测适合您的大小

你应该写的是

pop word [other]


我强烈建议不要推送或弹出16位寄存器、变量或常量。它们使堆栈错位,这可能会导致性能降低,并由于注意力丢失而导致愚蠢的错误(例如,您推送一个32位的值,然后错误地将其弹出为16位或其他方式)。

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

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

POP WORD PTR[<word_sized_var>]
POP WORD PTR[]
至于将a移到内存中,有几种语法方法:

MOV <var name>,<value>

MOV [<var name>],<value>
MOV,
MOV[],

在您的例子中,您可能需要第一个:
MOV other,EBP

NASM使用与TASM和MASM不同的语法。NASM没有
一些大小的PTR
。NASM不能执行
MOV myVar,EAX
,因为
myVar
是一个常数,它是变量的地址,而不是变量。我可以执行
MOV[other],EAX
?@RileyH-Yep,这就是你应该对NASM执行的操作。@AlexeyFrunze,没错!你会想进入这个地址的!我假设在机器级别,
pop
的操作码使用一个数字操作数——目标。如果将该地址的解引用值(例如,字符“a”)传递给pop指令,那就没有任何意义了,不是吗?彼得·科德斯我当时感到困惑的原因是,我过去认为汇编程序是一个很好的查找和替换工具,它会看到标记
pop
并替换为,比如说,55。它将看到令牌
bx
,并替换为
0x02
。现在我知道用二进制表示汇编操作要复杂得多。操作码由表示操作数是哪种数据的标志组成。这最终使我能够将NASM视为一种语言,在它如何表示间接地址的背后有着自己的哲学。不管怎样,谢谢你。那没有道理。标签
other
只是一个表示内存中某个位置的数字,对吗?例如,如果您已将值5存储在
other
所指的地址,那么我希望
pop[other]
将转换为
pop 5
@JamesM。请注意,您在最后一句话中所说的没有意义。试着想象一下,想想你为什么会这样做。@JamesM.Lay:在NASM语法中,内存操作数总是需要
[]
围绕地址。因此,
pop[other]
是使用
other
作为寻址模式,对内存目标的弹出。x86没有任何双地址寻址模式,它可以从内存中加载指针并对其进行引用。@ AlxyFrunZEZ给某人学习NASM,当你被教导将括号等同于解引用操作符时,它是完全有意义的。我的心理模型是一个函数pop:
void-pop(void*address)
,和
pop-other
相当于
pop(other)
vs
pop[other]
相当于
pop(*other)
。他们没有告诉你的秘密是,机器操作员比汇编助记符多。汇编程序生成的操作根据操作数的寻址模式而变化。
mov符号、eax
也不汇编。我不知道关于标记行上的segfault的编辑想要说什么。
POP WORD PTR[<word_sized_var>]
MOV <var name>,<value>

MOV [<var name>],<value>