示例中的 MOV 和 LEA 有什么区别?

逆向工程 部件 x86-64 汇编 指针 纳姆
2021-06-17 06:32:44

查看我看到的汇编代码片段:

lea rax, [rbp-0x50]

这告诉我rax寄存器现在指向 rbp-hex(50) 中的任何值。

问题。这样做我会得到同样的结果吗?

mov rax, dword ptr [rbp-0x50]

如果是这样,lea无论如何需要指令?

感谢您在我深入研究 64b 汇编程序时的耐心等待。

4个回答

lea = 地址
mov = 内容

如果地址 0x401000 包含 0xDeadBeef 就像 ef be ad de

lea MySecretPlace, [401000] MySecretPlace 将是 0x401000
Mov MySecretPlace, [401000] MySecretPlace 将是 DeadBeef

mov MySecretPlace, byte ptr [401000] MySecretPlace 将是 0xef 0r 0xef 取决于 EndianNess

mov MySecretPlace, word ptr [401000] MySecretPlace 将是 0xdead 0r 0xadde 取决于 EndianNess

在此处输入图片说明

在下面找到一个小的演示

:\>cat lea.cpp
#include <stdio.h>
int main (void) {
    unsigned int secret = 0xdeadbeef;
    printf("DWORD PTR ds:[%p] == %x\n" , &secret,*(unsigned int   *)&secret);
    printf("WORD  PTR ds:[%p] == %x\n" , &secret,*(unsigned short *)&secret);
    printf("BYTE  PTR ds:[%p] == %x\n" , &secret,*(unsigned char  *)&secret);
        return 0;
}

编译并链接到

:\>bld.bat lea

:\>cl /Zi /W4 /O1 /analyze /EHsc /nologo  lea.cpp /link /release
lea.cpp

被执行

:\>lea.exe
DWORD PTR ds:[0030F7DC] == deadbeef
WORD  PTR ds:[0030F7DC] == beef
BYTE  PTR ds:[0030F7DC] == ef

拆解

:\>cdb -c "uf lea!main;q" lea.exe 
0:000> cdb: Reading initial command 'uf lea!main;q'
lea!main:
00fe1029 55              push    ebp
00fe102a 8bec            mov     ebp,esp
00fe102c 51              push    ecx
00fe102d b8efbeadde      mov     eax,0DEADBEEFh
00fe1032 50              push    eax
00fe1033 8945fc          mov     dword ptr [ebp-4],eax
00fe1036 8d45fc          lea     eax,[ebp-4]
00fe1039 50              push    eax
00fe103a 6890010201      push    offset lea!`string' (01020190)
00fe103f e82d000000      call    lea!printf (00fe1071)
00fe1044 0fb745fc        movzx   eax,word ptr [ebp-4]
00fe1048 50              push    eax
00fe1049 8d45fc          lea     eax,[ebp-4]
00fe104c 50              push    eax
00fe104d 68ac010201      push    offset lea!`string' (010201ac)
00fe1052 e81a000000      call    lea!printf (00fe1071)
00fe1057 0fb645fc        movzx   eax,byte ptr [ebp-4]
00fe105b 50              push    eax
00fe105c 8d45fc          lea     eax,[ebp-4]
00fe105f 50              push    eax
00fe1060 68c8010201      push    offset lea!`string' (010201c8)
00fe1065 e807000000      call    lea!printf (00fe1071)
00fe106a 83c424          add     esp,24h
00fe106d 33c0            xor     eax,eax
00fe106f c9              leave
00fe1070 c3              ret
quit:

这是基本的。假设 rpb 的值为 55h(汇编程序语法)。然后 lea rax, [rbp-50h] 将导致 5。

另一方面,mov rax, [rbp-50h]很可能会使您的应用程序崩溃,因为它会尝试读取地址 5 的内容并将其放入 rax。

因此,区别在于第一个是直接的,第二个是间接的。顺便说一句,您可以轻松地自己尝试一下!

警告:用于解释的非法指令。
如果您想知道是否mov可以完成 的工作lea
mov eax, esp+4并将lea eax, [esp+4]相同的值复制到eax.
但是,mov eax, esp+4不是法律指令!esp+4不是合法的寻址模式。)
但是,您可以替换lea eax, [esp+4]为以下内容吗?

mov eax, esp
add eax, 4

并不真地!eax执行上述指令后的值将匹配lea eax, [esp+4]但它们仍然不一样!这是因为add指令可能会修改标志,而lea不会。

不同的是lea只计算地址,而mov实际移动数据。如果你知道 C 或 C++,它有点类似于:

  1. 利亚:rax = rbp + 0x50;
  2. 移动: rax = rbp[0x50];

(由于计数方式不同,不等同于组装)