20145225 《信息安全系统设计基础》第5周学习总结

第三章 程序的机器级表示

第二节 程序编码

一、机器级代码

1.机器级编程的两种抽象

(1)指令集结构ISA
(2)机器级程序使用的存储器地址是虚拟地址

2.汇编代码的特点:

用可读性更好的文本格式来表示。

3.几个处理器:

  • 程序计数器(CS:IP)
  • 整数寄存器(AX,BX,CX,DX)
  • 条件码寄存器(OF,SF,ZF,AF,PF,CF)
  • 浮点寄存器

一条机器指令只执行一个非常基本的操作。

二、代码示例

书第107页的代码如下:

int accum = 0;

int sum(int x, int y)
{
    int t = x + y;
    accum += t;
    return t;
}

这里需要注意的是反汇编器的使用:

objdump -d xxx.xx

即可反汇编-d后的文件,查看目标代码文件的内容。

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

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

机器代码和它的反汇编表示的一些特性:

  • IA32指令长度从1到15个字节不等
  • 设计指令格式的方式是,从某个给定位置开始,可以将字节唯一的解码成机器指令
  • 反汇编器只是基于机器代码文件中的字节序列来确定汇编代码,不需要访问程序的源代码或汇编代码
  • 反汇编器使用的指令命名规则与GCC生成的汇编代码使用的有些差别

ATT和INTEL的汇编代码格式有所差别。

第四节 访问信息

Linux——平坦寻址方式:

ds,ss,cs等各段的段基地址都指向同一个地方,不管是数据段还是代码段,只要他们的偏移相等,那么他们就是寻址一样的物理内存,所以我们就只需指明偏移就能得到统一的寻址目标,不管这个目标是在代码段还是数据段或者堆栈段之中。

一、操作数指示符

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

1.操作数的三种类型

  1. 立即数
  2. 寄存器
  3. 存储器

2.结果存放的两种可能

  1. 寄存器中
  2. 存储器中

    3.寻址方式

    (1)立即数寻址方式

    格式:$后加用标准c表示法表示的整数,如$0xAFF

    (2)寄存器寻址方式

    如%eax,与汇编中学过的AX寄存器类比。

    (3)存储器寻址方式
  • 直接寻址方式
  • 寄存器间接寻址方式
  • 寄存器相对寻址方式
  • 基址变址寻址方式
  • 相对基址变址寻址方式

二、数据传送指令

1.mov指令

2.push&pop

(1)堆栈

需要注意两点:

1.后进先出

2.栈指针指向栈顶元素

3.栈朝低地址方向增长

(2)压栈push

指令格式——PUSH r16/m16/seg

指令功能

第一步:SP←SP-2  ;堆栈指针SP上移
第二步:(SS):(SP)←r16/m16/seg  ;字操作数存入堆栈顶部

注意 堆栈操作必须至少以为单位,这时栈顶指针-2

如果压入的是双字,栈顶指针-4

(3)出栈pop

指令格式——POP r16/m16/seg
指令功能

第一步:r16/m16/seg← (SS):(SP) ;栈顶的一个字传送到指定的目的操作数
第二步:SP←SP+2   ;堆栈指针SP下移,指向新的栈顶

栈顶指针变化同压栈。

三、数据传送示例

1.c操作符*执行指针的间接引用。

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

3.局部变量通常保存在寄存器中,而不是存储器

第五节 算术和逻辑操作

一、加载有效地址

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

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

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

二、一元操作和二元操作

1.一元操作

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

2.二元操作

源操作数 目的操作数

第一个操作数可以是立即数、寄存器或者存储器位置
第二个操作数可以是寄存器或者存储器位置
但是不能同时是存储器位置。

三、移位操作


源操作数:移位量——立即数或CL

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

四、特殊操作

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返回 都不影响条件码

二、访问条件码

都适用的情况:执行比较指令,根据计算t=a-b设置条件码。

三、跳转指令及其编码

P128页。

jump分为直接跳转和间接跳转:

直接跳转:后面跟标号作为跳转目标
间接跳转:*后面跟一个操作数指示符

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

四、翻译条件分支

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

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

五、循环

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

1.do-while循环

通用形式:

do
    body-statement
    while(test-expr);

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

可以翻译成:

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

即先执行循环体语句,再执行判断。

2.while循环

通用形式:

while (test-expr)
    body-statement

GCC的方法是,使用条件分支,表示省略循环体的第一次执行:

if(!test-expr)
    goto done;
do
        body-statement
        while(test-expr);
done:

接下来:

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

归根究底,还是要把循环改成do-while的样子,然后用goto翻译。

3.for循环

for循环可以轻易的改成while循环,所以再依照上面的方法改成do-while再翻译即可。

六、条件传送指令

控制的条件转移和数据 的条件转移:前者是条件操作的传统方法,后者是指先计算一个条件操作的两种结果,然后再根据条件是否满足从中选取一个。在有限的可行情况下,就可以用过简单的条件传送指令实现后者。

※基于条件数据传送的代码比基于条件控制转移的代码性能好。

七、Switch语句

Switch语句是多重分支的典型,而且使用的是跳转表这种数据类型,是的搜索的更快更高效。

所以这里的关键就是要领会使用跳转表是一种非常有效的实现多重分支的方法。

第七节 过程

过程调用:

进入,为过程的局部变量分配空间
将数据(以过程参数和返回值的形式)和控制从代码的一部分传递到另一部分。
退出,释放这些空间。

一、栈帧结构

栈用来传递参数、存储返回信息、保存寄存器,以及本地存储。

1.栈帧

为单个过程分配的那部分栈称为栈帧,通用结构见149页

所以本质上栈帧还是栈

2.两个指针

最顶端的栈帧以两个指针界定:

寄存器%ebp-帧指针
寄存器%esp-栈指针

栈指针可移动,所以信息访问多相对于帧指针。

3.调用的过程

课本150页过程P调用过程Q的示例。

调用者的帧应该在被调用者的下面,并且调用者返回地址是它的栈帧末尾,这样可以保证被调用者执行完毕全都出栈后,程序能够继续向下执行。

关于被调用者Q用栈的几个用处:

1.保存不能存放在寄存器中的局部变量。

当要对一个局部变量使用地址操作符&的时候,就必须要为它生成一个地址,所以要入栈。这个用法!以前没见过!

2.存放它调用的其他过程的参数。

二、转移控制

这里用到的主要就是CALL和RET这一对指令。

1.call

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

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

然后就会用到ret了。

2.ret

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

3.leave

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

movl %ebp,%esp
popl %ebp

三、寄存器使用惯例

程序寄存器组是唯一能被所有过程共享的资源。

保存一个值以待以后运算可用的时候,有两种选择:

1.由调用者保存。在调用之前就压进栈。

2.由被调用者保存,在刚被调用的时候就压进栈,并在返回之前恢复。

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

backtrace/bt n

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

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

frame n

n是一个从0开始的整数,是栈中的层编号。比如:frame 0,表示栈顶,frame 1,表示栈的第二层。

这个指令的意思是移动到n指定的栈帧中去,并打印选中的栈的信息。如果没有n,则打印当前帧的信息。

up n

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

down n

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

练习:

这是我输入的源代码:

执行了

之后

得到的结果,去掉.开头的句子之后:

add:
    pushl   %ebp    ;将%ebp入栈,为帧指针
    movl    %esp, %ebp
    movl    8(%ebp), %eax
    addl    $9, %eax
    popl    %ebp    ;%ebp出栈
    ret
sec:
    pushl   %ebp    ;将%ebp入栈,为帧指针
    movl    %esp, %ebp
    subl    $4, %esp
    movl    8(%ebp), %eax
    movl    %eax, (%esp)
    call    add     ;调用add函数
    leave           ;为返回准备栈,相当于%ebp出栈
add:
    pushl   %ebp    ;将%ebp入栈,为帧指针
    movl    %esp, %ebp
    movl    8(%ebp), %eax
    addl    $9, %eax
    popl    %ebp    ;%ebp出栈
    ret
sec:
    pushl   %ebp    ;%ebp入栈

这个程序的流程其实是sec的过程调用了add的过程,所以sec先把它的%ebp寄存器压入栈作为帧指针,然后压入被保存的寄存器、本地变量和临时变量,最上面是参数构造区域。然后再用call调用add,这时又把返回地址压入栈。

add被调用后,把它的帧指针%ebp压入栈,然后压入寄存器、本地变量、临时变量,最上面是参数构造区域。

add运算结束前,add会把%ebp弹出栈,然后ret指令弹出并跳转到之前call压入的地址,返回到sec过程,最后因为leave,%ebp出栈。

时间: 2024-10-24 20:48:11

20145225 《信息安全系统设计基础》第5周学习总结的相关文章

20145216 史婧瑶《信息安全系统设计基础》第一周学习总结

20145216 <信息安全系统设计基础>第一周学习总结 教材学习内容总结 Linux基础 1.ls命令 ls或ls .显示是当前目录的内容,这里“.”就是参数,表示当前目录,是缺省的可以省略.我们可以用ls -a .显示当前目录中的所有内容,包括隐藏文件和目录.其中“-a” 就是选项,改变了显示的内容.如图所示: 2.man命令 man命令可以查看帮助文档,如 man man : 若在shell中输入 man+数字+命令/函数 即可以查到相关的命令和函数:若不加数字,那man命令默认从数字较

20145311 《信息安全系统设计基础》第一周学习总结

20145311 <信息安全系统设计基础>第一周学习总结 教材学习内容总结 常用的部分命令 CTRL+SHIFT+T:新建标签页,编程时有重要应用: ALT+数字N:终端中切换到第N个标签页,编程时有重要应用: Tab:终端中命令补全,当输入某个命令的开头的一部分后,按下Tab键就可以得到提示或者帮助完成: CTRL+C:中断程序运行 Ctrl+D:键盘输入结束或退出终端 Ctrl+S: 暂定当前程序,暂停后按下任意键恢复运行 Ctrl+A: 将光标移至输入行头,相当于Home键 Ctrl+E

20145216史婧瑶《信息安全系统设计基础》第九周学习总结

20145216史婧瑶<信息安全系统设计基础>第九周学习总结 教材内容总结 第十章 系统级I/O 输入/输出(I/O)是在主存和外部设备之间拷贝数据的过程. 第一节 Unix I/O 这一节涉及到操作系统的基本抽象之一--文件.也就是说,所有的I/O设备都被模型化为文件,而所有的输入输出都被当做对相应文件的读/写.相关的执行动作如下: 1.打开文件: 应用程序向内核发出请求→要求内核打开相应的文件→内核返回文件描述符 文件描述符:一个小的非负整数,用来在后续对此文件的所有操作中标识这个文件.有

20145311 《信息安全系统设计基础》第二周学习总结

20145311 <信息安全系统设计基础>第二周学习总结 教材学习内容总结 重新学习了一下上周的一部分命令:grep main wyx.c(grep的全文检索功能)ls > ls.txt :ls内容输出到文本find pathname -mtime -n/+nfind -size -n/+n (find的功能还是比较强大) 简单地学习了一下vim编辑器,跟着vimtutor简单地学了一些,在linux bash中使用vim能够极大地提高效率, vim的用法比较多,只学习了其中简单的一部分

20145339《信息安全系统设计基础》第一周学习总结

20145339顿珠达杰<信息安全系统设计基础>第一周学习总结 ◆ Linux是一个操作系统.如果使用GUI,Linux和Windows没有什么区别.Linux学习应用的一个特点是通过命令行进行使用. 物理机系统上可以通过使用[Ctrl]+[Alt]+[F1]-[F6]进行终端和图形界面切换,在线实验环境中按下[Ctrl]+[Alt]+[F7]来完成切换.普通意义上的 Shell 就是可以接受用户输入命令的程序,Unix/Linux 操作系统下的 Shell 既是用户交互的界面,也是控制系统的

2017-2018-1 20155228 《信息安全系统设计基础》第九周学习总结

2017-2018-1 20155228 <信息安全系统设计基础>第九周学习总结 教材学习内容总结 常见的存储技术 RAM 随机访问存储器(Random-Access Memory, RAM)分为两类:静态的和动态的.静态 RAM(SRAM)比动态RAM(DRAM)更快,但也贵得多.SRAM用来作为高速缓存存储 器,既可以在CPU芯片上,也可以在片下.DRAM用来作为主存以及图形系统的帧缓冲 区.典型地,一个桌面系统的SRAM不会超过几兆字节,但是DRAM却有几百或几千兆 字节. SRAM将每

2017-2018-1 20155332 《信息安全系统设计基础》第九周学习总结

2017-2018-1 20155332 <信息安全系统设计基础>第九周学习总结 教材学习内容总结 简单模型中,存储器是一个线性的字节数组.真实模型中,是一个具有不同容量,成本,访问时间的存储层次结构(存储器山) 程序的局部性很重要,对程序性能有很重要的影响. 计算机系统一个基本而持久的思想,如果你理解了系统是如何将数据在存储器层级结构中上下移动,你就可以编写程序,让数据存储在层次结构中较高的地方,从而CPU可以更快的访问到他们. 编写程序实现功能是最简单的,如何让编写的程序拥有最高的性能,例

2017-2018-1 20155227 《信息安全系统设计基础》第九周学习总结

2017-2018-1 20155227 <信息安全系统设计基础>第九周学习总结 教材学习内容总结 第六章 随机访问存储器 随机访问存储器分为:静态RAM(SRAM)和动态RAM(DRAM),静态RAM(SRAM)比动态RAM(DRAM)更快,但也贵很多. (1)静态RAM SRAM将每个位存储在一个双稳态的存储器单元里,每个单元是用一个六晶体管电路来实现的. 属性:它可以无限制地保持在两个不同的电压配置或状态之一.其他任何状态都是不稳定的. 特点:由于SRAM的双稳态特性,只要有电,它就会永

2017-2018-1 20155334 《信息安全系统设计基础》第九周学习总结

2017-2018-1 20155334 <信息安全系统设计基础>第九周学习总结 学习目标: 了解常见的存储技术(RAM.ROM.磁盘.固态硬盘等) 理解局部性原理 理解缓存思想 理解局部性原理和缓存思想在存储层次结构中的应用 高速缓存的原理和应用 教材学习内容总结 一.常见的存储技术: 基本的存储技术包括随机存储器(RAM).非易失性存储器(ROM)和磁盘. 1. RAM分静态RAM(SRAM)和动态RAM(DRAM). 2. SRAM快些,主要用做CPU芯片上的高速缓存,也可以用作芯片下的

2017-2018-1 20155331 《信息安全系统设计基础》第九周学习总结

2017-2018-1 20155331 <信息安全系统设计基础>第九周学习总结 教材学习内容总结 存储器层次结构 存储技术 随机访问存储器 随机访问存储器分为:静态的SRAM.动态的DRAM 静态RAM: SRAM的特点:存储器单元具有双稳态特性,只要有电就会永远保持它的值,干扰消除时,电路就会恢复到稳定值. 动态RAM: DRAM的特点:每一位的存储是对一个电容的充电:对干扰非常敏感. 用途:数码照相机和摄像机的传感器 DRAM存储不稳定的应对机制: 存储器系统必须周期性地通过读出,或者重