20145223 《信息安全系统设计基础》第5周学习总结
教材学习内容总结
*Intel处理器(X86) 寻址方式经历三代:
1.DOS时代的平坦模式,不区分用户空间和内核空间,很不安全
2.8086的分段模式
3.IA32的带保护模式的平坦模式
*程序编码:
在执行命令gcc时所使用的就是GCC C编译器,这是Linux上默认的编译器,实际上gcc命令调用了一系列程序,将源代码转换为可执行代码
*机器级编程有两种重要的抽象
1.机器级格式的格式和行为,定义为指令集体系结构——ISA,它定义了处理器状态、指令的格式以及每条指令对状态的影响
2.机器级程序使用的存储器地址是虚拟地址,存储系统的实际实现是将多个硬件存储器和操作系统软件组合起来
*gcc -S xxx.c -o xxx.s 获得汇编代码,也可以用objdump -d xxx 反汇编; 注意函数前两条和后两条汇编代码,所有函数都有,建立函数调用栈帧,应该理解、熟记
注意: 1.64位机器上想要得到32代码:gcc -m32 -S xxx.c
2.MAC OS中没有objdump, 有个基本等价的命令otool
3.Ubuntu中 gcc -S code.c (不带-O1) 产生的代码更接近教材中代码(删除"."开头的语句)
*二进制文件可以用od 命令查看,也可以用gdb的x命令查看
有些输出内容过多,我们可以使用 more或less命令结合管道查看,也可以使用输出重定向来查看
od code.o | more
od code.o > code.txt
*不同数据的汇编代码后缀
C声明 | Intel数据类型 | 汇编代码后缀 | 大小(字节) |
---|---|---|---|
char | 字节 | b | 1 |
short | 字 | w | 2 |
int | 双字 | l | 4 |
long int | 双字 | l | 4 |
long long int | — | — | 4 |
lchar * | 双字 | l | 4 |
float | 单精度 | s | 4 |
double | 双精度 | l | 8 |
long double | 扩展精度 | t | 10/12 |
*IA32整数寄存器
·寄存器就是用来存放数据的容器,比如存储程序里某个int变量的值,或者是某个指针指向的值等等。
·在IA32中央处理单元(CPU)中,包含了8个32位整数寄存器(如下图)。从图中可以看到在每个32位寄存器的名字前面都会有一个%e,在这里可以把e理解成extended(扩展的),因为早期的8086寄存器是16位,所以加e之后就变成32位的了
esi edi可以用来操纵数组,esp ebp用来操纵栈帧。
对于寄存器,特别是通用寄存器中的eax,ebx,ecx,edx,大家要理解32位的eax,16位的ax,8位的ah,al都是独立的
问题:假定当前是32位x86机器,eax寄存器的值为0x8226,执行完addw $0x8266, %ax指令后eax的值是多少?
解析:0x8226+0x8226=0x1044c, ax是16位寄存器,出现溢出,最高位的1会丢掉,剩下0x44c,不要以为eax是32位的不会发生溢出.
操作数的三种类型:立即数、寄存器、存储器;有效地址的计算方式: Imm(Eb,Ei,s) = Imm(立即数偏移) + R[Eb](基址寄存器) + R[Ei](变址寄存器)s(比例因子)
*MOV指令
MOV指令将原操作数的值复制到目的操作数中,**传送指令的两个操作数不能都指向存储器位置,即不能从内存地址直接MOV到另一个内存地址,要用寄存器中转一下。**
MOV相当于C语言的赋值”=“,注意ATT格式中的方向,
MOVS和MOVZ指令类都是将一个较小的源数据复制到一个较大的数据位置,高位用**符号扩展(MOVS)**或**零扩展(MOVZ)**进行填充
*push,pop指令
栈是一个数据结构,可以添加或者删除值,原则是**先进后出**,push操作把数据压入栈中,pop操纵删除数据。
**注意**栈顶元素的地址是所有栈中元素地址中最低的
*C语言中的指针其实就是“地址”,局部变量保存在寄存器中,间接引用指针就是将该指针放在一个寄存器中,然后在存储器引用中使用这个寄存器。
*算术和逻辑操作
leal S,D——加载有效地址
INC D——加一
DEC D——减一
NEG D——取负
NOT D——取补
ADD S,D——加
SUB S,D——减
IMUL S,D——乘
XOR S,D——异或
OR S,D——或
AND S,D——与
SAL k,D——左移
SHL k,D——左移
SAR k,D——算术右移
SHR k,D——逻辑右移
注意移位操作移位量可以是立即数或%cl中的数
算术和逻辑操作目的操作数类型
1.leal:目的操作数必须是一个寄存器
2.一元操作:操作数可以是一个寄存器,也可以是一个存储器位置
3.二元操作:第一个操作数可以是立即数、寄存器或者是存储器位置,第二个操作数可以是寄存器或存储器位置,**两个操作数不能同时是存储器位置**
4.位移操作:位移量可以是一个立即数,目的操作数可以是一个寄存器或是一个存储器位置
*条件码
CF:进位标志
ZF:零标志
SF:符号标志
OF:溢出标志
leal指令不改变任何条件码,因为它是用来进行地址计算的,除此之外上面列出的算术和逻辑运算指令都会设置条件码
有两类指令只设置条件码而不改变其他寄存器:
CMP S2,S1:比较S1,S2来设置条件码
TEST S2,S1:与AND指令一样,但不改变目的寄存器的值
SET指令:目的操作数是8个单字节寄存器元素之一,或是存储一个字节的存储器位置,将这个字节设置为0或者1, SET指令根据t=a-b的结果设置条件码
*跳转语句
jmp:**无条件跳转(goto)**
p128所示的其他跳转命令都是有条件的,这些指令的名字和跳转条件与SET指令是匹配的(实现if,switch,while,for)。
*条件分支(if/switch)
if—els形式e:
t=test-expr;
if(!t)
goto false;
then-statement
goto done
false:
else-atatemrnt
done:
*循环语句(while, for)
do-while循环:
loop:
body-statement
t = test-sxpr;
if(t)
goto loop;
while循环:
t = test-sxpr;
if(!t)
goto done;
loop:
body-statement
t = test-sxpr;
if(t)
goto loop;
done
for循环:
init-expr;
while(test-expr){
body-statement;
update-expr;
}
*switch:根据一个整数索引值进行多重分支 ,教材P145案例
*IA32利用栈来支持过程调用(包括将数据和控制),为单个过程分配的那部分栈称为栈帧,最顶端的栈帧用两个指针界定,寄存器%ebp为帧指针,寄存器%esp为栈指针(栈指针%esp指向栈顶元素)。当程序执行时,栈指针可以移动,大多信息的访问都是相对于帧指针来说的。
*转移控制(call/ret):函数返回值存在%eax中
call指令的结果是将返回地址入栈,斌跳转到被调用过程的起始处,**返回地址是程序中紧跟call后面那条指令的地址**
ret指令从栈中弹出地址,并跳转到这个位置,使用这条指令栈指针要指向前面call指令存储返回地址的位置。
教材学习中的问题和解决过程
习题3.1:掌握各种寻址方式
习题3.3:掌握指令使用规则
movb $0xF,(%bl):(%bl)是一个值,不是寄存器或者存储器地址
movl %al:指令后缀和寄存器标识之间的不匹配
movw (%eax),4(%esp):两个目的操作数不能同时为存储器
movb %ah,%sh:%sh寄存器不存在
movl %eax $0x123:立即数不能作为目的操作数
movl %eax,%dx:目的操作数%dx的大小不符合要求
movb %si,8(%epb):指令后缀和寄存器标识之间的不匹配
习题3.5:逆向思维,将汇编代码转换为等效的C语言代码:
习题3.9:
c语言代码如下:
gcc -o XXX.c编译后的汇编代码如下:
利用objdump
反汇编
习题3.16第二问:** 第一个条件分支是&&表达式实现的一部分。如果对p为非空的测试失败,代码会跳过对a>0的测试。**
实验楼练习
学习过程中遇到的问题
习题3.15 题目:C.
解析:je指令的目标为0x8048391,则mov指令的地址为0x8048391-0x12,即0x804837f。又因为74、12占2字节,则je指令的地址为0x804837f-2,即0x804837d
因此答案是:
804837d: 74 12 je 8048391
804837f: b8 00 00 00 mov $0x0, %eax
部分本周代码托管截图——- 代码托管链接
实验楼:
书上练习:
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 4000行 | 20篇 | 400小时 | |
第0周 | 0/0 | 1/1 | 5/5 | |
第1周 | 0/0 | 1/2 | 10/15 | |
第2周 | 300/300 | 1/3 | 15/30 | |
第3周 | 200/500 | 1/4 | 10/40 | |
第5周 | 150/650 | 1/5 | 10/50 |