c语言 - 对此 asm x86 代码的意义进行故障排除



首先,这里是汇编代码:

/           0x000006a0      55             push rbp                             
|           0x000006a1      4889e5         mov rbp, rsp                         
|           0x000006a4      4883ec10       sub rsp, 0x10                        
|           0x000006a8      488d05b50000.  lea rax, str.AAAA           ; 0x764  
|           0x000006af      488945f8       mov qword [local_8h], rax  
|           0x000006b3      488b45f8       mov rax, qword [local_8h]
|           0x000006b7      4889c6         mov rsi, rax                         
|           0x000006ba      488d3da80000.  lea rdi, 0x00000769         ; "%s"   
|           0x000006c1      b800000000     mov eax, 0                           
|           0x000006c6      e895feffff     call sym.imp.printf         ;[2] ; i 
|           0x000006cb      b800000000     mov eax, 0                           
|           0x000006d0      c9             leave                                
           0x000006d1      c3             ret  

到这个 C 程序:

#include <stdio.h>
#include <string.h>
int main(){
char* a = "AAAA";
printf("%s", a);
return 0;
}

特别是我对这段代码有一个问题:

|           0x000006af      488945f8       mov qword [local_8h], rax            
|           0x000006b3      488b45f8       mov rax, qword [local_8h]

这两个指令的意义是什么?我只看到一种方式和相反的相同指令。但这是为什么呢?

以下是可执行文件的一些进一步信息:

blksz    0x0
block    0x100
fd       6
file     demo
format   elf64
iorw     false
mode     -r--
size     0x20e0
humansz  8.2K
type     DYN (Shared object file)
arch     x86
binsz    6559
bintype  elf
bits     64
canary   false
class    ELF64
crypto   false
endian   little
havecode true
intrp    /lib64/ld-linux-x86-64.so.2
lang     c
linenum  true
lsyms    true
machine  AMD x86-64 architecture
maxopsz  16
minopsz  1
nx       true
os       linux
pcalign  0
pic      true
relocs   true
relro    partial relro
rpath    NONE
static   false
stripped false
subsys   linux
va       true

这些行彼此分开:

第一行属于char* a = "AAAA";行,将变量的值保存到RAM。

第二行从 RAM 访问变量,将行printf("%s", a);作为参数。

从技术上讲,这两行都是可选的,正如您可能写的那样:

printf("%s", "AAAA");

编辑:要跳过这些不必要的代码,您可以启用自动优化(对于GCC:-O2)

问题是你的反汇编器坏了(或者至少"太聪明了")并且"有用"地给你提供了与人们通常期望的不同、令人困惑的信息。 这两行:

|           0x000006af      488945f8       mov qword [local_8h], rax            
|           0x000006b3      488b45f8       mov rax, qword [local_8h]

应该是

|           0x000006af      488945f8       mov qword [rbp-8h], rax            
|           0x000006b3      488b45f8       mov rax, qword [rbp-8h]

它们通过rbp寄存器间接访问堆栈帧中的存储器。 这种内存由编译器用于局部变量,因此反汇编器显示的"局部"。

最新更新