Linux下NASM x86汇编中MOV指令对变量与寄存器的行为疑问
NASM x86汇编:内存地址与寄存器操作的疑问
我编写了一段Linux下的NASM x86汇编程序,目的是将36除以10并在屏幕上打印余数6,但原代码无法运行。排查后发现问题出在标记行:我将值本身存入ecx,而非该值在内存中的地址。
之后我修改了代码,先将值存入变量,再执行mov ecx, variable(该指令实际将变量的地址而非值存入ecx寄存器),程序即可正常运行。
现提出两个问题:
- 为何执行
mov ecx, variable是将变量的地址存入ecx,而执行mov ecx, edx是将edx的值存入ecx? - 如何指定寄存器的地址并将其存入另一寄存器的值中?
问题1解答
这是NASM的语法规则决定的:
- 当操作数是变量名时,NASM默认把它解析为该变量在内存中的地址(即符号对应的内存偏移量,结合段基址可得到线性地址)。所以
mov ecx, variable本质是把变量的内存地址加载到ecx里。 - 当操作数是寄存器名时,NASM直接将其解析为寄存器本身,
mov指令会完成寄存器间的值拷贝,也就是把edx寄存器里的数值传递到ecx中。
简单总结:变量名代表内存地址,寄存器名代表寄存器内存储的内容。
问题2解答
x86架构中,普通通用寄存器(如edx、ecx)是CPU内部的硬件单元,并不处于内存空间中,因此它们本身没有内存地址,你没法直接获取寄存器的"地址"并存入另一个寄存器。
如果你的需求是让寄存器指向存储了某寄存器值的内存位置(就像你修改代码时的思路),可以这么做:
- 在
.data段定义一个变量:section .data remainder db 0 ; 定义一个字节大小的变量,初始值为0 - 将目标寄存器的值写入该变量:
mov [remainder], edx ; 方括号表示访问变量对应的内存地址,把edx的值写入内存 - 再把变量的地址加载到目标寄存器:
mov ecx, remainder ; 把变量的地址存入ecx,供int 80h系统调用使用
另外,也可以用栈临时存储寄存器的值,再让寄存器指向栈顶位置:
push edx ; 把edx的值压入栈中 mov ecx, esp ; esp是栈顶指针,此时ecx指向栈中存储edx值的位置 ; 调用完系统调用后,记得执行pop edx恢复栈平衡
原代码
global _start section .text _start: mov ebp, esp; for correct debugging ; division mov eax,36 mov ebx,10 mov edx,0 ; cleaning edx before division div ebx add edx,0x30 ; converting the remainder (integer) into ascii digit ; display result mov eax,4 mov ebx,1 mov ecx,edx ; pay attention to this line mov edx,1 int 80h ; exit mov eax,1 mov ebx,0 int 80h
内容的提问来源于stack exchange,提问作者rimoto
相关产品推荐
相关产品推荐

