汇编语言程序设计永利集团304com:,程序的机器级表示

本文同时发布于我的博客

  • 3.2 程序编码
    • 3.2.1 机器级表示
      • 抽象
        • 计算机系统使用了多种不同形式的抽象,
          利用更简单的抽象模型来隐藏实现的细节
        • 最重要的两种抽象:
          1. 由指令集体系结构(Instruction Set Architecture,
            ISA)来定义机器级程序的格式和行为.
          2. 机器级程序使用的内存地址是虚拟地址,
            提供的内存模型看上去是一个非常大的字节数组
      • 处理器状态
        • 程序计数器(通常被称为”PC”, 在x86-64中用%rip表示):
          给出将要执行的下一条指令在内存中的地址
    • 3.2.2 代码示例
      • 汇编与反汇编程序
        • 汇编: gcc
          • linux> gcc -Og -S mstore.c
            • 这会使GCC运行编辑器, 产生一个汇编文件mstore.s,
              但是不做其他进一步的工作. (通常情况下,
              它还会继续调用汇编器产生目标代码文件)
          • linux> gcc -Og -c mstore.c
            • 这会产生目标代码文件mstore.o, 它是二进制格式的,
              所以无法直接查看
        • 反汇编: objdump
          • linux> objdump -d mstore.o
            • 这些反汇编程序(像objdump)会根据机器代码产生一种类似汇编代码的格式
      • 链接器
        • l链接器(Linker)是一个程序,
          将一个或多个由编译器或汇编器生成的目标文件外加库链接为一个可执行文件
    • 3.2.3 关于格式的注释
      • 以”.”开头的行
        • 都是指导汇编器和链接器工作的伪命令
      • 把C语言和汇编语言结合起来
        • 方法:
          1. 我们可以编写完整的函数, 放进一个独立的汇编文件中,
            让汇编器和链接器把它和用C语言编写的代码合并起来
          2. 我们可以使用GCC的内联汇编(inline assembly)特性,
            用asm伪指令可以在C程序中包含简短的汇编代码

            • 好处: 减少代码量
            • 坏处:
              会使代码与某些特殊的机器有关,所以只应该在想要的特性只能以这种方式才能访问到时才使用它
      • 条件码: 条件码是CPU根据运算结果由硬件设置的位,
        体现当前指令执行结果的各种状态信息. 例如:
        算术运算产生的正/负/零/溢出等结果.

        • 奇偶标志(parity flag):
          • 定义: 用于反映运算结果中”1″的个数的奇偶性
          • 作用: 为了提供传送的可靠性, 如果采用奇偶校验的方法,
            就可使用该标志位
  • 3.3 数据格式
    • 由于是从16位体系结构扩展成32字,
      Intel用术语”字(word)”表示16位数据类型. 因此32位数为”双字(double
      words)”, 称64位数为”四字(quad words)”.
    • 数据格式的汇编后缀:
      • 后缀”l”: 表示4字节整数和8字节双精度浮点数, 这样不会产生歧义,
        因为浮点数使用的是一组完全不同的指令和寄存器
  • 3.4 访问信息
    • 通用目的寄存器:
      • 作用: 用来存储整数数据和指针
      • 数量: 16
      • 详情:
        • 8位: | %al | %bl | %cl | %dl | %sil | %dil | %bpl | %spl
          | %r8b | %r9b | %r10b | %r11b | %r12b | %r13b | %r14b |
          %r15b |
        • 16位: | %ax | %bx | %cx | %dx | %si | %di | %bp | %sp |
          %r8w | %r9w | %r10w | %r11w | %r12w | %r13w | %r14w |
          %r15w |
        • 32位: | %eax | %ebx | %ecx | %edx | %esi | %edi | %ebp |
          %esp | %r8d | %r9d | %r10d | %r11d | %r12d | %r13d |
          %r14d | %r15d |
        • 64位: | %rax | %rbx | %rcx | %rdx | %rsi | %rdi | %rbp |
          %rsp | %r8 | %r9 | %r10 | %r11 | %r12 | %r13 | %r14 |
          %r15 |

          • 不同字节数的操作码可以访问不同的最低寄存器
    • 3.4.1 操作数指示符
      • 操作数: 一个操作中要使用的源数据值, 以及放置结果的目的位置
        • 操作数本身没有数据类型的标志, 它的数据类型由操作码确定
      • 操作数格式:
        • 产生原因: 源数据值可以以常数形式给出,
          或是从寄存器或内存中读出. 结果可以存放在寄存器或内存中.
          因此, 不同的操作数可以分为三种类型:

          1. 立即数: 用来表示常数值
          2. 寄存器: 表示某个寄存器的内容
          3. 内存引用:
            根据计算出来的==地址==(通常是有效地址)访问某个内存位置
    • 3.4.2 数据传送指令
      • 注意点:
        • movabsq: 源操作数只能为64位立即数,
          目的操作数只能是寄存器
        • 指令如何修改目的寄存器的高字节数: 按照操作码的不同,
          有不同的方式. 有些操作码会保持高位不变,
          有些会将高位设置为0, 有些会将高位设置为符号位
        • x86-64的限制: 传送指令的两个操作数不能都指向内存位置
        • movq只能以表示32位的补码数字的立即数作为源操作数,
          然后把这个值符号扩展为64位的值, 放到目的寄存器
        • 立即数不能做目的操作数
    • 3.4.4 压入和弹出栈数据
      • 寄存器%rsp:
        • 作用: 栈指针寄存器, 用来存放栈指针的值
  • 3.5 算术和逻辑操作

    • 3.5.1 加载有效地址(load effective address: leaq)
      • 作用: 将一个有效地址写入目的寄存器
        • 有效地址: 计算出来的地址
      • 目的操作数: 必须是寄存器
    • 3.5.2 一元和二元操作
      • 一元操作: 只有一个操作数, 既是源又是目的.
        这个操作数可以是一个寄存器或者内存地址
      • 二元操作: 其中第二个操作数既是源又是目的,
        第一个操作数可以是立即数/寄存器/内存位置.
        第二个操作数是寄存器或内存地址

        • 注意: 当第二个操作数是内存地址时,
          处理器必须从内存读出值, 执行操作, 再把结果写回内存
    • 3.5.5 特殊的算术操作

      • imulq:

        • 一般用法:

        imulq   %rdx, %rcx
        
        • 特殊用法:

        imulq   %rdx     //有符号乘法
        mulq   %rdx     //无符号乘法
        
          - 作用: 计算两个64位值的全128位乘积
          - 注意点: 要求一个参数必须在寄存器%rax中, 而另一个作为指令的操作源给出. 然后乘积存放在寄存器%rdx(高64位)和%rax(低64位)中
        
  • 3.6 控制
    • 3.6.1 条件码
      • 常用条件码:
        • CF(Carry Flag): 进位标志
        • ZF(Zero Flag): 零标志
        • SF(Sign Flag): 符号标志
        • OF(Overflow Flag): 溢出标志
      • CMP:
        cmp系列指令会比较两个操作数并设置条件码,而不改变目的寄存器
      • 条件码的改变:
        • 绝大部分指令的执行都会设置条件码
        • lea系列指令不改变条件码
          • 原因: lea系列是用来进行地址计算的
    • 3.6 2 访问条件码
      • SET: set系列指令可以根据条件码的某种组合,
        将一个字节设置为0或1
      • 溢出:
        • 负溢出:
          当计算结果本应该是负数但寄存器中却存放的是正数时为负溢出
        • 正溢出:
          当计算结果本应该是正数但寄存器中却存放的是负数时为正溢出
        • 详见2.3.2 补码加法
    • 3.6.4 跳转指令的编码
      • 汇编: 将汇编代码转化成机器码
      • 反汇编: 将机器码转化成汇编代码
      • 理解跳转指令目标的如何编码, 对第7章研究链接非常重要
        • 汇编代码中: 跳转目标用符号标号书写
        • 汇编器, 以及后来的链接器, 会产生跳转目标的适当编码
          • 跳转指令有几种编码, 通常使用PC相对寻址(PC-relative)
            • PC-relative:
              会将目标指令的地址与紧跟在跳转指令后面的那条指令的地址之间的差作为编码

              • – 优点:
                1. 使用PC-relative时,
                当使用链接器将这些代码重新定位时,
                跳转目标的编码并没有改变
                2. 指令编码很简洁
                3. 目标代码可以不做改变的移动到内存的不同位置
            • “绝对”地址: 用4个字节直接指定目标

《汇编语言程序设计》(

在清华计算机系,汇编语言程序设计通常作为本科生接触到的第一门计算机系统课程,被定位为该系列的入门课,起到“承上启下”的作用。主要的授课内容包括:汇编语言与计算机系统结构、指令集初步、数制与整数表示、浮点数表示;80×86计算机组织与保护模式、X86指令系统与寻址方式、C与X86汇编、X86汇编编程;MIPS汇编。课程强调汇编语言的软硬件分界与桥梁作用,使得学习者能把程序的执行与计算机的工作过程紧密联系起来,以便深入地感知、理解和体会计算机的逻辑功能以及各种软件系统的原理,逐步形成软件系统功能构筑在其上,硬件系统功能运行于其下的计算机系统思维能力。与以往的讲法不同,本课程突出了“承上启下”这一理念,在内容编排上进一步突出了与相关课程的衔接,尤其是与C语言编程、编译原理、组成原理的衔接。比如说,强化与高级语言的联系,从典型的C语言代码段入手,通过编译成汇编代码来详细解释程序员角度的X86结构运行模型。掌握这两种语言的对应可以将程序的执行与计算机的工作过程紧密联系起来,直接体现汇编语言本身固有的特点,即它是最易于将“程序”和“机器”统一起来的一个结合点。进一步的通过对不同汇编代码的解释来给出微体系结构方面的差异。比如,同一段C代码通过不同的编译器/编译器开关所生成的代码是不一样的,为什么不一样?这就可以通过处理器微体系结构的差异来简单解释。这种做法可以为后续课程,如编译原理、计算机组成原理等提供一些先导知识,并有利于学生从整个系统构成的角度来理解各个课程的作用与位置。加入MIPS汇编(包括部分体系结构的内容),为后续的以MIPS为核心的计算机组成原理、编译原理、操作系统等专业课程奠定MIPS汇编语言的基础。

文字填空题

请写出ISA这个缩写的全名(单词首字母大写,单词间以”/”间隔)答案:=
Instruction/Set/Architecture

单选题

只有LOAD和STORE指令可以访问存储器的指令系统属于RISC还是CISC?

  • RISC
  • CISC

分析:这是RISC和CISC指令集的重要区别。

单选题

X86指令系统属于RISC还是CISC?

  • CISC
  • RISC

单选题

X86指令至多只有一个操作数在()中。

  • 内存
  • 寄存器

分析:而MIPS32指令的操作数必须都在寄存器中。

单选题

X86处理器的存储字节序是()。

  • 小端
  • 大端

分析:小端表示即所谓“低对低,高对高”(高位有效数字存在内存的高位中)。X86的字节序为小端,ARM、MIPS和IA64的字节序可配置,网络传输一般采取大端序。详见

文字填空题

已知某32位整数X,其值为-101,则其16进制补码为(),另一32位整数Y的补码为0xFFFFFF6A,则X+Y的16进制补码,X-Y的16进制补码为()。(本题一共三个空,十六进制表示示例:0xFFFFFFFF
注意开头与字母大小写。答案之间以‘/‘符号隔开)答案:0xFFFFFF9B/0xFFFFFF05/0x00000031分析:正数的补码与原码相等,负数的补码等于原码取反+1。

永利集团304com 1

(其实我这道题一直没有通过,但我觉得计算结果是对的)

判断题

以下几道判断题都与本题条件相同。已知x、y为int类型; unsigned int ux = x;
unsigned int uy = y.判断以下等式是否成立?==

  • 正确
  • 错误

分析:若y=-2147483648,则-y=-2147483648,等式不成立。

判断题

>>31 == -1

  • 正确
  • 错误

分析:取x=0,显然原式是错的。不过,当x不等于0时,原式是正确的,因为x和-x中至少有一个是负数,则的最高位必然为1,算术右移31位后,就全是1了。

判断题

¬x+¬y == ¬

  • 正确
  • 错误

分析:随便举个例子就会发现这是错的。

判断题

== –

  • 正确
  • 错误

分析:可以这样思考:无符号整数和带符号整数的内部表示形式和运算规则都是一样的,区别只在于解释的方法。

数值填空题

单精度浮点数的exp域的位宽是()位?答案:8

数值填空题

单精度浮点数的frac域位宽是()位。答案:23

判断题

已知 int x = …; float f = …; double d = …;且d 与 f 都不是
NaN。判断以下关系式是否成立?x == x

  • 正确
  • 错误

分析:float的frac域宽度不够,可能会有精度损失。

永利集团304com,判断题

条件同上题x == x

  • 正确
  • 错误

分析:double的frac域足够放下int,不会有精度损失。

判断题

f == f

  • 正确
  • 错误

分析:float转换成double不会有精度损失。

判断题

d == d

  • 正确
  • 错误

分析:double转换成float可能会有精度损失。

判断题

f == –

  • 正确
  • 错误

分析:浮点数取负只改变符号位,不会溢出。

判断题

2/3 == 2/3.0

  • 正确
  • 错误

分析:2/3的结果是整数,但2/3.0的结果是浮点数。

判断题

(d <0.0) == <0.0)

  • 正确
  • 错误

分析:浮点数的下溢是逐步下溢,不像整数会从负数变成正数。

判断题

== (-f > -d)

  • 正确
  • 错误

分析:浮点数取负不会溢出。

判断题

-d == f

  • 正确
  • 错误

分析:d+f可能会溢出,损失精度。

发表评论

电子邮件地址不会被公开。 必填项已用*标注