【问题标题】:Can't understand assembly mov instruction between register and a variable无法理解寄存器和变量之间的汇编 mov 指令
【发布时间】:2018-04-17 19:13:27
【问题描述】:

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

 msg db "hello, world"  

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

那么,如何在不溢出为 rsi 分配的内存的情况下做出如下指令:
mov rsi, msg

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

对不起,如果我写了完全废话,我是组装新手,我暂时无法掌握它。

【问题讨论】:

  • 它是消息的地址,就像在 C 中使用指向字符串的指针一样。
  • 感谢您的快速响应。学习了 C 以外的高级语言,所以我不熟悉指针。但我现在明白了。

标签: string assembly x86 nasm


【解决方案1】:

在 NASM 语法中(与 MASM 语法不同)mov rsi, symbol 将符号的 地址 放入 RSI。 (使用 64 位绝对立即数效率低下;改用 RIP 相对 LEA 或 mov esi, symbolHow 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?

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

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

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

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

【讨论】:

    【解决方案2】:

    免责声明:我不熟悉您正在处理的汇编风格,因此以下内容更为笼统。特定的风味可能比我习惯的具有更多的功能。通常,汇编处理大小取决于处理器的单字节/字实体。我在 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 中的指针。您将需要某种指示来指示字符串的终止或另一个指示字符串大小的值,以便您知道何时停止。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-11-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-04
      • 1970-01-01
      • 2018-09-13
      • 1970-01-01
      • 2017-04-09
      相关资源
      最近更新 更多