标签:
第三章 程序的机器级表示
一、知识点总结
(一)
1.计算机执行机器代码,用字节序列编码低级的操作,,包括处理数据、管理存储器、读写存储设备上的数据、利用网络通信。
2.GCC C语言编译器以汇编代码的形式产生输出,汇编代码是机器代码的文本表示。给出程序中每条指令,然后GCC调用汇编器和链接器,从而根据汇编代码生成可执行的机器代码
3.逆向过程——通过研究系统和逆向工作来了解系统的创建过程
(二)程序编码
1.gcc -01 -o p p1.c p2.c (-01告诉编译器使用第一级优化)
2.Gcc调用一系列程序将源代码转化为可执行代码。①C预处理器扩展源代码 ②编译器产生两个源代码的汇编代码p1.s、p2.s ③汇编器将汇编代码转为二进制目标代码p1.o、p2.o④链接器将两个目标代码文件与实现库函数的代码合并,并产生最终可执行代码文件p
3.机器级编程的两种抽象:①指令集体系结构②机器级程序使用的存储器地址是虚拟地址,存储器系统的实际实现是将多个硬件存储器和操作系统软件组合起来
4.gcc -01 -S code.c使用-S选项就能得到C语言编译器产生的汇编代码,产生一个code.s
5.gcc -01 -c code.c使用-c选项会产生目标代码文件code.o
6.反汇编器确定程序的字节表示,linux系统中-d可以充当这个角色objdump -d code.o
(三)数据格式
1.intel用“字”表示16位数据类型,32位数是“双字”
2.大多数GCC生成的汇编代码指令都有一个字符后缀,表明操作数的大小。数据传送指令:movb(传送字节)、movw(传送字)、movl(传送双字)。注意:汇编代码也用后缀l表示4字节整数和8字节双精度浮点数
(四)访问信息
1.一个CPU包含一组8个存储32位值的寄存器,用来存储整数数据和指针
2.操作数类型:立即数($后面跟一个用标准C表示法表示的整数)、寄存器(%ax……)、存储器
3.数据传送指令
①MOV相当于C语言的赋值“=”
②注意ATT格式中的方向
③注意不能从内存地址直接MOV到另一个内存地址,要用寄存器中转一下
④MOV:将源操作数的值复制到目的操作数中。pushl:将数据压入栈。popl:弹出数据
4.有效地址 Imm(Eb,Ei,s) = Imm + R[Eb] + R[Ei]*s;Imm是立即数偏移,Eb是基址寄存器,Ei是变址寄存器,s是比例因子(必须是1、2、4或8)
5.pushl功能是把数据压入栈上,popl是弹出数据,这些指令都只有一个操作数。注意栈顶元素的地址是所有栈中元素地址中最低的。
6.指针就是地址;局部变量保存在寄存器中
(五)算术和逻辑操作
1.加载有效地址(P141)
2.一元操作和二元操作(P142)
3.移位操作(P143)
4.特殊的算术操作(P145)
(六)控制
1.条件码(详见P147)
2.访问条件码:根据条件码的某个组合将一个字节设置为0或1、条件跳转到程序某个其他的部分、有条件地传送数据
3.跳转指令及其编码
有条件跳转(实现if,switch,while,for),无条件跳转jmp(实现goto)。有条件跳转的条件看条件码寄存器,注意leal不改变条件码寄存器。
4.循环:do while、while、for
5.条件传送指令
6.Switch语句:多重分支
(七)过程
一个过程调用包括将数据(以过程参数和返回值的形式)和控制从代码的一部分传递到另一部分。必须在进入时为过程的局部变量分配空间,并在退出时释放这些空间。
IA32通过栈来实现过程调用。
1.栈帧结构:栈支持过程调用,机器用栈来传递过程参数、存储返回信息、保存寄存器用于以后恢复和本地存储。为单个过程分配的部分成为栈帧。寄存器%ebp为帧指针,寄存器%esp为栈指针,栈指针可移动
2.转移控制
call/ret; 函数返回值存在%eax中
3.寄存器使用惯例
注意:一个调用者调用一个被调用者时,被调用者不会覆盖某个调用者稍后会使用的寄存器的值。
%eax,%edx,%ecx 调用者保存寄存器(Q可覆盖,P的数据不会被破坏)%ebx,%esi,%edi 被调用者保存寄存器(Q在覆盖这些值前必须压入栈并在返回前回复他们)%ebp,%esp 惯例保持%eax用来保存返回值
即要保存一个值以待以后运算可用的时候,有两种选择:
①由调用者保存。在调用之前就压进栈。
②由被调用者保存,在刚被调用的时候就压进栈,并在返回之前恢复。
4.过程示例(注意:GCC分配从不使用的空间)
5.递归过程
(八)数组分配和访问
1.对数据类型T和整型常数N的声明5:T A[N];
2.指针运算:单操作数的操作符&和*可以产生指针和间接引用指针。leal指令用来产生地址,movl用来引用存储器
3.嵌套的数组
4.定长数组(程序要用一个常数作为数组的维度或缓冲区大小时最好使用#define声明将这个常数与一个名字联系起来,后面使用该名字代替常数的数值)
5.变长数组(允许数组的维度是表达式)
(九)异质的数据结构
1.两种结合不同类型的对象来创建数据类型的机制:结构(structure)、联合(union)
2.结构:结构的各个字段的选取是在编译时处理的,机器代码不包含关于字段声明或字段名字的信息
3.联合:允许以多种类型来引用一个对象,是用不同的字段来引用相同的存储器块。一个联合的总的大小等于它最大字段的大小。联合还可以用来访问不同数据类型的位模式。
4.数据对齐:某种类型对象必须是某个K值(通常是2、4或8)的倍数。这种对齐限制简化了形成处理器和存储器系统之间接口的硬件设计
(十)综合:理解指针
1.每个指针都对应一个类型
2.每个指针都有一个值
3.指针用&运算符创建
4.运算符*用于指针的间接引用
5.数组与指针紧密联系
6.将指针从一种类型强制转换成另一种类型,只改变它的类型而不改变它的值
7.指针也可以指向函数
(十一)应用:使用GDB调试器
用gdb prog启动GDB
关于栈帧的gdb命令如下:
二、实验过程
实验环境中编写的源代码如下:
执行gcc -S -o main.s main.c -m32命令后编译成汇编代码
三、遇到的问题
对于实验中如何抽出汇编代码序列不甚了解,也不太清楚每条指令对应的相应栈帧情况,希望老师在课上能为我们讲解一下具体过程。
标签:
原文地址:http://www.cnblogs.com/20135228guoyao/p/4869876.html