无法理解寄存器和变量之间的汇编mov指令

kor*_*oma 2 string x86 assembly nasm

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

 msg db "hello, world"  
Run Code Online (Sandbox Code Playgroud)

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

因此,如何使这样的指令成为可能:
mov rsi, msg 而不溢出分配给rsi的内存。

还是rsi寄存器包含字符串的第一个符号的存储位置,并且在写入1个符号后将其更改为下一个符号的存储位置?

抱歉,如果我写的是完全废话,我是组装的新手,我暂时无法掌握它。

Pet*_*des 5

在NASM语法中(与MASM语法不同),将符号mov rsi, symbol地址放入RSI。(使用64位绝对立即数效率低下;使用相对RIP的LEA或mov esi, symbol代替。 如何将函数或标签的地址加载到GNU汇编器中的寄存器中

mov rsi, [symbol]将从8开始加载8个字节symbol。编写这样的指令时,您可以选择一个有用的位置来加载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)
Run Code Online (Sandbox Code Playgroud)

请注意,您可以使用mov esi, msg符号地址,因为符号地址始终适合32位(在默认的“小”代码模型中,所有静态代码/数据都存储在2GB的虚拟地址空间中)。NASM使用汇编时间常数(例如mov rax, 1)为您进行了优化,但可能无法使用链接时间常数。 为什么32位寄存器上的x86-64指令将整个64位寄存器的高位归零?

在写入1个符号后,它会更改为下一个符号的存储位置吗?

不,如果您必须这样做inc rsi。没有魔术。指针就是您可以像其他整数一样操作的整数,而字符串只是内存中的字节。

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

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