深入理解计算机系统读书笔记之一个简单汇编程序的调试分析

为了深入理解汇编程序中的帧指针(ebp)和栈指针(esp)的用法,想亲自调试下程序,我写了一个简单的程序,如下:  #include <stdio.h> int add (int a, int b, int c); int main (int *argc, char *argv[]) { int a = 3; int b = 4; int c = 5; add (a, b, c); return 0; } int add (int a, int b, int c) { return a + b + c; }     

保存为hello.c,然后在终端输入gcc -S hello.c,就会有个hello.s生成,也就是上面程序对应的汇编程序了,主要程序清单如下:                         

_start: //这里将main改成了_start,否则gdb找不到入口点 //另外加了一个nop,可以让程序在这里断下来 nop leal 4(%esp), %ecx andl $-16, %esp pushl -4(%ecx) pushl %ebp movl %esp, %ebp pushl %ecx subl $36, %esp movl $3, -16(%ebp) movl $4, -12(%ebp) movl $5, -8(%ebp) movl -8(%ebp), %eax movl %eax, 8(%esp) movl -12(%ebp), %eax movl %eax, 4(%esp) movl -16(%ebp), %eax movl %eax, (%esp) call add movl $0, %eax addl $36, %esp popl %ecx popl %ebp leal -4(%ecx), %esp ret .size main, .-main .globl add .type add, @function add: pushl %ebp movl %esp, %ebp movl 12(%ebp), %edx movl 8(%ebp), %eax addl %edx, %eax addl 16(%ebp), %eax popl %ebp ret 

然后使用as -gstabs -o hello.o hello.s和ld -o hello hello.o生成可执行文件,最后就可以调试了,这里就是本文的重点了。

一、设断点

break *_start + 1,程序会在nop那里停下来

二、run

三、我调试的每一步

Breakpoint 1, _start () at hello.s:7
7        leal    4(%esp), %ecx

(gdb) info registers eax 0x0 0 ecx 0x0 0 edx 0x0 0 ebx 0x0 0 esp 0xbffff5c0 0xbffff5c0 ebp 0x0 0x0 esi 0x0 0 edi 0x0 0 eip 0x8048095 0x8048095 <_start+1> eflags 0x200292 [ AF SF IF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x0 0         

(gdb) next
8        andl    $-16, %esp

(gdb) info registers //查看寄存器,果然ecx = esp + 4 eax 0x0 0 ecx 0xbffff5c4 -1073744444 edx 0x0 0 ebx 0x0 0 esp 0xbffff5c0 0xbffff5c0 ebp 0x0 0x0 esi 0x0 0 edi 0x0 0 eip 0x8048099 0x8048099 <_start+5> eflags 0x200292 [ AF SF IF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x0 0

然后的这句话比较费解 andl %-16, %esp,-16的二进制表示为0xFFFFFFF0,这里是将SP的低4位清零了,这样地址就是16的整数倍了,寻址会更快,因为esp的低4位本身就是0,所以这句话在这里并没有起到作用,我们就把这里跳过,直接next

(gdb) next
9        pushl    -4(%ecx)                             
(gdb) next
10        pushl    %ebp

(gdb) info registers //pushl -4(%ecx) ,把ecx压栈,esp -= 4 eax 0x0 0 ecx 0xbffff5c4 -1073744444 edx 0x0 0 ebx 0x0 0 esp 0xbffff5bc 0xbffff5bc ebp 0x0 0x0 esi 0x0 0 edi 0x0 0 eip 0x804809f 0x804809f <_start+11> eflags 0x200286 [ PF SF IF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x0 0

(gdb) next
11        movl    %esp, %ebp

(gdb) info registers // pushl %ebp,ebp压栈,esp -= 4 eax 0x0 0 ecx 0xbffff5c4 -1073744444 edx 0x0 0 ebx 0x0 0 esp 0xbffff5b8 0xbffff5b8 ebp 0x0 0x0 esi 0x0 0 edi 0x0 0 eip 0x80480a0 0x80480a0 <_start+12> eflags 0x200286 [ PF SF IF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x0 0

(gdb) next
_start () at hello.s:12
12        pushl    %ecx

(gdb) info registers //movl %esp, %ebp, ebp = esp eax 0x0 0 ecx 0xbffff5c4 -1073744444 edx 0x0 0 ebx 0x0 0 esp 0xbffff5b8 0xbffff5b8 ebp 0xbffff5b8 0xbffff5b8 esi 0x0 0 edi 0x0 0 eip 0x80480a2 0x80480a2 <_start+14> eflags 0x200286 [ PF SF IF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x0 0
(gdb) next
13        subl    $36, %esp

(gdb) info registers //pushl %ecx, ecx压栈, esp -= 4 eax 0x0 0 ecx 0xbffff5c4 -1073744444 edx 0x0 0 ebx 0x0 0 esp 0xbffff5b4 0xbffff5b4 ebp 0xbffff5b8 0xbffff5b8 esi 0x0 0 edi 0x0 0 eip 0x80480a3 0x80480a3 <_start+15> eflags 0x200286 [ PF SF IF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x0 0

(gdb) next
14        movl    $3, -16(%ebp)

(gdb) info registers //subl $36, %esp,esp -= 36,分配36个字节的空间 eax 0x0 0 ecx 0xbffff5c4 -1073744444 edx 0x0 0 ebx 0x0 0 esp 0xbffff590 0xbffff590 ebp 0xbffff5b8 0xbffff5b8 esi 0x0 0 edi 0x0 0 eip 0x80480a6 0x80480a6 <_start+18> eflags 0x200286 [ PF SF IF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x0 0

(gdb) next
15        movl    $4, -12(%ebp)

(gdb) info registers //movl $3, -16(%ebp), *(ebp - 16) = 3 eax 0x0 0 ecx 0xbffff5c4 -1073744444 edx 0x0 0 ebx 0x0 0 esp 0xbffff590 0xbffff590 ebp 0xbffff5b8 0xbffff5b8 esi 0x0 0 edi 0x0 0 eip 0x80480ad 0x80480ad <_start+25> eflags 0x200286 [ PF SF IF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x0 0

(gdb) next
16        movl    $5, -8(%ebp)

(gdb) info registers //movl $4, -12(%ebp), *(ebp - 12) = 4 eax 0x0 0 ecx 0xbffff5c4 -1073744444 edx 0x0 0 ebx 0x0 0 esp 0xbffff590 0xbffff590 ebp 0xbffff5b8 0xbffff5b8 esi 0x0 0 edi 0x0 0 eip 0x80480b4 0x80480b4 <_start+32> eflags 0x200286 [ PF SF IF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x0 0

(gdb) next
17        movl    -8(%ebp), %eax

(gdb) info registers //movl $5, -8(%ebp), *(ebp -8) = 5 eax 0x0 0 ecx 0xbffff5c4 -1073744444 edx 0x0 0 ebx 0x0 0 esp 0xbffff590 0xbffff590 ebp 0xbffff5b8 0xbffff5b8 esi 0x0 0 edi 0x0 0 eip 0x80480bb 0x80480bb <_start+39> eflags 0x200286 [ PF SF IF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x0 0

3, 4, 5就分别存放到了ebp -16, ebp -12, ebp -8 这3个位置

我们查看下是不是这样的

(gdb) x /4 0xbffff5a8                                    //果然在
0xbffff5a8:    3    4    5    -1073744444

(gdb) next
18        movl    %eax, 8(%esp)

(gdb) info registers //movl -8(%ebp), %eax, eax = *(ebp - 8) eax 0x5 5 ecx 0xbffff5c4 -1073744444 edx 0x0 0 ebx 0x0 0 esp 0xbffff590 0xbffff590 ebp 0xbffff5b8 0xbffff5b8 esi 0x0 0 edi 0x0 0 eip 0x80480be 0x80480be <_start+42> eflags 0x200286 [ PF SF IF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x0 0
(gdb) next
19        movl    -12(%ebp), %eax
(gdb) info registers //mov %eax, 8(%esp), *(esp + 8) = eax eax 0x5 5 ecx 0xbffff5c4 -1073744444 edx 0x0 0 ebx 0x0 0 esp 0xbffff590 0xbffff590 ebp 0xbffff5b8 0xbffff5b8 esi 0x0 0 edi 0x0 0 eip 0x80480c2 0x80480c2 <_start+46> eflags 0x200286 [ PF SF IF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x0 0

(gdb) next
20        movl    %eax, 4(%esp)

(gdb) info registers //movl -12(%ebp), %eax, eax = *(ebp - 12) eax 0x4 4 ecx 0xbffff5c4 -1073744444 edx 0x0 0 ebx 0x0 0 esp 0xbffff590 0xbffff590 ebp 0xbffff5b8 0xbffff5b8 esi 0x0 0 edi 0x0 0 eip 0x80480c5 0x80480c5 <_start+49> eflags 0x200286 [ PF SF IF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x0 0
(gdb) next
21        movl    -16(%ebp), %eax

(gdb) info registers //movl %eax, 4(%esp), *(esp + 4) = eax eax 0x4 4 ecx 0xbffff5c4 -1073744444 edx 0x0 0 ebx 0x0 0 esp 0xbffff590 0xbffff590 ebp 0xbffff5b8 0xbffff5b8 esi 0x0 0 edi 0x0 0 eip 0x80480c9 0x80480c9 <_start+53> eflags 0x200286 [ PF SF IF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x0 0
(gdb) next
22        movl    %eax, (%esp)

(gdb) info registers //movl -16(%ebp), %eax, eax = *(ebp - 16) eax 0x3 3 ecx 0xbffff5c4 -1073744444 edx 0x0 0 ebx 0x0 0 esp 0xbffff590 0xbffff590 ebp 0xbffff5b8 0xbffff5b8 esi 0x0 0 edi 0x0 0 eip 0x80480cc 0x80480cc <_start+56> eflags 0x200286 [ PF SF IF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x0 0
(gdb) next
23        call    add

(gdb) info registers //movl %eax, (%esp), *esp = %eax eax 0x3 3 ecx 0xbffff5c4 -1073744444 edx 0x0 0 ebx 0x0 0 esp 0xbffff590 0xbffff590 ebp 0xbffff5b8 0xbffff5b8 esi 0x0 0 edi 0x0 0 eip 0x80480cf 0x80480cf <_start+59> eflags 0x200286 [ PF SF IF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x0 0
(gdb) step
add () at hello.s:34
34        pushl    %ebp

(gdb) info registers //这里进入了add函数,esp会将函数的返回地址压栈,esp -= 4 eax 0x3 3 ecx 0xbffff5c4 -1073744444 edx 0x0 0 ebx 0x0 0 esp 0xbffff58c 0xbffff58c ebp 0xbffff5b8 0xbffff5b8 esi 0x0 0 edi 0x0 0 eip 0x80480e2 0x80480e2 <add> eflags 0x200286 [ PF SF IF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x0 0
(gdb) next
35        movl    %esp, %ebp

(gdb) info registers //pushl %ebp,ebp压栈,esp -= 4 eax 0x3 3 ecx 0xbffff5c4 -1073744444 edx 0x0 0 ebx 0x0 0 esp 0xbffff588 0xbffff588 ebp 0xbffff5b8 0xbffff5b8 esi 0x0 0 edi 0x0 0 eip 0x80480e3 0x80480e3 <add+1> eflags 0x200286 [ PF SF IF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x0 0
(gdb) next
36        movl    12(%ebp), %edx

(gdb) info registers //movl %esp, %ebp, ebp = esp eax 0x3 3 ecx 0xbffff5c4 -1073744444 edx 0x0 0 ebx 0x0 0 esp 0xbffff588 0xbffff588 ebp 0xbffff588 0xbffff588 esi 0x0 0 edi 0x0 0 eip 0x80480e5 0x80480e5 <add+3> eflags 0x200286 [ PF SF IF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x0 0
(gdb) next
37        movl    8(%ebp), %eax

(gdb) info registers //movl 12(%ebp), %edx, edx = *(ebp + 12) eax 0x3 3 ecx 0xbffff5c4 -1073744444 edx 0x4 4 ebx 0x0 0 esp 0xbffff588 0xbffff588 ebp 0xbffff588 0xbffff588 esi 0x0 0 edi 0x0 0 eip 0x80480e8 0x80480e8 <add+6> eflags 0x200286 [ PF SF IF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x0 0
(gdb) next
38        addl    %edx, %eax

(gdb) info registers //movl 8(%ebp), %eax,eax = *(ebp + 8) eax 0x3 3 ecx 0xbffff5c4 -1073744444 edx 0x4 4 ebx 0x0 0 esp 0xbffff588 0xbffff588 ebp 0xbffff588 0xbffff588 esi 0x0 0 edi 0x0 0 eip 0x80480eb 0x80480eb <add+9> eflags 0x200286 [ PF SF IF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x0 0
(gdb) next
39        addl    16(%ebp), %eax

(gdb) x /4 0xbffff590 0xbffff590: 3 4 5 0 (gdb) info registers //addl %edx, %eax, eax = eax + edx eax 0x7 7 ecx 0xbffff5c4 -1073744444 edx 0x4 4 ebx 0x0 0 esp 0xbffff588 0xbffff588 ebp 0xbffff588 0xbffff588 esi 0x0 0 edi 0x0 0 eip 0x80480ed 0x80480ed <add+11> eflags 0x200202 [ IF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x0 0
(gdb) next
40        popl    %ebp

(gdb) info registers //addl 16(%ebp), %eax, eax += *(ebp + 16) eax 0xc 12 ecx 0xbffff5c4 -1073744444 edx 0x4 4 ebx 0x0 0 esp 0xbffff588 0xbffff588 ebp 0xbffff588 0xbffff588 esi 0x0 0 edi 0x0 0 eip 0x80480f0 0x80480f0 <add+14> eflags 0x200206 [ PF IF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x0 0
(gdb) next
add () at hello.s:41
41        ret

(gdb) info registers //popl %ebp ,ebp出栈, esp += 4 eax 0xc 12 ecx 0xbffff5c4 -1073744444 edx 0x4 4 ebx 0x0 0 esp 0xbffff58c 0xbffff58c ebp 0xbffff5b8 0xbffff5b8 esi 0x0 0 edi 0x0 0 eip 0x80480f1 0x80480f1 <add+15> eflags 0x200206 [ PF IF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x0 0
(gdb) next
_start () at hello.s:24
24        movl    $0, %eax

(gdb) info registers //ret , esp += 4, 函数返回地址出栈 eax 0xc 12 ecx 0xbffff5c4 -1073744444 edx 0x4 4 ebx 0x0 0 esp 0xbffff590 0xbffff590 ebp 0xbffff5b8 0xbffff5b8 esi 0x0 0 edi 0x0 0 eip 0x80480d4 0x80480d4 <_start+64> eflags 0x200206 [ PF IF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x0 0
(gdb) next
25        addl    $36, %esp


(gdb) info registers //movl $0, %eax, eax = 0 eax 0x0 0 ecx 0xbffff5c4 -1073744444 edx 0x4 4 ebx 0x0 0 esp 0xbffff590 0xbffff590 ebp 0xbffff5b8 0xbffff5b8 esi 0x0 0 edi 0x0 0 eip 0x80480d9 0x80480d9 <_start+69> eflags 0x200206 [ PF IF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x0 0

(gdb) next
26        popl    %ecx

(gdb) info registers //addl $36, %esp , esp += 36,释放36个字节 eax 0x0 0 ecx 0xbffff5c4 -1073744444 edx 0x4 4 ebx 0x0 0 esp 0xbffff5b4 0xbffff5b4 ebp 0xbffff5b8 0xbffff5b8 esi 0x0 0 edi 0x0 0 eip 0x80480dc 0x80480dc <_start+72> eflags 0x200286 [ PF SF IF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x0 0
(gdb) next
27        popl    %ebp
(gdb) info registers //popl %ecx , esp += 4 eax 0x0 0 ecx 0xbffff5c4 -1073744444 edx 0x4 4 ebx 0x0 0 esp 0xbffff5b8 0xbffff5b8 ebp 0xbffff5b8 0xbffff5b8 esi 0x0 0 edi 0x0 0 eip 0x80480dd 0x80480dd <_start+73> eflags 0x200286 [ PF SF IF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x0 0

(gdb) next
_start () at hello.s:28
28        leal    -4(%ecx), %esp         

(gdb) info registers //popl %ebp, esp += 4 eax 0x0 0 ecx 0xbffff5c4 -1073744444 edx 0x4 4 ebx 0x0 0 esp 0xbffff5bc 0xbffff5bc ebp 0x0 0x0 esi 0x0 0 edi 0x0 0 eip 0x80480de 0x80480de <_start+74> eflags 0x200286 [ PF SF IF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x0 0                  

(gdb) next
_start () at hello.s:29
29        ret

(gdb) info registers //esp = *(ecx - 4) eax 0x0 0 ecx 0xbffff5c4 -1073744444 edx 0x4 4 ebx 0x0 0 esp 0xbffff5c0 0xbffff5c0 ebp 0x0 0x0 esi 0x0 0 edi 0x0 0 eip 0x80480e1 0x80480e1 <_start+77> eflags 0x200286 [ PF SF IF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x0 0
(gdb) next
0x00000001 in ?? ()

(gdb) info registers eax 0x0 0 ecx 0xbffff5c4 -1073744444 edx 0x4 4 ebx 0x0 0 esp 0xbffff5c4 0xbffff5c4 ebp 0x0 0x0 esi 0x0 0 edi 0x0 0 eip 0x1 0x1 eflags 0x200286 [ PF SF IF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x0 0
程序结束

你可能感兴趣的:(c,汇编,gcc,读书,终端)