20145335郝昊《信息安全系统设计基础》第五周学习总结
20145335 《信息安全系统设计基础》第五周学习总结
教材学习内容总结
-
本章概述:
本周学习了C语言提供的抽象层下面的东西,以了解机器级编程。通过让编译器产生机器级程序的汇编代码表示,我们了解了编译器和它的优化能力,还有一些机器、数据类型和指令集。
机器级程序和它们的汇编代码表示与C程序的差别很大。程序是以指令序列来表示的,每条指令都完成一个单独的操作。编译器必须使用多条指令来产生和操作各种数据结构。
用字节代码作为程序的低级表示,优点是相同的代码可以在许多不同的机器上执行,而本章谈到的机器代码只能在x86机器上运行。
-
知识点小结:
-
x86经历的寻址方式:
- DOS时代的平坦模式,不区分用户空间和内核空间,很不安全
- 8086的分段模式
- IA32的带保护模式的平坦模式
-
程序编码和数据格式:
- 使用GCC编译时候命令行中加入
-o1
使用第一级优化 、-o2
使用第二级优化 gcc -S xxx.c -o xxx.s
获得汇编代码,也可以用objdump -d xxx
反汇编; 注意函数前两条和后两条汇编代码,所有函数都有,建立函数调用栈帧。- b:8位、w:16位、l:32位。
- 注意: 64位机器上想要得到32代码:
gcc -m32 -S xxx.c
- 格式的注解:
ATT
和Intel
汇编代码格式。 - 理解寄存器
%eax
、%ecx
、%edx
、%ebx
为通用寄存器,%esi
和%edi
可以用来操作数组,%esp
和%edp
可以操作指针。 MOV
指令是使用最频繁的指令,注意不能直接从一个内存地址MOV
到另一个内存地址,要在寄存器中中转一下。- 注意栈顶元素的地址是所有栈中元素地址中最低的。
- 指针就是地址,局部变量保存在寄存器中。
- 使用GCC编译时候命令行中加入
-
算数和逻辑操作:
leal
指令,加载有效地址,是movl
指令的一个变形- 一元操作只有一个操作数,既是源又是目的。
- 注意二元操作,源操作数是第一个,目的操作数是第二个,注意减法操作后-前
- 移位操作先可以给出移位量,第二项再给出要移位的数值。
-
控制:
- 用
jump
指令可以改变一组机器代码指令的执行顺序。对于switch
语句可以采用jump table
跳转表来完成跳转。 - 条件码寄存器用来设置跳转的条件位的。
leal
不改变条件码寄存器。SET
指令根据计算t=a-b
设置条件码。- 有条件跳转(
if
、while
、for
)注意看条件码寄存器和无条件跳转(goto
)。 if-else
结构:使用了goto
语句。- 循环结构:
do-while
是最基本的循环结构,其他的循环首先会转换成do-while
来产生循环代码。每次循环会测试表达式,如果测试为真(非零)继续循环。c语言中三种形式的循环do-while
、while
和for
都可以用一种简单策略来翻译,产生包含一个或多个条件分支的代码。控制条件转移为循环翻译成机器代码提供了基本机制。 switch
的jt
表中引用&&
作为新的指针,执行switch
语句的关键步骤是通过跳转表来访问代码位置。
- 用
-
过程:
IA32
程序用程序栈来支持过程调用。注意:栈是向低地址增长的。- 栈帧结构:用来传递参数、储存返回信息、保存寄存器、以及本地存储
call
/ret
; 函数返回值存在%eax
中leave
指令可以使栈做好返回的准备- 程序寄存器是唯一能被所有过程共享的资源。
-
教材学习中的问题和解决过程
-
对于数据格式的知识
在书p111页给了数据格式,在汇编代码的后缀。在之后学习mov指令的时候,其中有一个指令
movl $Ox4050,%eax ,可是在之后使用中发现
movl指令对于双精度浮点数可以进行传送。后来看书,知道了汇编代码也使用后缀
‘l’`来表示4字节整数和8字节双精度浮点数。其实并不会产生歧义,因为浮点数使用的是一组完全不同的指令和寄存器。 -
对于寻址模式
首先在对于
%eax
和(%eax)
有点疑问,不知道二者样子相同,二者具体有什么不同,后来通过看书上p113的表格,其中有寄存器Ea
,操作数值是R[Ea]
,储存器(Ea)
操作数值是M[R[Ea]]
。虽然二者看起来样子很相似,但本质还是不一样的,一个是寄存器,另一个则表示缓存器,二者所代表的值也是不同的。 -
对于栈
栈在数据结构中就有所接触,遵循先进后出的原则。但是对于为什么栈底的地址大,栈顶的地址值小?如果这样那么栈就不会很大吗?通过网上百度,解决了这一问题。在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在Windows下栈的大小是固定的空间(1M或2M)超过栈的剩余空间会提示
overflow
。就类似于数组中的内个i,stack[i],入栈后i-1,出栈后i+1,i始终指向栈顶。 -
对于控制
首先对于这部分的知识不明白条件码和循环的具体关系是什么,导致在学习的时候有点云里雾里。后来询问同学后得知,因为这一小节是循环汇编,不仅有无条件跳转
goto
还有条件跳转(do-while
、for
、switch
),而对于汇编低级就算计语言不能很准确的翻译条件,需要借助一些条件码,比如CF
:进位标志、ZF
:零标志、SF
:符号标志、OF
溢出标志等,这样相互配合使用这些条件码就能解决了循环条件,这样也就解决了问题。 -
对于Switch语句
起初书上给的例子是有开关100、102~104、106,通过汇编代码,首先将106与100做差值运算,这样就会简化汇编语言的操作。可是对于这个例子102 开关之后没有
break;
既没有跳出语句,会继续操作103的代码,汇编语言是怎么实现的?通过自己动手操作了书上的例子后,两种情况有不同的目的地址,将这两个代码块都汇总到将result
加11的代码,这样就解决了问题。
代码调试中的问题和解决过程
-
练习的c代码
-
汇编代码,注意:要删除
.
开头的代码
-
cat homework
例子的汇编代码
-
查看可执行文件的二进制内容
-
将可执行文件转换为反汇编代码
课后作业中的问题和解决过程
-
习题3.1
其中有一个是
260(%ecx,%edc)
计算值,起初一直把260当作十进制运算,可是没有结果,后来发现260是十进制,但是参与运算时需要将其转换为16进制再次参与运算,这样260=Ox104
这样答案也就得到了。 -
习题3.2
指令的补全,对于mov指令格式为
mov s,d
,将s传送给d。但是对于MOV %eax,(%eax)
为什么是MOVL
而不是MOVW
?后来知道%ax
为寄存器16位,%eax
是扩展寄存器32位,这样就需要传送双字,就需要MOVL指令。 -
习题3.7
对于指令
imull $16,(%eax,%edx,4)
其中后面部分(%eax,%edx,4)
为目的操作数,计算出来为Ox10C
,对于16是十进制,如习题3.1一样,在运算时候需要换成十六进制Ox10
,这样对其运算就可以得到正确的结果。 -
习题3.29
对于
switch
语句的汇编代码,最初在做的时候存在序号问题,后来仔细查阅了解C语言中case
对应的序号对应着跳转表中的序号,需要注意的时候跳转表中的序号从0开始的。
本周代码托管截图
https://git.oschina.net/20145335/Linux-besti-is-20145335.git
其他(感悟、思考等,可选)
本周的学习内容是建立在汇编语言的基础之上的,最开始也会疑问,学习使用计算机,会编程就已经可以了,为什么还需要去掌握这些低级的语言,但是目的不仅仅是会编程而已,是需要了解计算机系统的操作原理和运行的每一步的。就比如最早接触的c语言,虽然一个hello world简单,但是是如何一步步从0、1比特流转换而来的。这都是需要我们去理解的,理解了它的历史,才有可能去发展它的未来。这周在本章下了很多时间,也补了很多汇编语言的功课,总之还是要去认认真真去对待每一个章节的知识点,这样才能融汇贯通。
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 200/200 | 2/2 | 20/20 | |
第二周 | 300/500 | 2/4 | 18/38 | |
第三周 | 500/1000 | 3/7 | 24/60 | |
第四周 | 1000/1300 | 2/9 | 30/90 | 加强对汇编语言的理解 |