【问题标题】:mov instruction operands typemov 指令操作数类型
【发布时间】:2023-12-25 11:06:01
【问题描述】:

这是将 2 和 3 相乘的代码的一部分:

section .text
global _start
_start:
mov al,'3'
sub al, '0'
mov bl, '2'
sub bl, '0'
mul bl
add al, '0'
;first question -> 
mov [res], al
mov ecx,msg
mov edx, len
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80
;second question ->
mov ecx,res
mov edx, 1
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80
mov eax,1 ;system call number (sys_exit)
int 0x80
section .data
msg db "The result is:", 0xA,0xD
len equ $- msg
segment .bss
res resb 1

在上面的代码中:

  1. 为什么要使用mov [res], al而不使用mov res, al
  2. 为什么要使用mov ecx,res而不使用mov ecx,[res]

****更新

我知道一个是地址,另一个是值,但我不知道为什么......

【问题讨论】:

  • 一个取地址,另一个值存储在该地址中
  • tnx 我的朋友。我知道但我不知道为什么?

标签: assembly nasm operands


【解决方案1】:

res 是汇编程序的名称,只不过是表示值的符号。
你已经知道res的值是它后面第一个字节的地址。
我们非正式地说res是变量res的地址。

在这种考虑下,指令mov res, ecx 没有意义,脱糖后它等同于mov <a number>, ecx
一个具体的例子:mov 0x12345678, ecx - 立即进入没有意义。

mov ecx, res 有意义,它会使用 res 的地址加载ecx
我们需要它的地址而不是它的值,因为sys_write 将字节流写入文件(在您的情况下为 stdout) - 它与打印高级语言中的数字的函数完全不同。
实际上,乘法的个位数结果通过add al, '0'的均值转换为字符串。
转换后sys_write 用于将字符串(不是数字!)写入stdout
由于sys_write 处理它期望在ecx 中写入的第一个字节的地址的字节流。
您可以查看C wrapper 以检查参数的类型:const void* 用于第二个参数。
所以必须给出地址 (mov ecx, res) 而不是值1 (mov ecx, [res])。


1请注意,地址和值之间的区别纯粹是语义上的,在汇编中没有这样的划分。

【讨论】: