码迷,mamicode.com
首页 > 其他好文 > 详细

信息安全系统设计基础第四周学习总结------20135334赵阳林

时间:2015-10-11 21:28:11      阅读:271      评论:0      收藏:0      [点我收藏+]

标签:

X86 寻址方式经历三代:

     1  DOS时代的平坦模式,不区分用户空间和内核空间,很不安全
     2  8086的分段模式
     3  IA32的带保护模式的平坦模式

对于机器级编程来说,其中两种抽象尤为重要

     1  机器级程序的格式和行为,定义为指令集体系结构(ISA),它定义了处理器状态,指令的格式,以及每条指令对状态的影响
     2  机器级程序使用的存储器地址是虚拟地址,提供的存储器模型看上去是一个非常大的字节数组

 

数据格式:由于是从16位体系结构扩展成32位,intel用术语字(word)表示16位数据类型,因此32位为双字(double words),64位数为4字(quad words)

 

对于ISA,要有以下基本观念:IA32的ISA和x86-64的ISA,以及其他大多数ISA,在抽象时都将指令按顺序执行抽象。但是处理器的硬件可以并发地执行许多指令,并且采用了一些safeguards来确保并行执行之后的结果和一条一条顺序执行的结果一样

一个IA32 CPU包含一组8个存储32位值的寄存器,用以存整数数据和指针:eax,ecx,edx,ebx,esi,edi,esp,ebp.大多数情况下前六个都用作通用寄存器,eax,ecx,edx的存储和恢复惯例不同于ebx,edi,esi(前三者为被调用者保存,后三者为调用者保存,详见3.7.3);最后两个用于存储指针,由于在过处理中非常重要,分别指向栈帧的顶部和底部,必须保持

 

关于ISA的指令:

一是,ISA中每条指令占用字节数不等,常用的指令所需的字节数少,不太常用的指令的字节数多,这样的话,相对于每条指令占用等长字节数的ISA,这种占用字节数不等的ISA为程序产生的总空间要更少。

 二是,ISA中的指令在设计时,达到了一个效果,对于一个二进制指令串,从某个字节开始,译码的结果是唯一的,这是达到了编码理论中“唯一可译性”的要求。

 (我觉得大概正是反汇编器正是利用了唯一可译性,从而将一串指令字节序列分割开来的)

 

 IA机器代码和原始的C代码差别很大

     1  程序计数器(PC)指令将要执行的下一条指令在存储器中的地址
     2  整数寄存器文件包含8个命名的位置,分别存储32位的值
     3  一些浮点寄存器存放浮点数据

gcc -S xxx.c -o xxx.s 获得汇编代码,也可以用objdump -d xxx 反汇编

注意:  64位机器上想要得到32代码:gcc -m32 -S xxx.c
       MAC OS中没有objdump, 有个基本等价的命令otool 
       Ubuntu中 gcc -S code.c (不带-O1) 产生的代码更接近教材中代码(删除"."开头的语句)

二进制文件可以用od 命令查看,也可以用gdb的x命令查看。 有些输出内容过多,我们可以使用 more或less命令结合管道查看,也可以使用输出重定向来查看

            od code.o | more
            od code.o > code.txt

当一个源文件生成了‘.o‘的目标二进制文件后,无法直接查看。

但是还是有个查看目标代码文件内容的方法,就是对‘.o‘目标文件使用反汇编器。它的输出还是二进制文件,但是,反汇编器将这些二进制按照指令进行了分段。让我们知道哪一段是一个指令(格式上与汇编器产生的汇编文件一样,分行的)

 

表中不同数据的汇编代码后缀

C声明 Intel数据类型 汇编代码后缀 字节
char 字节 b 1
short w 2
int 双字 l 4
long int 双字 l 4
long long int ----- - 4
char * 双字 l 4
float 单精度 s 4
double 双精度 l 8
long double 扩展精度 t 10/12

数据传送指令有三个变种:movb(传送字节)movw(传送字)movl(传送双字)

 

寄存器:

     esi edi可以用来操纵数组

     esp ebp用来操纵栈帧

     对于寄存器,特别是通用寄存器中的eax,ebx,ecx,edx,要理解32位的eax,16位的ax,8位的ah,al都是独立的,通过下面例子说明:

    假定当前是32位x86机器,eax寄存器的值为0x8226,执行完addw $0x8266, %ax指令后eax的值是多少? 
解析:0x8226+0x826=0x1044c, ax是16位寄存器,出现溢出,最高位的1会丢掉,剩下0x44c,不要以为eax是32位的不会发生溢出

 

操作数的三种类型:立即数、寄存器、存储器

     立即数:即常数值

     寄存器:表示某个寄存器内容

     存储器:根据计算出来的地址(通常称有效地址)访问某个存储器位置

     因此寻址方式也有多种,如:立即数寻址、寄存器寻址、绝对寻址、间接寻址、变址寻址、伸缩化  的变址寻址……

 

有效地址的计算方式 Imm(Eb,Ei,s) = Imm + R[Eb] + R[Ei]*s

 

区分MOV,MOVS,MOVZ三个命令

     MOV相当于C语言的赋值”=“

     MOVS将作了符号扩展的字节传送到字

     MOVZ将作了零扩展的字节传送到字

(不能从内存地址直接MOV到另一个内存地址,要用寄存器中转一下)

mov族(mov指令还有很多兄弟指令如movb、movw、movsb、movzb)、pop、push

movsb、movzb分别为符号扩展、零扩展,它们只拷贝一个字节,源操作数均为单字节,并设置目的操作数中其余的位,效果如下:

      初始假设:%dh=8D  %eax=98765432

      1   movb   %dh,%al       ;%eax=9876548D

      2   movsbl %dh,%eax    ;%eax=FFFFFF8D(目的操作数高24位设为源字节最高位,在这里为很显然为1,所以前24位为全F)

      3   movzbl %dh,%eax    ;%eax=0000008D(目的操作数高24位被设为0)

pushl指令等价于:

          subl $4,%esp

          movl %ebp,(%esp)  //注意这里的括号引起的差别

popl指令等价于:

           movl (%esp),%eax

           addl $4,%esp

1 遵循“后进先出”的原则
2 push压栈,pop出栈
3 栈顶:总是从这端插入和删除元素
4 栈顶元素的地址是最低的
5 栈指针%esp保存着栈顶元素的地址

指针

1 C语言中所谓的指针就是地址
2 间接引用指针是将该指针放在寄存器中然后在存储器引用中使用这个寄存器
3 局部变量通常保存在寄存器中。寄存器访问要比存储器快很多。

算术和逻辑操作

给出的每个指令类都有对字节、字、双字进行操作的指令,例如

addb
addw
addl

四组操作

加载有效地址:实际是将有效地址写入目的操作数,目的操作数必须是寄存器。

一元操作:只有一个操作数,可以是寄存器也可是存储器位置。

二元操作:源操作数是第一个,可以是立即数、寄存器、存储器
		 目的操作数是第二个,可以是寄存器、存储器
		 两个不能同时为存储器。

移位:第一个是移位量,用单个字节编码(只允许0-31位的移位),可以是立即数或者放在单字节寄存器%cl中
	 算术右移SAR,填上符号位;逻辑右移SHR,填上0。
	 目的操作数可以是一个寄存器或存储器。

 

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

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

条件码寄存器

描述了最近的算术或逻辑操作的属性,可以检测这些寄存器来执行条件分支指令
常用条件码:CF ZF SF OF
注意leal不改变任何条件码

访问条件码

1 根据条件码的某个组合,将一个字节设置为0或1。SET指令根据t=a-b的结果设置条件码
2 可以条件跳转到程序的某个其他部分
3 可以有条件的传送数据

跳转指令

会导致执行切换到程序中一个全新的位置,跳转的目的地通常用一个标号指明。

无条件跳转:JMP 可以是直接跳转也可以是间接跳转(写法是*后面加操作数指示符)
有条件跳转:根据条件码的某个组合,或者跳转或者继续执行下一条指令。

if-else汇编结构

通用形式会在两个分支语句中选择执行一个,汇编实现通过goto,就是汇编器为两个分支产生各自的代码块,它会插入条件和无条件分支,以保证能执行正确的代码块。

循环结构

do-while
while
for

汇编中用条件测试和跳转组合实现循环的效果。大多数汇编器根据do-while形式来产生循环代码,其他的循环会首先转换成do-while形式,然后再编译成机器代码。

switch

根据一个整数索引值进行多重分支。通过使用跳转表这种数据结构实现更加高效。跳转表是一个数组,表项i是一个代码段的地址,这个代码段实现当开关索引值为i时程序该做的。

这里的跳转可以用到goto/jmp

过程

过程调用包括将数据和控制从代码的一部分传递到另一部分,需要在进入时为过程的局部变量分配空间并在退出时释放空间,这通过程序栈实现。

IA32通过程序栈来实现过程调用。栈用来:

传递过程参数
存储返回信息
保存寄存器
本地存储

栈帧:为单个过程分配的那部分栈。

最顶端的栈帧以两个指针界定,寄存器%ebp为帧指针,寄存器%esp为栈指针。程序执行时,栈指针可以移动,大多数信息的访问都是相对于帧指针的。

栈向低地址方向增长。

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

ret指令从栈中弹出地址,并跳转到这个位置,使用这个指令栈指针要指向call指令存储返回地址的位置。

函数返回值存在%eax中

bt/frame/up/down :关于栈帧的gdb命令

四、特殊操作

1.乘法

(1)乘积截断
imull

双操作数,从两个32位操作数产生一个32位的乘积。

(2)乘积不截断
mull,无符号数乘法
imull,有符号数乘法

都要求一个参数必须在寄存器%eax中,另一个作为指令的源操作数给出。乘积的高32位在%edx中,低32位在%eax中。

2.除法

(1)有符号除法
idivl 操作数

将DX:AX中的64位数作为被除数,操作数中为除数,结果商在AX中,余数在DX中。

(2)无符号除法
divl指令

通常会事先设定寄存器%edx为0.

第六节 控制

一、条件码

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

条件码的改变:
数据传送指令
MOV 不影响标志位
PUSH POP 不影响标志位
XCHG 交换指令 不影响标志位
XLAT 换码指令 不影响标志位
LEA 有效地址送寄存器指令 不影响标志位
PUSHF 标志进栈指令 不影响标志位
POPF 标志出栈指令 标志位由装入值决定

算术指令
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 无条件转移指令 不影响条件码
所有条件转移指令  都不影响条件码

循环指令:
不影响条件码

子程序相关:
CALL调用和RET返回 都不影响条件码

 以上是我这周看书总结,参考了闫佳欣的总结。以后会努力学习,认真总结的。

信息安全系统设计基础第四周学习总结------20135334赵阳林

标签:

原文地址:http://www.cnblogs.com/EliteDci/p/4869931.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!