09-11-2016
传送指令
简单的数据传送指令
指令 | 效果 | 全称 | 描述 |
---|---|---|---|
MOV S,D | D←S | 传送 | |
movb | move byte | 传送字节 | |
movw | move word | 传送字 | |
movl | move long word | 传送双字 | |
movq | move quadword | 传送四字 | |
movadsq I,R | R←I | move abs quadword | 传送绝对的四字 |
※MOV指令只会更新目的操作数指定的那些寄存器字节或内存位置,但是movl指令以寄存器作为目的时,会把该寄存器高位4字节也设置为0.造成这个特殊性的原因时x86-64采用的惯例,即任何为寄存器生产32位值的指令都会把该寄存器的高位部分置0。
零扩展数据传送指令
指令 | 效果 | 全称 | 描述 |
---|---|---|---|
MOVZ S,R | R←零扩展(S) | 以零扩展进行传送 | |
movzbw | move zero extend byte to word | 将做了零扩展的字节传送到字 | |
movzbl | move zero extend byte to long word | 将做了零扩展的字节传送到双字 | |
movzwl | move zero extend word to long word | 将做了零扩展的字传送到双字 | |
movzbq | move zero extend byte to quadword | 将做了零扩展的字节传送到四字 | |
movzwq | move zero extend word to quadword | 将做了零扩展的字传送到四字 |
我们发现这里没有movzlq,原因参考上一节※处movl的解释。同理当我们在c代码中把unsigned char或者unsigned short类型赋值给unsigned long应当使用movzbq或movzwq指令,但是生产的汇编代码却是movzbl或movzwl。
unsigned long btl(unsigned char b) {
unsigned long result = b;
return result;
}
unsigned long wtl(unsigned short b) {
unsigned long result = b;
return result;
}
btl:
movzwl %dil, %eax
ret
wtl:
movzwl %di, %eax
ret
符号扩展传送指令
指令 | 效果 | 全称 | 描述 |
---|---|---|---|
MOVS S,R | R←符号扩展(S) | 传送符号扩展的字节 | |
movsbw | move sign extend byte to word | 将做了符号扩展的字节传送到字 | |
movsbl | move sign extend byte to long word | 将做了符号扩展的字节传送到双字 | |
movswl | move sign extend word to long word | 将做了符号扩展的字传送到双字 | |
movsbq | move sign extend byte to long quadword | 将做了符号扩展的字节传送到四字 | |
movswq | move sign extend word to long quadword | 将做了符号扩展的字传送到四字 | |
movslq | move sign extend long word to long quadword | 将做了符号扩展的双字传送到四字 | |
cltq | %rax←符号扩展(%eax) | convert long word to quadword | 把%eax符号扩展到%rax |
压入和弹出栈指令
指令 | 效果 | 全称 | 描述 | 解释 |
---|---|---|---|---|
pushq S | R[%rsp]←R[%rsp]-8; M[R[%rsp]]←S |
push quadword | 将四字压入栈 | 寄存器rsp的值-8,然后将S的值写入rsp寄存器指向的内存地址 |
popq D | D←M[R[%rsp]]; R[%rsp]←R[%rsp]+8 |
pop quadword | 将四字弹出栈 | 将rsp寄存之指向内存地址的值写入D,然后寄存器rsp的值+8 |
程序栈在程序启动后时固定大小的,我们可以看作一个桶一样,先进的数据会在栈底,内存地址值大,栈顶的值是最低的,所以push到栈时栈指针rsp寄存器的值需要-8.