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

时间:2017-11-05 15:15:24

标签: string assembly x86 nasm

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

的变量
 msg db "hello, world"  

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

那么如何制作如下指令呢? mov rsi, msg,没有溢出为rsi分配的内存。

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

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

2 个答案:

答案 0 :(得分:4)

在NASM语法中(与MASM语法不同)mov rsi, symbol将符号的地址放入RSI。

mov rsi, [symbol]将从symbol开始加载8个字节。你可以选择一个有用的地方来加载8个字节,就像你写这样的指令一样。

mov   rsi,  msg           ; rsi  = address of msg
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 most x64 instructions zero the upper part of a 32 bit register

  

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

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

访问寄存器并不会对它们进行神奇的修改。

lodsbpop等指令从内存加载并递增指针(rsirsp),但x86没有任何指针前/后递增/递减寻址模式,因此即使您需要,也无法使用mov获得该行为。使用add / subinc / dec

答案 1 :(得分:0)

免责声明:我不熟悉您正在处理的装配风格,因此以下内容更为通用。特定的味道可能具有比我以前更多的功能。通常,汇编处理单字节/字实体,其大小取决于处理器。我已经在8位和16位处理器上完成了相当多的工作,所以这就是我的答案来源。

关于汇编的一般声明: 汇编就像一个高级语言,除了你必须处理更多的细节。因此,如果您习惯于在C语言中使用某些操作,则可以从那里开始,然后再进一步中断操作。

例如,如果您已声明要添加的两个变量,那么在C中这很容易:

x = a + b;

在装配中,你必须进一步打破它:

mov R1, a  * get value from a into register R1
mov R2, b  * get value from b into register R2
add R1,R2  * perform the addition (typically goes into a particular location I'll call it the accumulator
mov x, acc * store the result of the addition from the accumulator into x

根据程序集和处理器的风格,您可以直接引用添加说明中的变量,但就像我说的那样我必须查看您正在使用的特定风格。

评论您的具体问题: 如果你有一串字符,那么你必须使用某种循环单独移动每个字符。我会设置一个寄存器来包含字符串的起始地址,然后在移动每个字符后递增该寄存器。它的作用类似于C中的指针。您需要对字符串的终止或其他告诉字符串大小的值有一些指示,因此您知道何时停止。