x86-64的算数和逻辑操作

前言

本篇文章介绍x86-64的算数和逻辑操作指令,主要包含下面几部分:

  • 加载有效地址指令
  • 一元操作指令
  • 二元操作指令
  • 移位指令
  • 特殊指令

加载有效地址指令

加载有效地址指令的指令名称为leaq(load effective address quad),从这个名称就可以看出leaq的特点:

  1. 该指令的源操作数是一个内存引用,但是不是指的内存引用在内存中的值,而是内存引用本身这个地址的值,这会让我们一下想到指针,也让我们一下子想到取地址符&。
  2. 该指令的目的操作数是一个四字的寄存器,为什么一定是四字呢,因为在x86-64的CPU中,一个内存地址就是用四字来表示的

更进一步,leaq指令还有一点很牛逼的就是,结合内存引用的计算方式
m e m A d d = I m m ( R b , R i , s ) mem Add= Imm(R_b,R_i,s) memAdd=Imm(Rb,Ri,s)
我们可以很方便的运行很多运算,我们实际举一个例子,下面是正经C代码

#include 
long scale(long x, long y, long z);
int main()
{
	int a = scale(10,11,12);
	return 0;
}

long scale(long x, long y, long z)
{
	long t = x + 4 * y + 12 * z;
	return t;
}

我们用gcc编译成汇编代码,不同的优化级别会生成不同的代码,比如使用默认的优化gcc -S test1.c -o test1.s,生成的部分代码如下:

	movq	%rdi, -24(%rbp)		# rdi就是x
	movq	%rsi, -32(%rbp)		# rsi就是y
	movq	%rdx, -40(%rbp)		# rdx就是z
	movq	-32(%rbp), %rax		
	leaq	0(,%rax,4), %rdx	# 4 * y
	movq	-24(%rbp), %rax
	leaq	(%rdx,%rax), %rcx	# x + 4 * y
	movq	-40(%rbp), %rdx
	movq	%rdx, %rax
	addq	%rax, %rax		# 2 * z
	addq	%rdx, %rax		# 2 * z + z = 3 * z
	salq	$2, %rax		# (3 * z) * 4 = 12 * z
	addq	%rcx, %rax		# x + 4 * y + 12 * z

经过-O3优化后gcc -S test1.c -o test1.s -O3的代码如下:

	# rdi就是x 
	# rsi就是y 
	# rdx就是z
	leaq	(%rdi,%rsi,4), %rax	# x + 4 * y
	leaq	(%rdx,%rdx,2), %rdx	# z + 2 * z = 3 * z
	leaq	(%rax,%rdx,4), %rax	# x + 4 * y + (3 * z)*4

这玩意真是个天才的设计

一元操作指令

一元操作指令有四个:
INC D:D = D +1
DEC D:D = D -1
NEG D:D = -D 数值取反
NOT D:按位取反
D既可以是一个寄存器,也可以是一个内存引用

二元操作指令

二元操作指令有六个:
ADD S, D:D = D + S
SUB S, D:D = D - S
IMUL S, D:D = D * S
XOR S, D:D = D ^ S
OR S, D:D = D | S
AND S, D:D = D & S
D既可以是一个寄存器,也可以是一个内存引用
S可以是一个立即数,寄存器或者内存引用

移位指令

移位指令有四个:
SAL k, D:全称(Shift Arithmetic(算术) Left),D向左移动k位
SHL k, D:全称(Shift Logical(逻辑) Left),D向左移动k位
SAR k, D:全称(Shift Arithmetic(算术) Right),D向右移动k位,左侧的位用符号位补齐
SHR k, D:全称(Shift Logical(逻辑) Right),D向右移动k位,左侧的位用0补齐

注意:
k可以是一个立即数,或者是寄存器cl,只能是这个寄存器,并且按理说cl有八位,最多可以移位255。但是实际不是这样,移位操作对 w w w位长的数据值进行操作,移位量是由寄存器cl的低m位决定的,这里 2 m = w 2^m = w 2m=w 。高位会被忽略

特殊指令

单操作数乘法

imulq S:计算 S * %rax的值,S和%rax都作为有符号数处理,结果高64位存储在寄存器rdx中,低64位存储在寄存器rax中

mulq S:计算 S * %rax的值,S和%rax都作为无符号数处理,结果高64位存储在寄存器rdx中,低64位存储在寄存器rax中

idivq S:寄存器rdx(高64位)和rax(低64位)中的128位数作为有符号被除数,S作为有符号除数,结果余数存储在寄存器rdx中,商存储在寄存器rax中

divq S:寄存器rdx(高64位)和rax(低64位)中的128位数作为无符号被除数,S作为无符号除数,结果余数存储在寄存器rdx中,商存储在寄存器rax中

clto将寄存器rax的值以符号位扩展到寄存器rdx和rax的128位中

你可能感兴趣的:(程序设计-汇编语言,汇编)