2017-03-09 76 views
1

我在阅读Haching:开发的艺术我发现编译代码和书中的代码有所不同。序幕函数的区别

代码:

void test_function(int a, int b, int c, int d) { 

    int flag; 
    char buffer[10]; 

    flag = 31337; 
    buffer[0] = 'A'; 
} 

int main() { 

    test_function(1, 2, 3, 4); 
} 

在他用gcc编译和使用gdb反汇编的书,我不知道这个软件的版本。 他使用的命令:

gcc -g program.c 
gdb -q ./a.out 

然后,他做:

(gdb) disass main 
Dump of assembler code for function main(): 
0x08048357 <main+0>: push ebp 
0x08048358 <main+1>: mov ebp,esp 
0x0804835a <main+3>: sub esp,0x18 
0x0804835d <main+6>: and esp,0xfffffff0 
0x08048360 <main+9>: mov eax,0x0 
0x08048365 <main+14>: sub esp,eax 
0x08048367 <main+16>: mov DWORD PTR [esp+12],0x4 
0x0804836f <main+24>: mov DWORD PTR [esp+8],0x3 
0x08048377 <main+32>: mov DWORD PTR [esp+4],0x2 
0x0804837f <main+40>: mov DWORD PTR [esp],0x1 
0x08048386 <main+47>: call 0x8048344 <test_function> 
0x0804838b <main+52>: leave 
0x0804838c <main+53>: ret  

End of assembler dump 
(gdb) disass test_function() 
Dump of assembler code for function test_function: 
0x08048344 <test_function+0>: push ebp 
0x08048345 <test_function+1>: mov ebp,esp 
0x08048347 <test_function+3>: sub esp,0x28 
0x0804834a <test_function+6>: mov DWORD PTR [ebp-12],0x7a69 
0x08048351 <test_function+13>: mov BYTE PTR [ebp-40],0x41 
0x08048355 <test_function+17>: leave 
0x08048356 <test_function+18>: ret  

这实际上是我的输出(使用相同的命令):

(gdb) disass main 
Dump of assembler code for function main: 
    0x000000000040058b <+0>: push rbp 
    0x000000000040058c <+1>: mov rbp,rsp 
    0x000000000040058f <+4>: mov ecx,0x4 
    0x0000000000400594 <+9>: mov edx,0x3 
    0x0000000000400599 <+14>: mov esi,0x2 
    0x000000000040059e <+19>: mov edi,0x1 
    0x00000000004005a3 <+24>: call 0x400546 <test_function> 
    0x00000000004005a8 <+29>: mov eax,0x0 
    0x00000000004005ad <+34>: pop rbp 
    0x00000000004005ae <+35>: ret  
End of assembler dump. 

(gdb) disass test_function 
Dump of assembler code for function test_function: 
    0x0000000000400546 <+0>: push rbp 
    0x0000000000400547 <+1>: mov rbp,rsp 
    0x000000000040054a <+4>: sub rsp,0x40 
    0x000000000040054e <+8>: mov DWORD PTR [rbp-0x34],edi 
    0x0000000000400551 <+11>: mov DWORD PTR [rbp-0x38],esi 
    0x0000000000400554 <+14>: mov DWORD PTR [rbp-0x3c],edx 
    0x0000000000400557 <+17>: mov DWORD PTR [rbp-0x40],ecx 
    0x000000000040055a <+20>: mov rax,QWORD PTR fs:0x28 
    0x0000000000400563 <+29>: mov QWORD PTR [rbp-0x8],rax 
    0x0000000000400567 <+33>: xor eax,eax 
    0x0000000000400569 <+35>: mov DWORD PTR [rbp-0x24],0x7a69 
    0x0000000000400570 <+42>: mov BYTE PTR [rbp-0x20],0x41 
    0x0000000000400574 <+46>: nop 
    0x0000000000400575 <+47>: mov rax,QWORD PTR [rbp-0x8] 
    0x0000000000400579 <+51>: xor rax,QWORD PTR fs:0x28 
    0x0000000000400582 <+60>: je  0x400589 <test_function+67> 
    0x0000000000400584 <+62>: call 0x400420 <[email protected]> 
    0x0000000000400589 <+67>: leave 
    0x000000000040058a <+68>: ret  
End of assembler dump. 

我使用gcc版本5.4 .0和gdb版本7.11.1。

我有两个问题:

  • 为什么功能proloque不同?书本编译器给出的指令与我给出的指令有什么不同? (我不是在谈论注册名称,我正在谈论为什么我的主要序言只是推动和移动)

  • 可能由于可能的堆栈溢出和编译器而导致test_function的差异(更新比另一个)知道并修补它?如果是这样,它是如何知道存在缺陷以及采用什么方法来修补它的?

编辑:我知道这本书版本在32位架构编制。我的问题是关于编译器的不同指令,如果他们必须做同样的事情,他们为什么不同?

+0

编译器随时间变化,特别是GCC更新频率不足以产生不同版本的相同代码。你的版本最可能是作者用来写这本书的新版本。 – StoryTeller

+3

您正在编译x86-64,本书编译x86(32位)。 – EOF

+0

为了响应你的编辑,他们在64位和32位之间不同的原因是因为调用约定不同。另一个区别是,你使用的是与本书不同的编译器,它也在构建堆栈检查(如果你使用的是更高版本的Debian或Ubuntu,这并不罕见) –

回答

1

该书的版本是在32位体系结构上编译的,64位是你的一个。使用-m32开关生成32位可执行文件。

+0

也许我的问题不清楚。我知道这本书的版本是在32位体系结构上编译的,我的问题是关于编译器的不同指令,如果它们必须做同样的事情,它们为什么不同? – Erika