【问题标题】:Differences between MOV, LEA and OFFSETMOV、LEA 和 OFFSET 的区别
【发布时间】:2015-12-23 12:22:22
【问题描述】:

当然MOV“移动”(实际上是复制)一些东西,但是如何?它是将源中的实际值放入目的地还是放入某种地址。

当我在 Jeff Duntemann 介绍性汇编书中看到他正在使用 Linux 的 80h 中断时,我想到了这个问题:

mov eax,4    ; Specify sys_write call
mov ebx,1    ; Specify File Descriptor 1: Standard output
mov ecx,Buff ; Pass address of the character to write
mov edx,1    ; Pass number of chars to write
int 80h      ; Call sys_write

在开始阅读之前,我几乎没有练习过 TASM,但知道 LEA 指令。所以当我看到:

mov ecx,Buff ; Pass address of the character to write

这让我大吃一惊,因为我使用 LEA(加载有效地址)或 OFFSET 将地址放入寄存器,而他正在使用 MOV

两种形式都正确吗?不过,他正在使用 NASM,是因为汇编程序吗?我现在很困惑,因为我习惯于看到 MOV 将值而不是地址。

【问题讨论】:

  • 是的,这是因为不同的汇编器不幸使用不同的语法。我在stackoverflow.com/questions/34058101/… 的回答中介绍了label 作为源操作数(除其他外)的MASM 和NASM 语法之间的区别。您可能会发现其中一些有用(或者没有,IDK!)通常当您使用LEA 将地址放入寄存器(而不是mov reg, imm32)时,它在 64 位模式下获得 RIP 相对寻址(位置独立于不需要搬家。)

标签: assembly nasm tasm


【解决方案1】:

MOV(移动)指令在内存和寄存器之间或寄存器之间传输数据。 MOV 指令在内存和处理器的寄存器之间执行基本的加载数据和存储数据操作以及寄存器之间的数据移动操作。MOV 指令不能将数据从一个内存位置移动到另一个内存位置或从一个段寄存器移动到 另一个段寄存器。使用MOVS(字符串移动)指令执行内存到内存的移动。

LEA(加载有效地址)指令计算源操作数在内存中的有效地址(段内的偏移量)并将其放入通用寄存器中。该指令可以解释任何处理器的 寻址模式,并且可以执行任何可能需要的索引或缩放。

Intel 64 和 IA-32 架构软件开发人员手册

它作为3-operand non-destructive add 也非常有用,例如ecx = eax + edx*4 - 15


NASM 通过使用更简单的内存引用语法来避免这种不良情况。规则很简单,对内存位置内容的任何访问都需要在地址两边加上方括号,而对变量地址的任何访问都不需要。因此mov ax, foo 形式的指令将始终引用编译时常量,无论它是EQU 还是变量的地址;要访问变量 bar 的内容,您必须编码 mov ax, [bar]。这也意味着 NASM 不需要 MASM 的 OFFSET 关键字,因为 MASM 代码 mov ax, offset barMASM 的含义完全相同strong>NASM 的 mov ax,bar.

Nasm 文档


从以上所有内容中,您可能会看到在 asm 中获取变量地址的方法有多种,并且这些方法在不同的汇编语言中可能并且将会有所不同。要找到问题的答案,最好查看文档(汇编语言通常都有详细的文档)。

你应该永远记住,在编程中总是有几种方法可以解决一个特定的问题。

【讨论】:

  • LEA 的许多用例都是针对非地址值的数学运算。例如通用整数数学运算,结果写入第三个寄存器。
猜你喜欢
  • 2011-02-17
  • 2010-12-14
  • 2016-05-30
  • 1970-01-01
  • 1970-01-01
  • 2016-05-29
  • 2017-05-05
相关资源
最近更新 更多