首页 > 编程语言 >深入理解计算机系统(第3章 程序的机器级表示②)

深入理解计算机系统(第3章 程序的机器级表示②)

时间:2022-10-01 10:23:13浏览次数:82  
标签:计算机系统 操作数 机器 3.4 指令 深入 内存 寄存器 64

目录

3.3 数据格式

由于是从16位体系结构扩展成32位的,Intel用术语“字(word)”表示16位数据类型。因此,称32位数为“双字(double words/long word)”,称64位数为“四字(quad words)”。
image
大多数GCC生成的汇编代码指令都有一个字符的后缀(b/w/l/q),表明操作数的大小。

注意:汇编代码同时使用后缀'l'来表示4字节整数和8字节双精度浮点数。这不会产生歧义,因为浮点数使用的是一组完全不同的指令和寄存器。

3.4 访问信息

一个x86-64的中央处理单元(CPU)包含一组16个存储64位值的通用目的寄存器,用来存储整数数据和指针。
image

指令集的历史演化造成了不同的命名规则:最初的8086中有8个16位寄存器(%ax~%sp),每个寄存器都有特殊的用途。扩展到IA32架构时,寄存器扩展成32位寄存器(%eax~%esp)。扩展到x86-64后,原来的8个寄存器扩展成64位(%rax~%rsp),还增加了8个新的寄存器(%r8~%r15)。

两条规则:

  • 生成1字节和2字节数字的指令会保持剩下的字节不变。
  • 生成4字节数字的指令会把高位4个字节置为0。

%rsp是栈顶指针,用来指明运行时栈的结束位置。(一般不在其它情况下使用)
注意参数的使用顺序:%rdi->%rsi->%rdx->%rcx。
返回值存入%rax中。

3.4.1 操作数指示符

大多数指令有一个或多个操作数(operand),指示出执行一个操作中要使用的源数据值,以及放置结果的目的位置。有以下三种类型:

  • 立即数(immediate),表示常数值。书写方式:'$'后面跟一个用标准C表示法表示的整数。(不同指令允许的立即数值范围不同,汇编器会自动选择最紧凑的方式进行数值编码。)
  • 寄存器(register),表示某个寄存器的内容。书写方式:用符号\(r_a\)表示任意寄存器\(a\),用引用\(R[r_a]\)来表示它的值。(这是将寄存器集合看成一个数组R,用寄存器标识符作为索引。)
  • 内存(memory)引用,根据计算出来的有效地址访问某个内存位置。书写方式:用符号\(M_{b}[Addr]\)表示对存储在内存中从地址\(Addr\)开始的\(b\)个字节值的引用,通常省去下标\(b\)。(同样将内存看成一个很大的字节数组。)

如下图所示,有多种不同的寻址模式,允许不同形式的内存引用。
\(Imm(r_b, r_i, s)\)是最常用的表示形式,有四个部分:一个立即数偏移\(Imm\),一个基址寄存器\(r_b\),一个变址寄存器\(r_i\)和一个比例因子\(s\)(1/2/4/8)。有效地址被计算为\(Imm+R[r_b]+R[r_i]·s\)。
image
image

3.4.2 数据传送指令

将数据从一个位置复制到另一个位置。

MOV类

把数据从源位置复制到目的位置。
image

常规的movq指令只能以表示为32位补码数字的立即数作为源操作数,然后把这个值符号扩展得到64位的值并放到目的位置,movabsq指令能够以任意64位立即数值作为源操作数,并且只能以寄存器作为目的。

MOVZ类

把目的中剩余的字节填充为0。
image

MOVS类

通过符号扩展填充,把源操作数的最高位进行复制。
image

cltq没有操作数,效果与movslq %eax, %rax完全一致,不过编码更紧凑。

x86-64采用的规则:

  • 规则1:任何为寄存器生成32位值的指令都会把该寄存器的高位置0。
  • 规则2:传送指令的两个操作数不能都指向内存位置。将一个值从内存位置复制到另一个内存位置需要两条指令。
    image

3.4.3 数据传送示例

image

image

image

image

image

image

image

image

C语言中所谓的“指针”其实就是地址。间接引用指针就是将该指针放在一个寄存器中,然后在内存引用中使用这个寄存器。

像t0、t1这样的局部变量通常是保存在寄存器中,而不是内存中。

3.4.4 压入和弹出栈数据

有关栈ADT的描述可参考文章数据结构与算法分析——C语言描述(第3章 表、栈和队列②)https://www.cnblogs.com/kirin-dev/p/Data-Structures_Chapter-3-2.html
image

pushq和popq指令都只有一个操作数——压入的数据源和弹出的数据目的。

指令pushq %rax等价于下面两条指令(将栈指针减8,再将值写到新的栈顶地址):
subq $8, %rsp
movq %rax, (%rsp)

同理,指令popq %rdx等价于:
movq (%rsp), %rdx
addq $8, %rsp

image
在x86-64中,程序栈存放在内存中的某个区域。如上图所示,栈向下增长,栈顶元素的地址是所有栈中元素地址中最低的。(根据惯例,这里的栈是倒过来画的,栈“顶”在图的底部。)栈指针%rsp保存栈顶元素的地址。

因为栈和程序代码以及其他形式的程序数据都存放再同一内存中,所以程序可以用标准的内存寻址方法访问站内的任意位置。
eg:movq 8(%rsp), %rdx将第二个四字从栈中复制到寄存器%rdx。

标签:计算机系统,操作数,机器,3.4,指令,深入,内存,寄存器,64
From: https://www.cnblogs.com/kirin-dev/p/Computer-Systems_Chapter-3-2.html

相关文章