前言
为能深入学习Linux,提高编程能力,探寻奇妙的编程之旅,参加了网易的《Linux内核分析》公开课。
卢晅 + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
第一章 原文件处理
C语言源代码:
int a(int x)
{
return x + 5;
}
int b(int x)
{
return a(x);
}
int main(void)
{
return b(7) + 6;
}
得出的汇编代码:
a:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax
addl $5, %eax
popl %ebp
ret
b:
pushl %ebp
movl %esp, %ebp
pushl 8(%ebp)
call a
addl $4, %esp
leave
ret
main:
pushl %ebp
movl %esp, %ebp
pushl $7
call b
addl $4, %esp
addl $6, %eax
leave
第二章 调试
实验环境为:Ubuntu 14.10
在终端中输入了:gcc -S -o main.s main.c -m32
接着打开main.s并通过gdb命令进行分析:
实验环境为:Ubuntu 14.10
在终端中输入了:gcc -S -o main.s main.c -m32
接着打开main.s并通过gdb命令进行分析:
gdb ./main
gdb layout asm
gdb layout regs
然后得到如下结果:
所需要注意的是,如果gdb提示The program is not being run.则输入r。如果要结束调试则输入kill,退出输入q。
设置断点
(gdb)b main
(gdb)b a
(gdb)b b
接着:输入r运行。
然后输入:
(gdb)si
进行逐句分析。
结果发现一个有趣的现象便是:函数真正开始的地方为:<function name+3>的位置。
输入(gdb)layout regs查看寄存器的结果:
这里我选了几张,因为步骤太多了:
开始:
第一步:
最后:
第三章 分析
a:
pushl %ebp
pushl %ebp
esp先指向下一位,将esp和ebp指向同一地方。
movl %esp, %ebp
movl %esp, %ebp
将esp和ebp指向同一地方。
movl 8(%ebp), %eax
movl 8(%ebp), %eax
将epb的值8赋值给eax。
addl $5, %eax
addl $5, %eax
eax的值加5。
popl %ebp
popl %ebp
相当于两步:
movl (%esp),%eax
addl $4,%esp
则:将esp所指向的值赋值给eax,接着esp向上移动一位。
ret
相当于pop eip(*)
则:eip的值赋值给eax,而esp则指向上一位内存空间。
b:
pushl %ebp
b:
pushl %ebp
esp先指向下一位,将ebp的值赋值给esp所指的地方。
movl %esp, %ebp
movl %esp, %ebp
将esp和ebp指向同一地方。
pushl 8(%ebp)
pushl 8(%ebp)
将8赋值给ebp所指向的地址空间。
call a
call a
将eip的值记为下一条指令的地址,esp指向下一个地址空间。这时转向a函数。
addl $4, %esp
addl $4, %esp
esp往上移一位4。
leave
leave
esp和指向同一位置ebp。
然后将esp所指向的内存空间的值付给eax。
esp往上移一位。
ret
main:
pushl %ebp
相当于两步:
subl $4 %esp
movl %ebp,(%esp)
esp先指向下一位,将ebp的地址值赋值给esp所指的地方。
movl
%esp, %ebp
将esp和ebp指向同一地方。
pushl
$7
esp向下移一位,然后将7赋值给esp所指的地方。
call b
call b
分为两步:
pushl %eip(*)
movl b的地址 %eip(*)
将eip的值记为下一条指令的地址,esp指向下一个地址空间。这时转向b函数。
addl $4, %esp(ubuntu多余代码,不予以分析)
addl $6, %eax
addl $4, %esp(ubuntu多余代码,不予以分析)
addl $6, %eax
eax的值加6。
leave
leave
esp和指向同一位置ebp。
然后将esp所指向的内存空间的值赋值给eax。
esp往上移一位。
第四章 总结
在生成代码的时候,我发现生成了很多多余代码。而现在我才发现,这些代码都是因为自己没有写对函数名造成的。由于我更改了老师的代码,却没有更改相应的函数名导致了错误。也算是给自己的教训。还有,我还发现了一段多余的代码:addl $4,%esp,不知道是什么原因。这个是为了什么设定的呢?希望大家来讨论一下。