我在 64 位 linux 上使用 NASM 汇编程序。
有一些我无法理解的变量和寄存器。
我创建了一个名为“msg”的变量:

 msg db "hello, world"

现在,当我想写入标准输出时,我将 msg 移动到 rsi 寄存器,但是我不理解 mov 指令按位... rsi 寄存器由 64 位组成,而 msg 变量有 12 个符号,每个符号为 8 位,这意味着 msg 变量的大小为 12 * 8 bits ,显然大于 64 位。

那么这怎么可能做出如下指令:mov rsi, msg ,不会溢出为 rsi 分配的内存。

或者 rsi 寄存器是否包含字符串的第一个符号的内存位置,在写入 1 个符号后,它会更改为下一个符号的内存位置?

对不起,如果我写的完全是胡说八道,我是组装新手,我只是暂时无法掌握它。

最佳答案

在 NASM 语法中(与 MASM 语法不同),mov rsi, symbol 将符号的地址放入 RSI。 (使用 64 位绝对立即数效率低下;使用 RIP 相对 LEA 或 mov esi, symbol 代替。 How to load address of function or label into register in GNU Assembler )
mov rsi, [symbol] 将从 symbol 开始加载 8 个字节。当您编写这样的指令时,您可以选择一个有用的位置来加载 8 个字节。

mov   rsi,  msg           ; rsi  = address of msg.  Use lea rsi, [rel msg] instead
movzx eax, byte [rsi+1]   ; rax  = 'e' (upper 7 bytes zeroed)
mov   edx, [msg+6]        ; rdx  = ' wor' (upper 4 bytes zeroed)

请注意,您可以使用 mov esi, msg,因为符号地址始终适合 32 位(在默认的“小”代码模型中,所有静态代码/数据都位于低 2GB 的虚拟地址空间中)。 NASM 使用汇编时常量(如 mov rax, 1 )为您进行了这种优化,但可能无法使用链接时常量。 Why do x86-64 instructions on 32-bit registers zero the upper part of the full 64-bit register?



不,如果你想要,你必须 inc rsi 。没有魔法。指针只是可以像任何其他整数一样操作的整数,而字符串只是内存中的字节。

访问寄存器不会神奇地修改它们。

有像 lodsbpop 这样的指令,它们从内存中加载并递增一个指针(分别是 rsirsp),但是 x86 没有任何前/后递增/递减寻址模式,因此您甚至无法使用 mov 获得这种行为如果你想要的话。使用 add/subinc/dec

关于string - 无法理解寄存器和变量之间的汇编 mov 指令,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47123137/

10-12 22:13