概述
目录
程序的机器级表示:
程序编码:
数据格式:
访问信息
寄存器:
操作数:
数据传送指令:
数据传送示例
导入和弹出栈数据:
算术和逻辑操作:
加载有效地址(leaq):
一元和二元操作:
移位操作:
特殊的算术操作:
控制:
程序的机器级表示:
程序编码:
C语言 ---【预处理器】---> 扩展后的C ---【编译器】---> 汇编语言 ---【汇编器】---> 二进制目标文件 ---【链接器】---> 可执行文件
对于机器级编程的两种抽象:
- 指令集架构将程序的行为抽象成每条指令按顺序执行
- 内存模型抽象成非常大的字节数组
机器代码可见的处理器状态:
程序计数器、整数寄存器、条件码寄存器、向量寄存器
数据格式:
字表示16位,32位双字,64位四子,不同数据类型大小不同,汇编后缀也不同
64位机器里面一个指针8个字节
访问信息
寄存器:
一个X86-64的cpu包含一组16个存储64位值的通用目的寄存器:
- 部分指令会在寄存器中生成小于8个字节的指令,生成1个字节、2个字节的指令会保持剩下的字节不变,生成4字节数字的指令会把高位4个字节置为0。
操作数:
一个指令有>=1个操作数.
三种类型:立即数、寄存器、内存引用
- 寄存器用类似数组的R[r]来表示,寄存器名就是索引,R[r]表示寄存器存储的值
- %rax是表示寄存器里存的值0x100,(%rax)表示内存里0x100位置处的值。
- 64位机器里不能用32位寄存器来寻址:(%ebx)非法
数据传送指令:
MOV S,D
前面是源操作数:立即数,寄存器里的值,内存里的值
源操作数表示的是值,如果源操作数为%rax,表示寄存器里的值,如果源操作数为(%rax),表示间接寻址内存里的值
后面是目标操作数:寄存器、内存地址
后面是存储数据的位置,如果目标操作数为%rax,表示放到寄存器里,如果源操作数为(%rax),表示放到间接寻址后的内存地址里。
- Movb, movw, movl, movq表示对于操作数大小不同
- 不能将内存里的值直接传送到内存:mov (%rax),(%rbx) (非法)
- 一般情况下只会更新目的操作数指定的寄存器,唯一例外是movl,会把高位四字节记成0。见寄存器部分
- movq和movabsq区别,前者只能移动32位补码数字,然后符号扩展到64位的值,后者可以以任意64位立即数作为源操作数,并且目标只能是寄存器
MOVZ S,R
小移动到大时,零扩展
转存失败重新上传取消
按照b,w,l,q应该有四个,为啥没有movlq,因为movlq的含义和movl的含义是一样的。
MOVS S,R
小移动到大时,符号扩展,高位由源操作数第一位复制得到
cltq的含义: movslq %eax, %rax
为啥都只考虑小移动到大,大会不会移动到小呢?
如果目标是内存地址,应该会以此地址为起始,往后存储,所以不存在源操作数过大
如果目前是寄存器呢,64位操作数移动到32位寄存器会发生什么?应该是低32位存储
数据传送示例
转存失败重新上传取消
这段从C到汇编的转换,帮助我们理解了指针是什么:
- 指针在64位机器中,占8个字节,指针其实就是地址。
- 指针变量在右边时,意思是指针指向的内存里的值,-> 对应于MOV指令中的源操作数,我们对(%rax)的理解
- 指针变量在右边时。意思是指针指向的内存。-> 对应于MOV指令中的目标操作数,我们对(%rax)的理解
- 在上图汇编中,把指针存在寄存器rdi里,2,3两点可以解释c语言和翻译成汇编后的含义是一致的
5、局部变量通常放在寄存器中,而不是内存,访问寄存器比内存快得多
转存失败重新上传取消
转存失败重新上传取消
再通过这个例子,我们可以认识一下&取址操作。&a的含义是取值为4的a变量他在内存中的地址。
导入和弹出栈数据:
栈是什么?栈不是什么神奇的东西,也就是内存中的某个区域。
栈指针,始终指向栈顶位置,入栈时地址减小:
转存失败重新上传取消
1、pushq和popq都是可以用mov指令+计算指令替代的。区别在于前两个指令大小只有1个字节。
2、栈可以同样当做内存来处理:movq 8(%rsp), %rdx会将第二个四字从栈中复制到寄存器rdx,为什么是第二个四字?8(%rsp)操作数值为M[R[%rsp] + 8], 取的是栈顶上方8-15个字节,即第二个四字。
算术和逻辑操作:
转存失败重新上传取消
加载有效地址(leaq):
- 源是内存地址(看上去是),目标是寄存器
- 和movq的区别:
Movq (%rdx) %rax 将M[R[rdx]]的值赋给rax
Leaq (%rdx) %rax 将R[rdx]的值赋给rax
- 由于这种特性,往往用于普通的算术操作:long t = x + 4y +12z
一元和二元操作:
转存失败重新上传取消
- 一元操作:
只有一个操作数,这个操作数必须是寄存器或者内存(也就是必须是个地址)
表示的含义是:把这个寄存器或者内存的值中,再放入这个寄存器或者内存中
- 二元操作:两个操作数,第一个操作数是源,可以是寄存器或者内存、立即数,这个操作数必须是寄存器或者内存(也就是必须是个地址)
表示的含义是:把这个寄存器或者内存的值中取出,和源操作数做计算,再放入这个寄存器或者内存中
移位操作:
- 第一个数是移位量,第二个是目标操作数
表示的含义是:目标操作数的值经过移位处理后,放回目标操作数位置
- 移位量时立即数或者单字节寄存器cl
- 当移位量为cl时的移位规则是:对w位长的数据值进行操作,移位量由cl寄存器的低m位组成,2^m-1=w
- 左移指令SAL和SHL相同,右边补0
- 右移质量SAR执行算术右移(填符号位),SLR执行逻辑右移(填0)
特殊的算术操作:
转存失败重新上传取消
此图的idivq和divq的寄存器有误,看原书第三版:
imulq的两种形式:
- 二元操作:将两个64位相乘得到一个64位数,此时,仅用imulq一个操作可以同时实现有符号数和无符号数的乘法:截断后的补码的位级行为是一样的
- 如上图中,只有一个操作数,将两个64位相乘得到一个128位数,分别放在两个寄存器中
控制:
除了整数寄存器,CPU还维护着一组单个位的访问条件码寄存器:他们记录了算术或逻辑操作的属性,我们检测这些寄存器的值,就可以判断条件的真假,就是这么神奇
转存失败重新上传取消
举例而言,当我们执行一个ADD指令完成 t = a + b这个C表达式时,各个条件码寄存器都会发生变化:
转存失败重新上传取消
ZF和SF很好理解,但是CF、OF是什么意思呢,我们可以举例说明:
CF可以使用反证法:如果没有无符号溢出,t必然大于a,反之亦然
OF:有符号数加法溢出,a和b必然符号不同,所以有(a<0 == b<0), 同时如果没有溢出,t必然和a、b符号相同。
转存失败重新上传取消
最后
以上就是简单绿茶为你收集整理的CSAPP第三章程序的机器级表示程序的机器级表示:的全部内容,希望文章能够帮你解决CSAPP第三章程序的机器级表示程序的机器级表示:所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复