zoukankan      html  css  js  c++  java
  • 信息安全系统设计基础第四周学习总结

    程序的机器级

    由于格式不够美观,我重新将博客换了一种编译器编写,但因为编译器的修改必须重新开一篇博客。留此截图以示提交日期,此博客为格式修改过的新随笔,以此为准。

    一、x86寻址方式的历程

    DOS时代的平坦模式,不区分用户空间和内核空间,很不安全;8086的分段模式;IA32的带保护模式的平坦模式
    特别注意:i386增加了平坦寻址模式,Linux和最近版本的windows系列操作系统都是使用这种模式,这是Intel系列中第一台Unix操作系统的机器。

    二、程序编程

    1、机器级代码

    ①ISA:机器级程序的格式和行为,定义为指令集体系机构,它定义了处理器状态指令的格式,以及每条指令对状态的影响。
    机器级程序使用的存储器地址是虚拟地址,提供的存储器模型看上去是一个非常大的字符数组。
    ②PC:程序计数器。在IA32中,用%eip表示,指示将要执行的下一条指令在存储器中的地址。
    ③程序存储器:包含程序的可执行机器代码,操作系统需要的一些信息,用来管理过程调用和返回的运行时栈,以及用户分配的存储器块。

    ④ARM(举一反三部分)参考链接:

    http://blog.chinaunix.net/uid-25067956-id-398205.html

    2、代码示例

    ①64位机上想得到32位代码:

    gcc -m32 -S xxx.c

    ②编译并产生汇编目标文件xxx.o:

    gcc -O1 -c xxx.c

    ③获得汇编代码:

    gcc -S xxx.c -o xxx.s

    ④Ubuntu中获得汇编代码:(更接近教材)

    gcc -S xxx.c

    ⑤教材中获得汇编代码:(编译器使用的是第一级优化)

    gcc -O1 -S xxx.c

    ⑥汇编代码中需要牢记以下几句:

    pushl %ebp
    movl %esp,%ebp
    ……
    popl %ebp
    ret

    ⑦二进制文件可用od命令查看,也可以用gdb的x查看:

    (gdb)x/17xb sum

    (表示检查17个十六进制的字节)
    ⑧显示代码过多或过少可用more、less结合管道查看,也可以用输出重定向:

    od xxx.o | more
    od xxx.o > xxx.txt

    ⑨反汇编:

    objdump -d xxx.o

    ⑩MAC OS中没有objdump,可用otool代替;

    ***注意:汇编代码中另类结尾有'l'指的是大小指示符。

    3、关于格式的注释

    当带选项-S和-O1运行gcc时,会产生xxx.s文件,其中带有'.'开头的行是指导汇编器和链接器的命令。
    gcc -S产生的汇编代码中可以把以'.'开头的语句删除再使用也没关系。
    了解Linux和windows的汇编格式的区别:Intel代码省略了指示大小的后缀,即'l';Intel代码省略了寄存器名字前面的'%'符号,用的是esp,而不是%esp。

    三、数据格式

    C语言数据类型在IA32中的大小:

    四、访问信息

    1、IA32的整数寄存器:

    其中,esi、edi可以用来操纵数组,esp、ebp用来操纵栈帧。

    通用寄存器中的eax,ebx,ecx,edx中,32位的eax,16位的ax,8位的ah,al都是独立的。例如:
    假定当前是32位x86机器,eax寄存器的值为0x8226,执行完addw $0x8266, %ax指令后eax的值是多少?
    解析:0x8226+0x826=0x1044c, ax是16位寄存器,出现溢出,最高位的1会丢掉,剩下0x44c,不要以为eax是32位的不会发生溢出。

    2、操作数的整数寄存器

    操作数的三种类型:立即数、寄存器、存储器。

    有效地址的计算方式: Imm(Eb,Ei,s) = Imm + R[Eb] + R[Ei]*s

    寻址方式和操作数格式:

    3、数据传送指令

    不能从内存地址直接MOV到另一个内存地址,要用寄存器中转一下,因此需要两个指令。

    MOV:将源操作数的值复制到目的操作数中;
    MOVS:将一个较小的源数据复制到一个较大的数据位置,高位用位扩展;
    MOVZ:将一个较小的源数据复制到一个较大的数据位置,高位用零扩展。
    push:把数据压入栈中;
    pop:删除数据。

    栈顶元素的地址是所有栈中元素地址中最低的,栈指针%esp保存着栈顶元素的地址。

    4、数据传送示例

    指针是地址。
    局部变量通常是保存在寄存器中,而不是存储器中。寄存器访问比存储器访问要快得多。

    五、算数和逻辑操作

    第一类:目的操作数必须是一个寄存器
    
    第二类:一元操作。操作数既是源又是目的。可以是寄存器也可以是存储器。
    
    第三类:二元操作。第二个操作数既是源又是目的。但两个操作数不能同时是存储器。
    
    第四类:移位操作。位移量是一个立即数或放在单字节寄存器%cl中。移位操作的目的操作数可以是一个寄存器或是一个存储器位置。

     

    六、控制

    机器代码提供两种基本的低级机制来实现有条件的行为:测试数据值,然后根据测试的结果来改变控制流或者数据流。
    控制部分运用分支、循环语句实现。

    最核心的是跳转语句、有条件跳转、无条件跳转。

    1、条件码(状态寄存器):描述最近的算术或逻辑操作的属性。

    重点关注:CF、ZF、SF、OF
    

    leal指令不改变任何条件码,因为是用来进行地址计算的。

    >>有两类指令只设置条件码而不改变任何其他寄存器。

    >>CMP指令根据他们的两个操作数之差来设置条件码。除了至设置条件码而不更新目标寄存器之外。CMP与SUB行为是一样的。

    2、访问条件码

    SET指令:

    SET命令的描述都适用的情况是:执行比较指令,根据计算t=a-b设置条件码。
    当t=a-b中,当a-b<0时,CMP指令会设置仅为标志,因此无符号比较使用的是进位标志和零标志的组合。

    3、跳转指令及其编码

    跳转指令会导致执行切换到程序中一个全新的位置。这些跳转的目的地通常用一个标号指明。
    跳转语句主要有有条件跳转(if,switch,while,for)和无条件跳转jmp(实现goto)。

    主要查看书本包括例子:

    p130/p131: if-else 
    p132/p133: do-while
    p134/p135: while
    p137/p138: for
    p144/p145: switch

    七、过程

    IA32通过栈帧来实现过程调用。数据传递、局部变量的分配和释放通过操纵程序栈来实现。

    1、栈帧结构

    机器用栈来传递过程参数、存储返回信息、保存寄存器用于以后恢复以及本地存储。

    最顶端的栈帧以两个指针界定,寄存器%ebp为帧指针,而寄存器%esp为栈指针。

    2、转移控制


    call指令有一个目标,即指明被调用过程起始的指令地址。同跳转一样,调用可以是直接的,也可以是间接地。直接调用的目标是一个标号,而间接调用的目标是*后面跟一个操作数指示符。
    call指令的效果是将返回地址入栈,并跳转到被调用过程的起始处。返回地址是在程序中紧跟在call后面的那条指令的地址。
    ret指令从栈中弹出地址,并跳转到这个位置。栈指针要指向前面call指令存储返回地址的位置。
    返回值存在%eax中。

    八、使用GDB调试器

    1、启动GDB:

    gdb xxx

    2、补充知识点:

    <<<<查看函数调用栈信息的GDB命令
    ①backtrace/bt n
    n是一个正整数,表示只打印栈顶上n层的栈信息。
    -n表一个负整数,表示只打印栈底下n层的栈信息。
    ②frame n
    n是一个从0开始的整数,是栈中的层编号。比如:frame 0,表示栈顶,frame 1,表示栈的第二层。
    这个指令的意思是移动到n指定的栈帧中去,并打印选中的栈的信息。若不输入数字则默认打印当前帧的信息。 
    ③up n 表示向栈的上面移动n层,若不输入数字则默认向上移动一层。
    ④down n 表示向栈的下面移动n层,若不输入数字则默认向下移动一层。

    九、遇到的问题和解决方法

    起先做实验练习的时候,在编译week4.c时输入的编译代码是:

    gcc -O1 -S week4.c
    

    导致编译所得的汇编代码很奇怪,与应该有的代码差之甚远,如图:

    将其删除为纯汇编代码后非常简短,无法直观看出栈帧使用情况。原因是老师给出的编译代码、书上的编译代码没有将功能区分清楚,才导致了这样的情况。

    原本以为是系统环境的差别导致的,但是在MAC OS中编译也是十分简短,该有的代码没有出现。后来仔细尝试和再次查阅实验指导材料才发现是没有在64位环境下将代码转换为32位的汇编代码。

    十、实验练习

    ①使用vim编辑代码:

    ②编译:

    ③使用vim查看汇编文件:


    或者使用cat xxx.s查看汇编文件效果一致。
    ⑤修改汇编代码并另存为week4_final_.s:

    代码操作完成。

    虚拟机Ubuntu上操作截图:

    纯汇编代码:

    堆栈使用情况:

    十一、参考文献

    1、《深入理解计算机系统》pdf

    2、ARM知识拓展博客:http://blog.chinaunix.net/uid-25067956-id-398205.html

    3、实验楼实验指导书:https://www.shiyanlou.com/courses/413 实验四

  • 相关阅读:
    查看服务器被动手脚
    cordova安卓sdk
    Nginx 启动报错 “/var/run/nginx/nginx.pid" failed”
    家庭里如何搭建一个互联网可访问的服务器
    Mysql5.7基于事务转为基于日志
    021 基本数据类型小结
    018 字符串类型及操作
    022 程序的控制结构
    020 实例4-文本进度条
    017 示例3-天天向上的力量
  • 原文地址:https://www.cnblogs.com/paperfish/p/4872902.html
Copyright © 2011-2022 走看看