程序的机器级表示 - 访问数据
C语言与汇编语言的数据格式对比
因为是从16位体系扩展到32位又扩展到64位,所以Inter用word表示16位数据类型,以此类推32位是double word(long word),64位是quad word,所以在汇编语言中,q代表四字
以下是x86-64中数据格式
C声明 Intel数据类型 汇编代码后缀 大小(字节)
char 字节 b 1
short 字 w 2
int 双字 l 4
long 四字 q 8
char* 四字 q 8
float 单精度 s 4
double 双精度 l 8
访问信息
一个x86-64CPU中包含16个通用的64位寄存器,这些寄存器可以存储整数数据和指针。这些寄存器一般以%r开头,后面跟着其他的名字,这些名字一般标志着其用途,具体的用途会在其他文章中介绍。
操作数
operand(操作数)用来表示一个指令中要使用的源数据的值与放置结果的目的位置。在操作数大致分为三类:
立即数 在ATT格式的汇编代码中用
$
与一个标准的C整数组合表示,比如$-1
寄存器的内容 可以是1字节,2字节,四字节或8字节,用ra表示
内存的引用 用Mb[Addr]表示,b表示字节数
为了访问这三类操作数,所以有三种寻址模式:
立即数 格式:$Imm 操作数值:Imm
寄存器 格式:ra 操作数值:R[ra]
内存 格式:Imm(rb ,ri,s ),其中Imm立即数偏移,rb基址寄存器,ri变址寄存器,s比例因子,在这些中s必须是`1、2、4或8,操作数值:M[Imm+rb +ri * s]
数据传送指令
最常做的操作就是将数据从一个位置复制到另一个位置,在汇编语言中,这样的数据传送指令有很多,比如mov等。
mov指令系列
mov系列指令是最简单的数据传送指令,它只是将数据不做任何改变的从源位置复制到目的位置。其格式类似为mov S,D
,在mov后接一个字符代表操作的数据长度,比如movb传送一个字节,movl传送双字节等,有几点需要注意:
S源位置的值 可以是立即数、寄存器中的值i或内存地址中的值,而D目的位置只能是寄存器或内存中的地址,不能是立即数
在x86-64中,S和D不能同时为内存中的地址
movl(传送双字)如果目的地址位寄存器,会将该寄存器的高32位设置为0
movz、movs指令系列
这两类的指令都是在将较小的源值复制到较大的目的时使用,其源可以是内存或寄存器,目的只能是寄存器。并且每条指令最后都有两个字符,一个字符代表源大小(只有1,2字节),一个字符代表目的大小(2,4字),比如movzbl,movsbl
movz指令在复制时将目的的剩余位置用0填充。其格式类似为movz S,D
,比如movzbl。
movs指令在复制时将目的的剩余位置用符号位填充。其格式类似为movz S,D
。
cltq指令只作用于eax和rax,其功能是将eax符号扩展到rax
入栈出栈操作
在编程中栈是非常有用的一种数据结构,在程序调用过程中栈也是非常有用的。汇编中有直接对栈的操作:
pushq S
将四字压入栈 其效果是R[%rsp]<-R[%rsp]-8,M[R[%rsp]]<-S
popq D
将四字从栈中弹出 其效果是D<-M[R[%rsp]],R[%rsp]<-R[%rsp]+8
所以pushq %rbp等价于
同理popq %rax等价于
参考资料
版权声明: 本文为 InfoQ 作者【引花眠】的原创文章。
原文链接:【http://xie.infoq.cn/article/91eb902be62c6248a3fb91131】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论