您的位置:首页 > 其它

20135223何伟钦—信息安全系统设计基础第五周学习总结

2015-10-11 22:38 323 查看

第三章程序的机器级表示

一、历史观点

Intel处理器(X86)

二、程序编码

gcc-01-opp1.cp2.c
[/code]
①编译选项-01表示编译器使用第一级优化

②编译选项-02表示编译器使用第二级优化(较好的选择)

③-o表示分别将p1.c和p2.c编译后的可执行文件命名为p

GCC将源代码转化为可执行代码的步骤:

C预处理器:扩展源代码,插入所有#include命令指定的文件,并扩展生成.i文件
编译器:产生两个源代码的汇编代码,生成.s文件
汇编器:将汇编代码转化成二进制目标代码——生成.o文件
链接器:产生可执行代码文件p

回顾:gcc命令编译运行C语言


预处理阶段:将*.c文件转化为*.i预处理过的C程序。

编译阶段:将*.i文件编译为汇编代码*.s文件。

汇编阶段:将*.s文件转化为*.o的二进制目标代码文件。

链接阶段:将*.o文件转化为可执行文件。

生成可执行文件:将*.o转换为可执行文件。

执行可执行C语言文件。

(1)机器级代码

两种抽象

(1)指令集体系结构ISA

(2)机器级程序使用的存储器地址是虚拟地址(多个硬件存储器和操作系统软件组合起来)


处理器状态:


程序计数器(CS:IP)

整数寄存器(AX,BX,CX,DX)

条件码寄存器(OF,SF,ZF,AF,PF,CF)

浮点寄存器

(2)代码示例
C语言代码文件code.c:

intaccum=0;
intsum(intx,inty)
{
  intt=x+y;
  accum+=t;
  returnt;
}

产生汇编代码code.s:

gcc-01-Scode.c
编译并汇编该代码,产生目标代码code.o:gcc-01-ccode.c

反汇编器——查看目标代码文件
abjdump-dcode.o
[b]三、数据格式[/b]

数据类型:
字:16位
双字:32位
四位:64位

基本数据类型:

C声明Intel汇编代码后缀大小(字节)
char字节b1
shortw2
int双字l4
longint双字l4
longlongint4
char*双字l4
float单精度s4
double双精度l8
longdouble扩展精度t10/12


数据传送指令


movb传送字节

movw传送字

movl传送双字


四、访问信息

(一)操作数指示符


操作数:指示出执行一个操作中要引用的源数据值,以及放置结果的目标位置。


操作数类型:

立即数(常数值)例:$0x1F

寄存器例:%ax

存储器有效地址

寻址方式:

(1)立即数寻址方式

(2)寄存器寻址方式

(3)存储器寻址方式

(4)直接寻址方式

(5)寄存器间接寻址方式

(6)寄存器相对寻址方式

(7)基址变址寻址方式

(8)相对基址变址寻址方式

(二)数据传送指令


1.mov指令:把源操作数的值复制到目的操作数上

movb、movw、movl



2.堆栈

遵循“后进先出”的原则

栈指针指向栈顶元素

栈顶元素的地址在栈中元素地址是最低的


压栈push:将数据压入栈中

出栈pop:弹出数据



3.数据传送示例

c语言中的指针其实就是地址,间接引用指针就是将该指针放在一个寄存器中,然后在存储器引用中使用这个寄存器

局部变量通常保存在寄存器


(五)算术和逻辑操作

字节加法:addb
字加法;addw
双字加法:addl

1、加载有效地址


加载有效地址指令——leal,是movl指令的变形,对比汇编中的LEA指令学习。


将有效地址写入到目的操作数,目的操作数必须是寄存器






2、一元操作和二元操作


1.一元操作


只有一个操作数,既是源又是目的,可以是一个寄存器,或者存储器位置。

例:加法运算符(++)和减1运算符


2.二元操作

第二个数既是源又是目的

第一个操作数可以是立即数、寄存器或者存储器位置


第二个操作数可以是寄存器或者存储器位置


两个操作数但是不能同时是存储器位置。



三、移位操作


右边填0:SAL算术左移
SHL逻辑左移

填上符号位:
SAR算术右移
填上0:SHR逻辑右移


移位操作源操作数可以是立即数或CL

移位操作目的操作数可以是寄存器或存储器


4、特殊的算术操作





(六)控制


一、条件码

CF:进位标志
ZF:零标志
SF:符号标志
OF:溢出标志





注意:

leal不改变条件码寄存器

CMP与SUB的区别:CMP也是根据两个操作数之差设置条件码,但只设置条件码而不更新目标寄存器

有条件跳转的条件看状态寄存器(教材上叫条件码寄存器)

常用指令:
MOV不影响标志位
PUSHPOP不影响标志位
XCHG交换指令不影响标志位
XLAT换码指令不影响标志位
LEA有效地址送寄存器指令不影响标志位
PUSHF标志进栈指令不影响标志位
POPF标志出栈指令标志位由装入值决定

2、访问条件码


根据条件码的某个组合,将一个字节设置成0或1;

跳转到程序某个其他的部分

有条件的传送数据。

SET指令根据t=a-b的结果设置条件码


SET指令:





3、跳转指令及其编码


JUMP指令会导致执行切换到程序一个全新的位置,通常用一个标号指明

jmp指令是无条件跳转,可分为直接跳转和间接跳转:

直接跳转:后面跟标号作为跳转目标


间接跳转:*后面跟一个操作数指示


区别:

jmp*%eax用寄存器%eax中的值作为跳转目标

jmp*(%eax)以%eax中的值作为读地址,从储存器中读取跳转目标



控制中最核心的是跳转语句:

有条件跳转(实现if,switch,while,for)

无条件跳转jmp(实现goto)

当执行PC相关的寻址时,程序计数器的值是跳转指令后面那条指令的地址,而不是跳转指令本身的地址。

4、翻译条件分支

将条件表达式和语句从c语言翻译成机器语言,最常用的方式就是结合有条件和无条件跳转

无条件跳转:例如goto。书上的例子就是把if-else语句翻译成了goto形式,然后再由这个形式翻译成汇编语言



C语言中if-else语句的通用形式:

if(test-expr)
then-statement
else
else-statement

汇编结构:

	t=test-expr;
if!(t)
gotofalse;
then-statement
gotodone;
false:
else-statement
done:

5、循环


汇编中可以用条件测试和跳转组合起来实现循环的效果,但是大多数汇编器中都要先将其他形式的循环转换成do-while格式。


1.do-while循环


通用形式:


do
body-statement
while(test-expr);


循环体body-statement至少执行一次。


可以翻译成如下所示的条件和goto语句:


loop:
body-statement
t=test-expr;
if(t)
gotoloop;


即先执行循环体语句,再执行测试表达式。


2.while循环

C语言中while语句的通用形式:

while(test-expr)
body-statement

汇编结构:

	t=test-expr;
if(!t)
gotodone;
loop:
body-statement
t=test-expr;
if(t)
gotoloop;
done:

for循环

C语言中for语句的通用形式:

for(init-expr;test-expr;update-expr)
body-statement

汇编结构:

	init-expr
t=test-expr;
if(!t)
gotodone;
loop:
body-statement
update-expr;
t=test-expr;
if(t)
gotoloop;
done:

3.for循环


for循环

C语言中for语句的通用形式:

for(init-expr;test-expr;update-expr)
body-statement

汇编结构:

	init-expr
t=test-expr;
if(!t)
gotodone;
loop:
body-statement
update-expr;
t=test-expr;
if(t)
gotoloop;
done:


6、条件传送指令(详细看书本)


7、Switch语句


Switch语句是多重分支的典型(这个已经掌握的比较好,详细见书本)





(七)过程

栈帧结构


为单个过程分配的栈叫做栈帧,寄存器%ebp为帧指针,而寄存器指针%esp为栈指针,程序执行时栈指针移动,大多数信息的访问都是相对于帧指针。

栈向低地址方向增长,而栈指针%esp指向栈顶元素。

转移控制

call:目标是指明被调用过程起始的指令地址,效果是将返回地址入栈,并跳转到被调用过程的起始处。

ret:从栈中弹出地址,并跳转到这个位置。

函数返回值存在%eax中

1.call

call指令和转移指令相似,同样分直接和间接,直接调用的目标是标号,间接调用的目标是*后面跟一个操作数指示符,和JMP一样。

CALL指令的效果是将返回地址入栈,并跳转到被调用过程的起始处。返回地址是还在程序中紧跟在call后面的那条指令的地址。

然后就会用到ret了。

2.ret

ret指从栈中弹出地址,并跳转到这个位置。


在上学期的汇编语言学习中,call和ret常被用来进行子函数、子模块的调用。


3.leave

这个指令可以使栈做好返回的准备,等价于:

movl%ebp,%esp
popl%ebp

查看函数调用栈信息的GDB命令

Ÿbacktrace/btn

n是一个正整数,表示只打印栈顶上n层的栈信息。

-n表一个负整数,表示只打印栈底下n层的栈信息。

Ÿframen

n是一个从0开始的整数,是栈中的层编号。这个指令的意思是移动到n指定的栈帧中去,并打印选中的栈的信息。如果没有n,则打印当前帧的信息。

Ÿupn

表示向栈的上面移动n层,可以不打n,表示向上移动一层。

Ÿdownn

表示向栈的下面移动n层,可以不打n,表示向下移动一层。


寄存器使用惯例


寄存器%eax、%edx和%ecx被划分为调用者保存寄存器。


寄存器%ebx、%esi、%edi被划分为被调用者保存寄存器。


过程示例


GCC坚持一个函数使用的所有栈空间必须是16字节的整数倍,包括保存%ebp值的4个字节和返回值的4个字节。


递归过程


递归调用自身和调用其它函数是一样的。栈规则提供了一种机制,每次函数调用都有它自己私有的状态信息存储(保存的返回位置,栈指针和被调用者保存寄存器的值)

补充汇编语言命令:

算术指令
ADD加法指令影响标志位
ADC带进位加法指令影响标志位
INC加一指令不影响CF,影响别的标志位
SUB减法指令影响标志位
SBB带借位减法指令影响标志位
DEC减一指令不影响CF,影响其他标志位
NEG求补指令影响标志位只有操作数为0,例如字运算对-128求补,OF=1,其他时候OF=0
CMP比较指令做减法运算但不存储结果,根据结果设置条件标志位
MUL无符号数乘法指令
IMUL有符号数乘法指令均对CF和OF位以外的条件码位无定义(即状态不定)
DIV无符号数除法指令
IDIV带符号数除法指令除法指令对所有条件码位均无定义
位操作指令
AND逻辑与
OR逻辑或
NOT逻辑非不影响标志位
XOR异或
TEST测试指令除NOT外的四种,置CF、OF为0,AF无定义,SF,ZF,PF根据运算结果设置
移位指令
SHL逻辑左移指令
SHR逻辑右移指令移位指令根据结果设置SF,ZF,PF位
ROL循环左移指令
ROR循环右移指令循环移位指令不影响除CF,OF之外的其他条件位
串处理指令:
MOVS串传送指令
STOS存入串指令
LODS从串取指令均不影响条件位
CMPS串比较指令
SCAS串扫描指令均不保存结果,只根据结果设置条件码
控制转移指令:
JMP无条件转移指令不影响条件码



参考资料:20135202闫佳欣的《第三章程序的机器级表示》总结


                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
章节导航