信息安全设计基础第五周学习总结

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

【学习时间:10小时】

【学习内容:第三章:程序的机器表示】

一、教材内容

1.X86 寻址方式的变化:

1 DOS时代的平坦模式,不区分用户空间和内核空间,很不安全;

2 8086的分段模式;

3 IA32的带保护模式的平坦模式

2.机器编程的两种抽象:

1)指令集体系结构(Instruction set architecture,ISA)——定义指令格式以及每条指令执行之后对状态的影响。大多数ISA将程序行为描述成按顺序执行的;

2)虚拟地址

3.一些处理器状态

1)PC,即程序计数器,用来指示将要执行的下一条指令在存储器中的地址;

2)整数寄存器,存储数据;条件码寄存器,保存逻辑指令状态信息;等

4.gcc -S xxx.c 可以得到C语言编译器产生的汇编代码,但不会做其他工作;使用“-c”命令,GCC就会编译并汇编该代码,得到二进制文件XXX.o。由此可见,机器执行的实际上是对一系列指令进行编码的字节序列。

5.函数中通用的汇编语句:

pushl %ebp //将该寄存器内容全部压入程序栈
movl %esp,%ebp
……
addl %eax,accum
popl %ebp

6.64位机器上想要得到32代码:gcc -m32 -S xxx.c

7.反汇编器:根据目标代码产生一种类似于汇编代码的格式。在linux中,objdump -d xxx.o 可以实现

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

od code.o | more

od code.o > code.txt

9.Linux和的汇编格式为ATT格式,而Windows的为Intel格式。二者在语法上有区别——后者省略了指示大小的后缀、寄存器前的%等。

10.intel用术语“字”来表示16位数据类型。int和long int都是4字节即双字长度;char是单字节;指针存储为4字节的双字。另外,在汇编代码中,b表示字节;w表示字,l表示双字

11.一个IA32中央处理单元(CPU)包含一组8个存储32位值的寄存器。其中,esi edi可以用来操纵数组,esp ebp用来操纵栈帧。另外四个寄存器为通用(在32位和16位机器上都可以用)寄存器。然而,当单独使用其低四位的时候,一旦结果多于8位,仍然会发生溢出。

12.理解操作数的三种类型:立即数(不超过32位的数值)、寄存器(用Ea表示任意寄存器a,R[Ea]表示它的值)、存储器(会根据计算出来的地址访问某个内存,用M[addr]表示)

13.寻址方式的通用公式:有效地址可以表示为Imm+R[Eb]+R[Ei]*s。Imm为立即数偏移;Eb为基址寄存器;Ei为变址寄存器;s为比例因子。如:

1)Ea——操作数值:R[Ea]

2)(Ea)——操作数值:M(R[Ea])

3)Imm(Ea)——操作数值:M(Imm+R[Ea])

14.mov语句表示将值从源操作数“移给”目的操作数(前者在前,后者在后),相当于赋值。在IA32中规定不能从内存地址直接MOV到另一个内存地址,要用寄存器进行中转。其中,MOVS是符号扩展;MOVZ是零扩展。

15.push,pop语句:及向程序栈中压入或者弹出数据。栈遵循“后进先出”的原则,且栈顶向下增长;在栈指针%esp中保存着栈顶元素的指针。

16.leal——加载有效地址;将数据从存储器读到寄存器

NEG——取负

SUB S,D——将D-S的结果送至D

移位操作 SAL,SHL,SAR,SHR的移位量可以是立即数或%cl中的数

17.除了leal外,其他逻辑操作都会设置条件码。另外,有些操作只设置条件码而不将结果送至操作数——CMP:比较指令,与SUB类似;TEST指令,与AND类似(当两数相等的时候,会将条件码都设置成0)

思考一下:CMP和SUB用在什么地方?

【一般来说,CMP应该是用在对操作数进行测试的时候,比如,可以测试某个数与已知数的大小关系等;而SUB执行的是减法操作,用于普通运算中】

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

19.跳转指令:

1)无条件跳转——jmp.<标号> 跳转到标号所指示的语句处;jmp *<操作数指示符> 【注意:如果形如%eax,即以%eax中的值作为跳转目标;而形如(%eax)则是以其中的值作为地址,读出跳转目标】 2)有条件跳转——类似于SET类指令,是根据条件码或者其组合来跳转

20.do-while语句等价的goto语句——

loop:
  body-statement
  t = test-sxpr;
  if(t)
      goto loop;

21.while语句等价的goto语句——

t = test-sxpr;
if(!t)
    goto done;
loop:
  body-statement
  t = test-sxpr;
  if(t)
      goto loop;
done:

22.for循环的流程:程序首先对初试表达式init-expr求值,然后进入循环;在循环中它先对测试条件test-expr求值,如果为假则退出循环否则执行循环体;最后对更新表达式求值。

23.switch语句根据一个整数索引值进行多重分支;通过使用跳转表使其更加高效。跳转表是一个数组,表项i是一个代码段地址(C语言用&表示一个指向数据值的指针;而&&表示一个指向代码位置的指针)

24.IA32利用程序栈来支持过程调用(包括将数据和控制)。为单个过程分配的那部分栈做栈帧。最底端(地址最大)%ebp为帧指针;最顶端(地址最小)%esp为栈指针。当程序执行时,栈指针可以移动。

25.转移控制——

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

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

【二者配合,实现函数调用时的衔接:即,call类似于先行的探险者,将迷宫入口处的地址存到某个安全的地方,然后探索迷宫(函数);ret类似于保障人员,在探险完成之后将该地址取出来,带领程序回到最初的入口处,接着走大路(主程序)】

26.编译器根据一组很简单的惯例产生管理栈结构的代码。参数在栈上传递给函数,可以从栈中相对于%ebp的正偏移量来访问它们。可以用push指令或者是从栈指针中减去偏移量来分配在栈上的空间。

二、练习题筛选

1.下列代码的错误之处?

movb $0xf,(%bl) ---目的操作数只能是一个寄存器或者一个存储器地址。(%bl)表示一个值

movw (%eax),4(%esp)---目的操作数与源操作数不能都是存储器

movb %si, 8(%ebp)---指令后缀与寄存器地址不匹配

2.xp,yp,zp分别存储在相对于寄存器%edp中地址值偏移8、12、16的地方。试写出与以下代码等价的C语言代码

movl 8(%ebp),%edi
movl 12(%ebp),%edx
movl 16(%ebp),%ecx
movl (%edx),%ebx
movl (%ecx),%esi
movl (%edi),%eax
movl %eax,(%edx)
movl %ebx,(%ecx)
movl %esi,(%edi)

代码如下:

void decode1(int *xp,int *yp,int *zp)
{
    int x=*xp;
    int y =*yp;
    int z = *zp;
    *yp = x;
    *zp = y;
    *xp = z;
}

3.根据汇编代码,补充C语言代码(x,y,z分别存储在相对于寄存器%edp中地址值偏移8、12、16的地方)

movl 12(%ebp),%eax
xorl 8(%ebp),%eax
sarl $3,%eax
notl %eax
subl 16(%ebp),%eax

C语言代码:

int arith(int x,int y,int z)
{
    int t1 = x^y;
    int t2 = 3*t1;
    int t3 = ~t2;
    int t4 = t3-z;
    return t4;
}

4.考虑以下C语言代码:

int test(data_t a)
{
    return a TEST 0;
}

根据以下每条指令序列,确定哪种数据类型和比较TEST会使编译器产生这样的代码?

A. testl %eax,%eax setne %al

[既然是l,表明是32位,且data_t可以是int,unsigned和指针;而ne表示比较类型是 !=,对有无符号的数字都成立;对于unsigned,比较还可以是>]

B. testb %al,%al setg %al

[既然是b,表明是16位,且比较是 == ;则data_t应该是short或者unsigned short]

5.在下面这些反汇编二进制代码节选中,有些代码被x代替了。请补充。

A.

804828f:74 05   je   XXXXXXX
8048291:E8 10 00 00 00   CALL 80482B4

XXXXXXXX:0x8048291+0x05 = 0x8048296[利用P129所讲,程序计数器的值是跳转指令之后的那条指令的地址;而更新计数器又是执行一条指令的第一步,所以要加上原来的地址] B.

8048357:72 e7   jB   XXXXXXX
8048359:c6 05 10 a0 04 08 01   movb   $0x1,0x804a010

XXXXXXX:0xe7(补码)+0x8048359 = 0x8048359-25 = 8048340

6.已知下列C语言代码:

void cond(int a,int *p)
{
    if(p&&a>0)
        *p +=a;
}

按照与汇编代码等价的C语言goto版本,写一个与之等价的C语言代码。 答:

void goto_cond(int a,int *p)
{
    if(p == 0)
        goto done;
    if(a<=0)
        goto done;
    *p +=a;
    done:
        return;
}

为什么C语言只有一个条件语句;而汇编中有两个分支呢? 【第一个条件分支是&&表达式实现的一部分;如果对p非空的测试失败,代码会跳过对a的测试】

7.根据汇编代码,补充对应的C语言代码空缺部分

movl 8(%edp),%edx   //x at %edp+8
movl $0,%eax
testl %edx,%edx
je .L7
.L10:
xorl %edx,%eax
shrl %edx          //shift right by 1
jne .L10
.L7:
andl $1,%eax

则对应的C语言代码是:

int fun_a(unsigned x)
{
    int val = 0;
    while(x!=0)
    {
        val = val ^ x;
        x>> = 1;
    }
    return val & 0x1;
}

这段代码的功能? 【如果x有奇数个1,就返回1;如果有偶数个1,就返回0】

8.函数fun_b经GCC编译之后产生如下汇编代码:

movl 8(%ebp),%ebx      //x at %ebp+8
movl $0,%eax
movl $0,%ecx
.L13:
leal (%eax,%eax),%edx
movl %ebx,%eax
andl $1,%eax
orl %edx,%eax
shrl %edx
addl $1,%ecx
cmpl $32,%ecx
jne .L13

补充以下C语言源代码

int fun_b(unsigned x)
{
    int val = 0;
    int i;
    for(i =0;i<32;i++)
    {
        val = (val<<1) | (x & 0x1);
        x>> =1;
    }
return val;
}

作用? 【把x的位(十六进制)翻转过来填入val】

9.根据P148图3-20的汇编代码,填写补充C源代码

int switcher(int a,int b,int c)
{
    int answer;
    switch(a)
    {
        case 5 :
            c = b ^ 15;
        case 0 :
            answer = c+112;
        case 2 :
        case 7 :
            answer = c+6;
            break;
        case 4 :
            answer = a;
            break;
        default :
            answer = b;
    }
    return answer;
}

10.

call next
next:
popl %eax

A.寄存器%eax被设置成了什么值? 【popl】 B.解释为什么这个调用没有与之匹配的ret指令 【这不是一个真正的过程调用,因为根本是按照与指令相同的顺序进行的】 C.这段代码完成了什么功能? 【这是IA32中将程序计数器中的值放到整数计数器中的唯一办法】

三、疑问

1.既然leal是mov的变形,那么所有可以用leal的场合都可以用mov吗?

2.(已经在后续学习中解决,可以下方3.做参考,跳转到目标值之后可能接着执行某段代码)P127中,

jmp *<操作数指示符【注意:如果形如%eax,即以%eax中的值作为跳转目标;而形如(%eax)则是以其中的值作为地址,读出跳转目标】 那么,如果程序中有这种语句,跳到目标值之后会怎么样呢?

3.P146中,图3-19的代码块第6行有:

jmp *.L7(,%eax,4)

然而,该段代码中并没有标识.L7的位置。那么jmp指令如何寻址?

4.P148练习题3.29

根据图3-20的汇编代码,填写补充C源代码.答案如下:

int switcher(int a,int b,int c)
{
    int answer;
    switch(a)
    {
        case 5 :
            c = b ^ 15;
        case 0 :
            answer = c+112;
        case 2 :
        case 7 :
            answer = c+6;
            break;
        case 4 :
            answer = a;
            break;
        default :
            answer = b;
    }
    return answer;
}

其中,关于

case 4 :
    answer = a;
    break;

答案中解释为:

GCC对程序进行了优化,将answer = 4优化为answer = a。

为什么?

5.

call next
next:
popl %eax

C.这段代码完成了什么功能? 【这是IA32中将程序计数器中的值放到整数计数器中的唯一办法】

这句解释是什么意思呢?

四、学习心得

在这周的自学中,主要是学习了机器内执行程序的时候所发生的动态变化。要究动态,就必须了解静态的内部“参量”;有前面打下的基础,才有后面学得懂、学得透的可能性。在大的方面上,更是因为有上学期汇编语言的基础,才能保证流畅阅读基础的汇编代码,而不用时时刻刻“查字典”。在学习上,也有类似于文学作品中那样所谓的“伏笔”——自己奠定了什么样的基础,决定了有什么样的起承转合。

时间: 10-09

信息安全设计基础第五周学习总结的相关文章

信息安全设计基础第十周学习总结

信息安全设计基础第十周学习总结 [学习时间:8小时]  [学习内容:教材第十章 之 I/O总结:实验楼私有课程<深入理解计算机系统> 之 系统级I/O] 一.教材内容 1.I/O重定向 [重定向其实是unix系统优越性的一种体现(与管道相似):将一种操作的结果重定向到另外一种操作上,这样的思想保证了“专务专用”,将单个操作做到极致,又为用户自己提供了完善功能的平台(比如重定向,比如管道).] - unix外壳提供了I/O重定向操作符,允许用户将磁盘文件和标准输入输出连接起来.例如: ls &g

信息安全程序设计基础第五周学习总结

第四章 处理器体系结构 4.1 Y86指令集体系结构 一.程序员可见的状态 程序员可见状态:程序中的每条指令都会读取或修改处理器状态的某些部分 --8个程序寄存器:%eax,%ecx,%edx,%ebx,%esi,%edi,%esp,%ebp.他们都可以存储一个字; %esp被入栈.出栈.调用和返回指令作为栈指针; 其他情况时寄存器没有固定的含义或固定值 --3个一位条件码:ZF.OF.SF.保存最近的算术或逻辑指令所造成影响的有关信息 --PC(程序计数器):存放当前正在执行指令的地址. --

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

第三章 程序的机器级表示 一.历史观点 Intel处理器(X86) 二.程序编码 gcc -01 -o p p1.c p2.c ①编译选项-01 表示编译器使用第一级优化 ②编译选项-02 表示编译器使用第二级优化(较好的选择) ③-o 表示分别将p1.c和p2.c编译后的可执行文件命名为p GCC将源代码转化为可执行代码的步骤: C预处理器:扩展源代码,插入所有#include命令指定的文件,并扩展生成.i文件 编译器:产生两个源代码的汇编代码,生成.s文件 汇编器:将汇编代码转化成二进制目标

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

第四章 处理器体系结构 第一节 Y86指令集体系结构 一.程序员可见的状态 1.含义: 每条指令都会读取或修改处理器状态的某些部分 2.“程序员”: 可以是用汇编代码写程序的人,也可以是产生机器级代码的编译器. 3.具体的处理器状态:类似于IA32 有8个程序寄存器,%eax,%ecx,%edx,%ebx,%esi,%edi,%esp,%ebp 处理器的每个程序寄存器存储一个字 寄存器%esp被入栈.出栈.调用和返回指令作为栈指针.在其他情况下,寄存器没有固定的含义或固定值. 有三个一位的条件码

20135304刘世鹏——信息安全系统设计基础第五周学习总结

第四章 处理器体系结构 ISA:一个处理器支持的指令和指令的字节级编码——指令集体系结构 ISA在编译器编写者和处理器设计人员之间提供了一个概念抽象层 与IA32相比Y86指令集的数据类型.指令和寻址方式都要少一些,它的字节级编码比较简单,不过它仍然足够完整 4.1.Y86指令集结构 定义一个指令集体系结构,暴扣定义各种状态元素.指令集和它们的编码.一组编程规范和异常事件处理 1.程序员可见的状态 程序员可见状态:Y86程序中的每条指令都会读取或修改处理器状态的某些部分 Y86的处理器状态类似与

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

第3章 程序的机器级表示 一.X86 寻址方式 1 DOS时代的平坦模式,不区分用户空间和内核空间,很不安全 2 8086的分段模式 3 IA32的带保护模式的平坦模式 二.程序编码 编译如下代码: unix> gcc -01 -o p p1.c p2.c 01 表示告诉编译器使用第一级优化.通常,提高优化级别会使最终程序运行的更快,但编译时间可能会变长,用调试工具对代码进行调试会更困难. 从得到的程序性能方面考虑,第二级优化-02被认为是是较好的选择. 二.机器级代码 1.两种抽象 (1)IS

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

处理器的体系结构 ISA:一个处理器支持的指令和指令的字节级编码称为它的指令集体系结构ISA. Y86是一个指令体系结构(ISA)寄存器.存储器.条件码.PC.程序状态. halt:这个指令将会终止指令的执行. nop:这是一个占位指令,它不做任何事情,后续为了实现流水线,它有一定的作用. xxmovl:这是一系列的数据传送指令,其中r代表寄存器,m代表存储器,i代表立即数.比如rrmovl指令,则代表将一个寄存器的值,赋给另外一个寄存器. opl:操作指令,比如加法,减法等等. jxx:条件跳

20145307《信息安全系统设计基础》第五周学习总结PT2

20145307<信息安全系统设计基础>第五周学习总结PT2: 教材学习内容总结 之前有第一部分学习总结: http://www.cnblogs.com/Jclemo/p/5962219.html 以下为第二部分 执行汇编命令:gcc –s xxx.c –o xxx.s反汇编命令:objdump –d xxx 64位处理器得到32代码的命令:gcc –m32 –s xxx.c Ltme: 1.三种操作数: 立即数:常数值.表示为$c标准表示的整数. 寄存器:表示某个寄存器的内容. 存储器:根据

20145317《信息安全系统设计基础》第五周学习总结2

20145317<信息安全系统设计基础>第五周学习总结2 教材学习内容总结 X86 寻址方式经历三代: DOS时代的平坦模式,不区分用户空间和内核空间,很不安全. 8060的分段模式 IA32的带保护模式的平坦模式 程序编程 1.代码含义 gcc -01 -o p p1.c -01 表示使用第一级优化.优化的级别与编译时间和最终产生代码的形式都有关系,一般认为第二级优化-02 是较好的选择. -o 表示将p1.c编译后的可执行文件命名为p 2.机器级编程的两种抽象 指令集结构ISA 是机器级程