信息安全系统设计基础第四周学习总结

  1. X86寻址方式经历三代:
    1 DOS时代的平坦模式,不区分用户空间和内核空间,很不安全
    2 8086的分段模式
    3 IA32的带保护模式的平坦模式

 

  1. ISA的定义

ISA即为指令集体系结构,它定义了处理器状态、指令的格式,以及每条指令对状态的影响。

PC寄存器:

即程序计数器。指示将要执行的下一条指令在存储器中的地址。

 

  1. P107代码为code.c:

Int accum = 0;

 

Int sum(int x,int y)

{

    Int t = x  + y ;

    Accum +=t;

    Return t;

}

命令行上使用“-S”选项,就能得到C语言编译器产生的汇编代码。在Linux系统中,带“-d”命令行标志的程序OBGDUMP可以充当反汇编器的角色。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) 产生的代码更接近教材中代码(删除"."开头的语句)


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


5.main.c中有这样的函数:

Int main()

{

Return sum(1,3);

}

用unix> gcc -01 –o prog code.o main.c生成可执行文件prog,再对它反汇编:

Unix>objdump –d prog ,反汇编的结果与code.c反汇编产生的代码几乎完全一样。不同在于左边地址不同,还有有accum的地址。

第六行反汇编最后四个字节反的,为0x804a018

以“.”开头的可以忽略。


6.p110: 了解Linux和Windows的汇编格式区别:ATT格式和Intel格式4个区别。


7.p111: 表中不同数据的汇编代码后缀

见P111表格

8.p112:一个CPU包含一组8个存储32位值的寄存器,这些寄存器用来存储整数数据和指针。esi edi可以用来操纵数组,esp ebp用来操纵栈帧。

%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位的不会发生溢出.

9.p113表

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

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

结果存放的两种可能:寄存器中、存储器中

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

10.p114:MOV类由三条指令组成,即movb,movw,movl. MOV相当于C语言的赋值“=”。

注意ATT格式中的方向, 另外注意不能从内存地址直接MOV到另一个内存地址,要用寄存器中转一下。MOV指令中第一个是源操作数,第二个是目的操作数。

MOVS和MOVS指令类都是将一个较小的源数据复制到一个较大的数据位置,高位用符号位扩展(MOVS)或零扩展(MOVZ)进行填充。

栈:栈是一个数据结构,可以添加或删除值,不过要遵循“先进后出”的原则。

通过push操作把数据压入栈中,通过pop操作删除数据。

 

11.栈帧与push pop。

注意栈顶元素的地址是所有栈中元素地址中最低的。

12.C语言一些指针的示例

Int x = *xp;

*xp = y;

指针就是地址,间接引用指针就是将该指针放在一个寄存器中,然后在存储器引用中使用这个寄存器。

像x这样的局部变量一般是保存在寄存器中。寄存器访问要比存储器访问块

1.加载有效地址

加载有效地址指令——leal

指令形式:从存储器读取数据到寄存器。

实际:将有效地址写入到目的操作数,而目的操作数必须是寄存器;并不真实引用存储器。

2.一元操作和二元操作

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

二元操作:源操作数 目的操作数(第一个操作数可以是立即数、寄存器或者存储器位置,第二个操作数可以是寄存器或者存储器位置,但是不能同时是存储器位置。)

3.移位操作

SAL 算术左移
SHL 逻辑左移
SAR 算术右移(补符号位)
SHR 逻辑右移(补0

源操作数:移位量——立即数或%cl中的数

目的操作数:要移位的数值——寄存器或存储器


14.条件码:

有条件跳转的条件看条件码寄存器

常用条件码:CF:进位标志,ZF零标志 ,SF:符号标志,OF:溢出标志。

Leal指令不改变任何条件码,因为它是用来进行地址计算的。


15. CMP和SUB用在什么地方?(不会)


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

SET类指令根据t=a-b的结果所设置的条件码来将一个字节(目的操作数)设置为0或者1

 

17.跳转与标号

无条件跳转:jmp.<标号>

有条件跳转:类似于SET类指令,是根据条形码或者其组合来跳转。

 

18. if-else 的汇编结构
do-while
while
for
switch

19. IA32通过栈来实现过程调用。位单个过程分配的那部分栈做栈帧,最低端%ebp为帧指针,最顶端%esp为栈指针。注意函数参数的压栈顺序.

 

20. call/ret; 函数返回值存在%eax中

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

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

 

21.使用GDB调试器

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

 

练习题:

3.14C语言代码:

Int test(data_t a){

Return a TEST 0;

}

用typedef声明data_t,从而设置参数的数据类型;用#define来声明TEST,从而设置比较的类型。

A.  test1  %eax,%eax

setne  %al

“l”可知是32位操作数。比较是“!=”,对有符号无符号都一样。可推断data_t一定是int、unsigned或某种类型的指针。

对前两种,它们的指示符也可以是long大小的,当data_t是unsigned时,比较也可以是>.

 学习感受:

举一反三并不容易,将汇编与反汇编熟练应用也很不容易。还要回头复习以前学过的内容。但是总结之后发现令人惊喜的收获,

知识互通掌握后很有成就感。

posted on 2015-10-11 16:56  hzy_dky  阅读(158)  评论(1编辑  收藏  举报