吾读 - 《深入理解计算机系统》 第三章 程序的机器级表示 (一) 寄存器初步认识

3.2 程序编码

第一章已经介绍过代码如何编译成可执行程序的几个步骤,最终的可执行程序是二进制的,那么系统是怎么读这些二进制的呢?

3.2.1 机器级代码

能够理解汇编代码以及它是如何与原始的C代码相对应的,是理解计算机如何执行程序的关键一步。

基本概念:

  • 程序计数器 成为%eip,表示将要执行的下一条指令在存储器中的地址。
  • 整数寄存器有8个,可以存储32位的值。
  • 条件码寄存器保存着最近执行的算术指令的状态信息,用来实现条件控制。
  • 浮点寄存器也有8个。

到了汇编这一层,已经不区分有符号和无符号,各种数据结构在汇编代码中只是连续的字节。

程序存储器包含程序的目标代码,使用虚拟地址寻址。又操作系统转换成最终实际的存储器物理地址。

各种缓存、主存、显存,共同构成了一个连续的虚拟地址空间。

3.2.2 代码示例

本书以GCC为例分析编译的结果。

GCC使用自己的格式来产生汇编代码,这种格式被称为GAS(Gnu ASsembler,GNU汇编器)。

使用 gcc -O2 -S test.c 可以生产test.s汇编文件
使用 gcc -O2 -c test.c 可以产生test.o文件
使用 objdump -d test.o 可以看到一些汇编内容。 
objdump也就是反汇编器,可以将二进制一定程度上还原为汇编代码。

反汇编之后的特性:

  • IA32的指令长度1到15字节不等,指令编码被设计为常用的指令就比较短,不常用的就比较长

    这个设计方法好啊,开发中的一些功能函数常常也如此设计。频繁使用的函数尽量减少参数数量。

  • 反汇编器仅根据字节序列来确定汇编代码,无需访问原始代码或者汇编。

  • 反汇编器使用的指令名称跟GAS略有不同,例如,省去很多指令结尾的“l”后缀。

GCC产生的汇编代码中有一些.开头的行,这些事指导汇编器和链接器的命令,可以忽略不管。例如:

	.file	"sum.c"
	.globl	_accum
	.bss
	.align 4

汇编代码解释:

// 源代码
int simple(int *xp, int y)
{
   
	int t = *xp + y;
	*xp = t;
	return t;
}    
// 使用gcc -S 生成的代码段如下
simple:
  pushl %ebp        保存帧指针
  movl %esp,%ebp    创建新的帧指针
  movl 8(%ebp),%eax   获取xp
  mov1 (%eax),%edx    获取*xp
  addl 12(%ebp),%edx  把y加到t上
  movl %edx,(%eax)    把t赋值给*xp
  mov1 %edx,%eax      设置t为返回值
  movl %ebp,%esp      重置栈指针
  pop1 %ebp           重置帧指针
  ret

之前看过一点点汇编语言,在那本书上 ,例如 mov ax,10 表示把ax寄存器设为10 ,就是说第一参数作为目标寄存器。而GAS这边是反的,第二个参数(如果有)才是目标寄存器。 比如 movl %esp,%ebp 表示的是把esp里面的内容赋值给 ebp。

3.3 数据格式

GAS很多指令后面会有一个后缀,例如前面出现的l,这个是小写的L,不是数字1 。

在这里插入图片描述

如图所示,GAS中每个操作符都有一个后缀,用来表明操作数的大小。例如mov就有 movb movw movl等。movel既可以表示4字节整数,也可以表示8字节浮点,这不会产生歧义,因为浮点数使用独立的一组寄存器。

3.4 访问信息

以IA32为例,CPU包含8个32位寄存器。大多数情况下,前六个寄存器都可以看成是通用的寄存器。少数情况下,特定指令会使用特定的寄存器。最后两个寄存器ebp和esp,保存着程序栈的指针,不可随意使用。寄存器的布局如下:(其中前四个寄存器还可以通过ah al等方位低位的两个字节,这是为了兼容早起8086等早起处理器)

在这里插入图片描述

寄存器其实也没什么神秘的,就是一些放数据的地方,只不过位置特殊,在cpu上,所以就是访问特别快。

3.4.1 操作数指示符

一个典型的指令,有一个或多个操作数,就如同函数有一个或多个参数一样。这些操作数的作用是指出源数据的位置,和结果存储的位置。

好比一个C函数 void move(int src, int dest); 把src的值赋给dest,这也就是 movl xxx,xxx 的作用。

而这个源数据怎么得到呢?有下面三种方式:

  1. 立即数。以$ 开头就是直接给出,无需去内存中查找。例如$0x123
  2. 寄存器。%加寄存器的名称形式。例如 %eax,%esp。以 E a E_a
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值