20145219 《信息安全系统设计基础》第05周学习总结
20145219 《信息安全系统设计基础》第05周学习总结
教材学习内容总结
实验楼实验练习
-
test.c
实验代码
-
命令编译成汇编代码
test.s
-
删除gcc产生代码中以"."开头的编译器指令,并保存为
new.s
-
为汇编代码注释栈帧情况
教材重点内容
-
X86 寻址方式:
1 DOS时代的平坦模式,不区分用户空间和内核空间,很不安全 2 8086的分段模式 3 IA32的带保护模式的平坦模式
-
ISA的定义
指令集体系结构(ISA)定义了处理器状态、指令的格式、以及每条指令对状态的影响。大多数ISA包括IA32和x84-64,将程序的行为描述成好像每条指令是按顺序执行的。
-
汇编命令与反汇编命令
用
gcc -S xxx.c -o xxx.s
获得汇编代码,用gcc -c code.c
产生目标文件code.o
(二进制文件,无法直接查看),用objdump -d xxx.o
反汇编可以查看目标代码文件内容。汇编代码(函数前两条和后两条汇编代码,所有函数都有,建立函数调用栈帧):
前两条:
pushl %ebp 将寄存器%ebp的内容压入程序栈 movl %esp,%ebp 得到新栈低,将当前栈顶赋予栈低
后两条:
popl %ebp 过程调用结束,恢复旧栈低 ret 子程序的返回指令
64位机器上想要得到32代码:
gcc -m32 -S xxx.c
gcc -S 产生的汇编中可以把 以”.“开始的语句都删除了再阅读。
-
查看二进制文件
二进制文件可以用od 命令查看,也可以用gdb的x命令查看。 有些输出内容过多,我们可以使用 more或less命令结合管道查看,也可以使用输出重定向来查看:
od code.o | more od code.o > code.txt
-
不同数据的汇编代码后缀
-
Linux和Windows的汇编格式区别
1 Intel代码省略了指示大小的后缀。 2 Intel代码省略了寄存器名字前面的'%'符号。 3 Intel代码用不同的方式来描述寄存器中位置。 4 在带有多个操作数的指令情况下,列出操作数的顺序相反。
ATT是GCC、OBJDUMP和其它一些我们使用的工具的默认格式。Microsoft的工具、以及来自Intel的文档,其汇编代码都是Intel格式的。使用
gcc -S -masm=intel code.c
可以使GCC产生Intel格式的代码。 -
寄存器
esi edi可以用来操纵数组,esp ebp用来操纵栈帧。32位的eax,16位的ax,8位的ah,al都是独立的。
-
寻址方式
-
操作数三种类型
立即数,即常数值 寄存器,表示某个寄存器的内容 存储器,根据计算出来的地址(有效地址)访问某个存储器位置。
-
有效地址
计算方式
Imm(Eb,Ei,s) = Imm + R[Eb] + R[Ei]*s
-
MOV
MOV相当于C语言的赋值“=”,不能从内存地址直接MOV到另一个内存地址,要用寄存器中转一下。
MOV类中的指令将源操作数的值复制到目的操作数中,源操作数指定的值是一个立即数,存储在寄存器或存储器中,目的操作数指定一个位置,要么是一个寄存器,要么是一个存储器地址。
-
push与pop
先进后出:push将数据压入栈中,pop弹出,弹出的永远是最近被压入的。用数组实现栈,进行操作的一端为栈顶。栈向下增长,栈顶元素的地址是所有栈中元素地址中最低的。栈指针%esp保存栈顶元素的地址。
源操作数、目的操作数应为字操作数。
-
指针
C语言中“指针”其实就是地址。
-
局部变量
局部变量通常是保存在寄存器中。因为,寄存器访问比存储器访问要快得多。
-
算术和逻辑运算
1、一元操作:只有一个操作数,既是源又是目的,可以是一个寄存器,或者存储器位置。
2、二元操作:第一个操作数可以是立即数、寄存器或者存储器位置;第二个操作数既是源也是又是目的,可以是寄存器或者存储器位置,但是不能同时是存储器位置。
操作的顺序:第二个操作数 操作符 第一个操作数
3、移位操作:先给出移位量,第二项给出要移位的数值。
源操作数(移位量):立即数或者放在单字节寄存器元素%cl中。目的操作数:一个寄存器或是一个存储器位置。
-
控制
有条件跳转的条件看状态寄存器(教材上叫条件码寄存器) 注意leal不改变条件码寄存器。
1、分支(if/switch)
C语言if-else 语句:
if(test-expr) then-statement else else-statement (注:test-expr 整数表达式[假/真])
汇编实现形式:
t = test-expr; if (!t) goto false; then-statement goto done; false: else-statement done:
2、循环(while, for)
C语言do-while循环:
do body-statement while(test-expr);
汇编实现形式:
loop: body-statement t = test-expr; if(t) goto loop;
while循环、for循环均需转换成do-while形式在转换
3、switch语句
执行switch语句的关键步骤是通过跳转表来访问代码位置。
-
IA32
IA32利用程序栈来支持过程调用(包括将数据和控制)。为单个过程分配的那部分栈做栈帧。最底端(地址最大)%ebp为帧指针;最顶端(地址最小)%esp为栈指针。当程序执行时,栈指针可以移动。
-
转移
1、call指令
目标:指明被调用过程起始的指令地址。 效果:将返回地址入栈,并跳转到被调用过程的起始处。
2、ret指令
从栈中弹出地址,并跳转到这个位置. 使用这个指令时,栈指针要指向前面call指令存储返回地址的位置。
gdb代码调试过程
课后作业中的问题和解决过程
- 问题:p148 3.29通过阅读汇编代码和跳转表补填C语言代码中的缺失部分,我不明白课后答案中
case 几
是怎么得出的,越读越混乱,截至上交博客时还未解决。
本周代码托管截图
- 代码托管连接
- 老师上周让我改托管代码的格式,不要都混在一起,我这周尝试多次都不成功,还把原来已经托管的代码弄的一团乱,没有办法了,我只好重新新建了一个项目重新上传之前的和这次的代码,以前的那个项目太乱了已经删除了。
其他(感悟、思考等,可选)
本周的知识是与汇编语言相关的,在上学期的汇编语言学习过程中,我已经了解并基本掌握了一些寻址方式和汇编语言指令,能够阅读简单的汇编语言代码。本周的学习,我把重点放在C语言代码的汇编和反汇编、C语言代码和汇编代码的转换以及加强阅读汇编代码的能力提高上。
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第零周 | 0/0 | 1/1 | 15/15 | |
第一周 | 0/0 | 1/2 | 25/40 | |
第二周 | 62/62 | 1/3 | 25/65 | |
第三周 | 176/238 | 1/4 | 20/85 | |
第五周 | 57/295 | 1/5 | 20/105 |