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
      • 格式的注解:ATTIntel汇编代码格式。
      • 理解寄存器%eax%ecx%edx%ebx为通用寄存器,%esi%edi可以用来操作数组,%esp%edp可以操作指针。
      • MOV指令是使用最频繁的指令,注意不能直接从一个内存地址MOV到另一个内存地址,要在寄存器中中转一下。
      • 注意栈顶元素的地址是所有栈中元素地址中最低的。
      • 指针就是地址,局部变量保存在寄存器中。
    • 算数和逻辑操作:

      • leal指令,加载有效地址,是movl指令的一个变形
      • 一元操作只有一个操作数,既是源又是目的。
      • 注意二元操作,源操作数是第一个,目的操作数是第二个,注意减法操作后-前
      • 移位操作先可以给出移位量,第二项再给出要移位的数值。
    • 控制:

      • jump指令可以改变一组机器代码指令的执行顺序。对于switch语句可以采用jump table跳转表来完成跳转。
      • 条件码寄存器用来设置跳转的条件位的。
      • leal不改变条件码寄存器。
      • SET指令根据计算t=a-b设置条件码。
      • 有条件跳转(ifwhilefor)注意看条件码寄存器和无条件跳转(goto)。
      • if-else结构:使用了goto语句。
      • 循环结构:do-while是最基本的循环结构,其他的循环首先会转换成do-while来产生循环代码。每次循环会测试表达式,如果测试为真(非零)继续循环。c语言中三种形式的循环do-whilewhilefor都可以用一种简单策略来翻译,产生包含一个或多个条件分支的代码。控制条件转移为循环翻译成机器代码提供了基本机制。
      • switchjt表中引用&&作为新的指针,执行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-whileforswitch),而对于汇编低级就算计语言不能很准确的翻译条件,需要借助一些条件码,比如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 加强对汇编语言的理解

参考资料

posted @ 2016-10-16 23:07  20145335郝昊  阅读(202)  评论(7编辑  收藏  举报