kor*_*oma 2 string x86 assembly nasm
我在Linux 64位上使用NASM汇编程序。我无法理解某些带有变量和寄存器的东西。我创建一个名为“ msg”的变量:
msg db "hello, world"
Run Code Online (Sandbox Code Playgroud)
现在,当我想写入标准输出时,我将其移动msg到rsi寄存器,但是我不mov按位理解指令……rsi寄存器由64位组成,而msg变量具有12个符号,每个符号8位,这意味着msg变量的大小为12 * 8bit,显然大于64位。
因此,如何使这样的指令成为可能:
mov rsi, msg 而不溢出分配给rsi的内存。
还是rsi寄存器包含字符串的第一个符号的存储位置,并且在写入1个符号后将其更改为下一个符号的存储位置?
抱歉,如果我写的是完全废话,我是组装的新手,我暂时无法掌握它。
在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。没有魔术。指针就是您可以像其他整数一样操作的整数,而字符串只是内存中的字节。
访问寄存器不会神奇地修改它们。
有类似这样的指令lodsb,pop它们从内存中加载并递增一个指针(rsi或rsp分别递增),但是x86没有任何前/后递增/递减寻址模式,因此mov即使您想要它也无法获得这种行为。使用add/ sub或inc/ dec。