C 此asm x86代码的故障排除
首先,这里是汇编程序代码:C 此asm x86代码的故障排除,c,assembly,x86,instructions,C,Assembly,X86,Instructions,首先,这里是汇编程序代码: / 0x000006a0 55 push rbp | 0x000006a1 4889e5 mov rbp, rsp | 0x000006a4 4883ec10 sub rsp, 0x10
/ 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;
}
这两个指令的意义是什么?我只看到同样的指令是单向的,而不是反向的。但为什么呢
以下是可执行文件的一些进一步信息:
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
寄存器间接访问堆栈帧中的内存。编译器将这种内存用于局部变量,因此反汇编程序显示的是“局部”。您应该检查非调试代码,即删除这些不必要存储的代码。编译器通常使用非常简单的规则将源代码分解为一系列基本步骤(有时称为“中间代码”)然后,他们优化中间代码以消除冗余或浪费的步骤。您似乎已在关闭优化的情况下编译了此代码。您在未进行优化的情况下编译了代码。毫不奇怪,当你告诉编译器不要优化时,编译器会发出无用的奇怪代码@fuz您的声明听起来有点像“编译器供应商通过在非优化输出中引入箔条来区分优化输出和非优化输出”。我想编译器供应商会认为这是一种侮辱。另外,根据我的经验,优化后的版本更奇怪,但原因很好,即使很复杂。@Yunnosch至少gcc关闭了寄存器分配,使用了更简单的指令选择器,并且在没有优化的情况下生成了额外的糟糕代码。这需要额外的代码来支持,所以从某种意义上说,是的,编译器编写者在没有优化的情况下确实会让代码变得更糟糕。或者,程序员可以打开优化,让编译器来完成,而不是从源代码中删除局部变量a
。从这个简单的例子中可能看不出这一点,但是手工优化源代码通常会降低可读性,并且通常不如让编译器来做那样有效。你完全正确。我的例子应该说明为什么会出现装配线。OP并不是问local_8h
是什么意思。OP询问第二条指令的目的是什么,当它加载到rax
中的值不可能与rax
中已有的值不同时?答案是,因为这两行中的每一行都是从不同的源代码行生成的,并且优化被关闭。
| 0x000006af 488945f8 mov qword [rbp-8h], rax
| 0x000006b3 488b45f8 mov rax, qword [rbp-8h]