深入理解计算机系统第三章理解和习题解析之数据格式和mov指令

文章目录

  • 关于本文的说明
  • 写在前面
  • 数据格式
  • mov指令
    • 关于操作数指示符的理解
    • mov后缀b、w、l、q的确定方法总结
    • mov中的数据转换

关于本文的说明

本文主要记录的是本人对于《深入理解计算机系统》一书中第三章部分章节个人理解和总结分析,其中包括:

1. 数据格式:对应书中3.3节
2. mov指令的理解:对应书中3.4.1、3.4.2、3.4.3 这几节内容

写在前面

  最近华为被美国禁令,前段时间中兴也被断了芯片,深感核心技术的重要性。虽然中国人多,人才多,缺钱,这几样因素整合起来让我们觉得这些外界的禁令都不成问题,只要政府政策稍加倾斜,投入人力财力物力去做相关研发,能出产品,能出成绩。但是,我还是认为,任何技术的基础部分,那些基本功东西,仍然是重要的,可能它无趣,它不出成果,客户不买你的账,但是那是一切高楼的基础。比如在程序开发行业,现在都不用汇编了,都有python、js、perl、底层点的C++,api做的即稳定有好用,那么多社区论坛,不会问百度,资源又多又方便,谁还在乎你知不知道程序是怎么编译的,可是好多这些重要的框架、库函数都是老外发明的,不知道它是怎么堆起来的用着用着就心里发虚,一个是硬性的条件哪天被禁用了,像现在一样,一个是出了问题,稀奇古怪的,都无从下手,只能放到网上搜索,一旦找不到方案就完了。
  所以翻出以前买的《深入理解计算机系统》,准备有空时补下基础知识,也许现在已经太迟了,或者看书很慢,也看不见成效,但是还是决定看下去,就当是出于热爱吧。
  为了记录看书的心得,写了博客,也欢迎各位指正讨论。

数据格式

  图3-1和图2-3两张表格记录下来,对比看即可,个人认为后者是前者的更详细部分,主要扩展部分是添加了符号和32位和64位对比。后面实例和题目主要还是基于64位,因为说明是x86-64了,但是关于符号的扩展还是需要留意。
深入理解计算机系统第三章理解和习题解析之数据格式和mov指令_第1张图片

深入理解计算机系统第三章理解和习题解析之数据格式和mov指令_第2张图片

mov指令

关于操作数指示符的理解

操作数指示出一个操作中要使用的源数据值放置结果的目的位置

原数据值:这是一个,如果是立即数则代表这个数本身,如果是寄存器或者内存地址则代表寄存器或内存地址中存放的值

目的地址:这是一个位置寄存器或者内存地址就是它本身

接着下面讲mov指令,比如

mov %rsi,%rax

  一开始我搞不清楚,这里哪个指示的是值,哪个指示位置,依据什么来判断。后来重新回来看3.4.1节,第一句话,我终于明白,第一个参数是值,第二个参数是位置,上面的指令意思是把%rsi寄存器中的值取出来放到%rax的位置中。
  仔细想想也有道理,我们是知道源数据值和目标位置的。所以系统设定是寄存器放在第一个参数代表取其中值,放在第二个参数代表这个寄存器本身。

源:数值,有以下几种类型:

  • 立即数:取这个数本身作为源操作数值
  • 寄存器:取这个寄存器中存储的值作为源操作数值
  • 内存地址:取这个内存地址中存储的值作为源操作数值

目的地址:地址 有以下几种类型:

  • 寄存器:寄存器是目的地址
  • 内存地址:内存地址是目的地址

下面举几个例子:

寄存器
%rdi 0x001
%rsi 0x002
内存地址
0x001 30
0x002 40
mov %rdi,%rsi

该指令将寄存器%rdi中的值放到寄存器%rsi中,执行完成后寄存器内容如下:

寄存器
%rdi 0x001
%rsi 0x001
mov (%rdi),%rsi

该指令将%rdi值0x001指示的内存地址中的值放到寄存器%rsi中,执行完成后寄存器内容如下:

寄存器
%rdi 0x001
%rsi 30

mov后缀b、w、l、q的确定方法总结

这个问题曾经困扰我很久,因为不知道到底该通过什么来确定使用哪个后缀,习题3.2就是关于这方面的知识。

后来查看书中的实例后个人总结如下
因为源包括:立即数、寄存器、内存地址,目的地址包括:寄存器和内存地址两种,所以应该有3*2=6种组合方案,由于不能出现源和目的地址都是内存地址的情况,所以只有6-1=5种可能的组合方案,我们将其归纳如下:

目的地址 确定后缀
立即数 寄存器 根据寄存器确定后缀
立即数 内存地址 根据立即数大小确定后缀
寄存器 寄存器 根据目的寄存器确定后缀
寄存器 内存地址 根据寄存器确定后缀
内存地址 寄存器 根据寄存器确定后缀

优先权总结

1. 如果源和目的都是寄存器,根据第二个参数也就是目的地址寄存器来确定
2. 有寄存器根据寄存器确定
3. 其次是立即数大小
4. 内存地址没有决定权

书中给出的示例验证
- movl $0x4050,%eax 表格总结第一种
- movw %bq,%sp 表格总结第三种
- movb (%rdi,%rcx),%al 表格总结第五种
- movb $-17,(%rsp) 表格总结第二种
- movq %rax,-12(%rbq) 表格总结第四种情况

依据以上的归纳总结,习题3.2均可以套用,并且可以解决习题3.3中第二个(找错误)和倒数两个。

习题3.3中第一个的错误之处在于:x86-64系统规定所有内存地址都必须用四字长的寄存器给出,而%ebx存储双字;
习题3.3中第三个的错误之处在于:两个操作数全部是内存地址;
习题3.3中第四个的错误之处在于:没有%sl寄存器;
习题3.3中第五个的错误之处在于:目的操作数只能是地址不能是立即数.

mov中的数据转换

这里除了上面的归纳总结以外,还需要牢记以下几点
1.movq指令只能以表示为32位补码数字的立即数作为源操作数,然后把这个值符号扩展得到64位的值,放到目的位置;
2.当涉及符号和大小都需要变化时,优先进行大小变化;
3.movl指令以寄存器作为目的时,它会把该寄存器的高位4字节设置为0.

习题3.4解析:
char-int:
源:char 有符号 1字节
目的:int 有符号 4字节

均为有符号,所以是有符号扩展 movs
从1字节到4字节,b-l 所以是movsbl
目的是四字节 所以取%rax的双字寄存器 %eax
所以第一个指令是movsbl (%rdi),%eax
第二个指令从%eax到(%rsi)寄存器到内存地址,以寄存器为准所以是movl

char-unsigned
源:char 有符号1字节
目的:unsigned 无符号4字节

一个有符号一个没有,但涉及字节大小变化,优先大小,所以第一条指令没有变化符号
按照原始的有符号movs,所以是movsbl
其他参考第一个。

unsigned char -long
源:unsigned char 无符号 1字节
目的:long 有符号 8字节

这个是最难理解。
我认为应该是:movzbq(%rdi),%rax movq %rax,(%rsi)原因如下:
涉及大小变化,优先大小,第一条指令使用原始无符号movz,从1字节到四字,所以是movzbq,然后使用%rax寄存器存储8字节,再使用movq移到目的寄存器。
但是答案却是于此不同,这点还没想明白。

int-char
源:int 有符号4字节
目的:char 有符号1字节

大小变小时,先找源大小的寄存器中存下,然后在从其中更低位寄存器中读取。
所以此处movl(%rdi),%eax 然后从%al中取

同样可以解释下一个

你可能感兴趣的:(计算机基础)