Linux内核分析,c程序汇编代码分析--第一周

c程序汇编代码分析


做作业,顺便记录笔记

AT&T相关指令入门知识笔记,见外联  http://ouonline.net/att-asm-1

1.  汇编语言的五种寻址模式

movl %eax,%edx             edx=eax                        寄存器寻址 registermode(相当于c地址指针赋值)

movl  $0x123, %edx        edx=0x123                    立即寻址 immediate(相当于直接赋值地址值给c指针)

movl  0x123,%edx            edx=*(int*)0x123           直接寻址 direct(相当于获取地址指针的内容,* 操作)

movl (%ebx),%edx            edx=*(int*)ebx               间接寻址 indirect(相当于地址指针赋值后取值)

movl 4(%ebx),%edx            edx=*(int*)(ebx +4)      变址寻址 displaced(相当于地址指针增加后,赋值后取值)


2. 几个重要的汇编指令

Pushl %eax

Subl $4, %esp   //栈顶指针减4

Movl %eax, (%esp) //将eax中的值放入栈顶指针指向的内存位置

Popl %eax

Movl (%esp), %eax //从栈顶指针指向的内存中的值放入eax中

Addl $4, %esp //栈顶指针加4,栈在向上收缩

Call 0x12345
(eip 无法直接操作)

Pushl %eip //ip压栈

Movl $0x12345, %eip //将0x12345放入eip中

Ret Popl %eip //ip出栈
Enter Pushl %ebp   ebp入栈
Movl %esp, %ebp  使得ebp等于当前esp
leave Movl %ebp, %esp  使得esp等于当前ebp(相当于栈清空了)
Popl %ebp  ebp地址出栈


================================================================================================================

现做汇编分析实验

实现环境:

系统 win7 64位

编译器 mingwin

现有c程序 main.c :

int g(int x)
{
  return x + 3;
}
 
int f(int x)
{
  return g(x);
}
 
int main(void)
{
  return f(8) + 1;
}

对其进行  gcc –S –o main.s main.c -m32

去掉相关带.的行,分析main.s

_g:

	pushl	%ebp
	movl	%esp, %ebp
	movl	8(%ebp), %eax
	addl	$3, %eax
	popl	%ebp
	ret

_f:
	pushl	%ebp
	movl	%esp, %ebp
	subl	$4, %esp
	movl	8(%ebp), %eax
	movl	%eax, (%esp)
	call	_g
	leave
	ret

_main:
	pushl	%ebp
	movl	%esp, %ebp
	andl	$-16, %esp
	subl	$16, %esp
	call	___main
	movl	$8, (%esp)
	call	_f
	addl	$1, %eax
	leave
	ret

逐条分析

1.程序由_mian进入,首先 pushl %ebp

堆栈变化如下图,堆顶压入了ebp的值

Linux内核分析,c程序汇编代码分析--第一周_第1张图片

2. movl %esp,%ebp

改变ebp的值使得其指向esp
Linux内核分析,c程序汇编代码分析--第一周_第2张图片


3.andl $-16,%esp

esp 与 0xfffffff0 与运算,使得它对齐寻址空间,加快cpu处理速度

Linux内核分析,c程序汇编代码分析--第一周_第3张图片

4.subl $16,%esp

esp 向下移动4位

Linux内核分析,c程序汇编代码分析--第一周_第4张图片

4.call ___main

调用___main,由于在.def 里面被我删了,开始无法理解,然后google才知道,是编译器加入的,理解为加入调试信息,初始化变量等。真正的函数开始是这里开始的

.def___main;.scl2;.type32;.endef

至于.scl 2 和 .type 32 的意思,上网查一下就有的了。stackoverflow

5.因为call返回后,堆空间不变的,直接进入下一条

movl $8,(%esp)

Linux内核分析,c程序汇编代码分析--第一周_第5张图片

6.call _f  调用_f 函数,由于eip不可以直接修改,只能调用 call

call 是两条指令组成的,它先压入下一条指令的地址到栈顶,这里就是addl $1,%eax的地址,然后把f的地址赋予eip寄存器。函数调用开始。

Linux内核分析,c程序汇编代码分析--第一周_第6张图片

7.运行_f 函数的指令

pushl %ebp

movl  %esp,%ebp

后,变成下图,注意这里压入之前ebp地址A

Linux内核分析,c程序汇编代码分析--第一周_第7张图片

8

Linux内核分析,c程序汇编代码分析--第一周_第8张图片

9.运行movl 8(%ebp),%eax,从图可知就是把8的值移动加入到eax寄存器里面

Linux内核分析,c程序汇编代码分析--第一周_第9张图片

10.然后把eax的值传给exp所指的空间

Linux内核分析,c程序汇编代码分析--第一周_第10张图片

11.call _g

Linux内核分析,c程序汇编代码分析--第一周_第11张图片

12.之后和之前的一样,压入ebp地址,改变ebp,然后把8赋予eax

Linux内核分析,c程序汇编代码分析--第一周_第12张图片

13.往eax加3

Linux内核分析,c程序汇编代码分析--第一周_第13张图片

14.popl %ebp  把exp的值给ebp,相当于ebp值回地址B

Linux内核分析,c程序汇编代码分析--第一周_第14张图片

15.ret后,eip指向leave指令的地址,esp加四

Linux内核分析,c程序汇编代码分析--第一周_第15张图片

16.运行f函数的leave指令,有两个过程

先movl %ebp,%esp

Linux内核分析,c程序汇编代码分析--第一周_第16张图片

然后popl %ebp,相当于堆栈返回了

Linux内核分析,c程序汇编代码分析--第一周_第17张图片

17.ret指令,eip指向addl指令

Linux内核分析,c程序汇编代码分析--第一周_第18张图片

18.往eax加1

Linux内核分析,c程序汇编代码分析--第一周_第19张图片

19.leave,ebp恢复到进入程序之前的ebp地址

Linux内核分析,c程序汇编代码分析--第一周_第20张图片

20.ret 终于结束了,把esp上指的内容给会eip,函数返回。

Linux内核分析,c程序汇编代码分析--第一周_第21张图片



总结,计算机程序运行是依照冯诺依曼体系结构,从硬件上看其工作的方式,就是cpu依次读取寄存器中的指令来进行工作,不同的指令集合构成不同的计算机系统和程序。



你可能感兴趣的:(编程,汇编语言,linux内核)