从C程序分析计算机执行指令的过程
来源:互联网 发布:携程首席数据官 编辑:程序博客网 时间:2024/06/05 09:07
傅敬飞 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
本文章是参加网易云课堂MOOC课程的第一次作业
冯·诺依曼结构
也叫存储程序计算机工作模型。将指令存储在内存中,CPU从内存中取出指令执行。在X86 CPU有寄存器IP(Instruction Pointer), CS(Code Segment),这两个寄存器来确定CPU取值地址:
下一条要执行的命令的物理地址 = CS * 16 + IP
当CPU从内存取一条指令时,IP会自动增加该指令的长度个字节,使得CS:IP永远指向下一条要执行的指令。在汇编语言中CALL, RET, JMP,条件JMP可以改变CS与IP的值。
ABI
应用程序二进制接口(application binary interface)。包括以下:
- 数据类型的大小、布局和对齐;
- 调用约定(控制着函数的参数如何传送以及如何接受返回值),例如,是所有的参数都通过栈传递,还是部分参数通过寄存器传递;哪个寄存器用于哪个函数参数;通过栈传递的第一个函数参数是最先push到栈上还是最后;
- 系统调用的编码和一个应用如何向操作系统进行系统调用;
- 以及在一个完整的操作系统ABI中,目标文件的二进制格式、程序库等等
通用寄存器:
段寄存器:
- CS——代码段寄存器(Code Segment Register),其值为代码段的段值;
- DS——数据段寄存器(Data Segment Register),其值为数据段的段值;
- ES——附加段寄存器(Extra Segment Register),其值为附加数据段的段值;
- SS——堆栈段寄存器(Stack Segment Register),其值为堆栈段的段值;
- FS——附加段寄存器(Extra Segment Register),其值为附加数据段的段值;
- GS——附加段寄存器(Extra Segment Register),其值为附加数据段的段值。
部分基本汇编指令
movl %eax, %edx#将eax的值赋给edx,寄存器寻址movl $0x123, %edx#将值0x123赋给edx,立即数寻址movl 0x123, %edx#将内存地址为0x123中的值赋给edx,直接寻址movl (%ebx), %edx#将内存地址为ebx的值,该内存地址所存储的数据赋给edx。间接寻址movl 4(%ebx), %edx#将内存地址为ebx的值 + 4,该内存地址所存储的数据赋给edx。变址寻址
pushl %eax入栈指令,相当于执行
subl $4, $espmovl %eax, (%esp)
popl %eax
出栈指令,相当于:
movl (%esp), %eaxaddl $4, %esp
call 0x12345跳转指令,现将eip的值压栈,在更改eip的值。相当于
pushl (%eip) #该命令不存在movl $0x12345, %eip #该命令不存在
ret返回指令
popl %eip #该命令不存在
enter相当于:
pushl %ebpmovl %esp,%ebp
leave相当于
movl %ebp,%esppopl %ebp
b, w, l, q分别代表8位, 16位, 32位, 64位
linux下gcc采用的是AT&T的汇编格式,而windows下都是采用Intel汇编格式,他们之间的差别主要如下:
- 寄存器命名: AT&T中寄存器名字前带%,如%eax,而intel不带%,如eax
- 源,目的操作数顺序 : AT&T中源在前,目的在后,如 mov src,dst ; intel则相反
- 操作数长度 : AT&T中每个操作都有一个长度后缀,如movb (字节),movl(双字),movw(字),而intel则没有这种后缀
- 立即数格式: AT&T中立即数前有$,如$0x01;intel则没有$,如0x01
- 间接寻址的语法 : INTEL 中基地址使用“[” 、“]” ,而在 AT&T 中使用“(”、“)”
编译一个C程序,分析其汇编代码执行过程
实验环境为WMWare + Ubuntu2010
main.c内容如下:
int g(int x){ return x + 3;} int f(int x){ return g(x);} int main(void){ return f(9) + 1;}
使用命令
gcc –S –o main.s main.c -m32得到main.s内容精简如下:
g:pushl%ebpmovl%esp, %ebpmovl8(%ebp), %eaxaddl$3, %eaxpopl%ebpretf:pushl%ebpmovl%esp, %ebpsubl$4, %espmovl8(%ebp), %eaxmovl%eax, (%esp)callgleaveretmain:pushl%ebpmovl%esp, %ebpsubl$4, %espmovl$9, (%esp)callfaddl$1, %eaxleaveret程序从main函数的第一句开始执行,也就是第20行的代码开始。为了方便分析,将上面汇编代码命令的行号当做命令的段内地址赋给EIP,假定程序开始的ebp的值。命令的执行过程中内存的变化如下图,图中指令表示正在执行的指令,内存和部分寄存器的值表示命令完成后的状态。
实验部分截图如下:
总结:
现在计算机大多采用冯·诺依曼结构,程序员的工作就是提前编号程序存储起来。CPU有通过CS:IP确定要执行的命令的位置。ABI则规定CPU中寄存器的作用。程序的执行过程就是将程序加载到内存,设置好各个寄存器的初始值,然后一步步执行指令。
0 0
- 从C程序分析计算机执行指令的过程
- 通过分析一个C程序的汇编指令执行过程,理解计算机的工作。
- 计算机的指令执行过程分析
- 计算机程序的执行过程分析
- 计算机执行指令的过程
- 从汇编指令细看计算机程序的运行过程
- 从一个简单的C语言程序分析计算机程序工作过程
- 计算机程序的执行过程
- 计算机程序的执行过程
- 计算机底层执行一条指令的过程
- 计算机程序就是计算机执行指令的一个串行
- 计算机程序执行过程
- AngularJS 指令的执行过程分析
- C程序的执行过程
- c程序的执行过程
- 指令的执行过程
- 从程序的执行过程到多态
- 程序执行过程的内存分析
- Java中String 操作及前期绑定与后期绑定例子
- 算法训练 最短路
- 美观化文字
- 第5章2节《MonkeyRunner源码剖析》Monkey原理分析-启动运行: 启动流程概览(原创)
- hdu 5183 Negative and Positive (NP)
- 从C程序分析计算机执行指令的过程
- ACM-BestCoder Round #32
- java ServerSocket 用法详解(二)
- android 获取本地全部图片列表的实现及源码下载(二)
- linux学习笔记:本地如何上传文件到linux服务器
- 使用C++实现一套简单的状态机模型——原理解析
- dpdk的编译
- XMPP协议分析-原理篇
- JAVA正则表达式语法大全