天天看点

CSAPP第三章之算术指令

算术操作

一些指令类

每一个指令类都有各种不同大小操作数的变种(除

leaq

外)

指令 效果 描述
leaq S, D D<-&S 加载有效地址
INC D D<-D+1 加一
DEC D D<-D-1 减一
NEG D D<- -D 取负
NOT D 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
SAL k, D D<-D<<k 左移
SHL k, D D<-D<<k 左移,等同于SAL
SAR k, D D<-D>>Ak 算术右移
SHR k, D D<-D>>LK 逻辑右移(logic)
  • ATT格式的代码,操作数的顺序与一般的直觉相反

加载有效地址

leaq

其实是

movq

指令的变形

它根本没有引用内存,而是直接将有效地址写入目的操作数

目的操作数必须是寄存器

它还可以简洁地描述普通的算术操作。

例如,当

%rdx

值为x时,

leaq 7(%rdx,%rdx, 4), %rax

是设置寄存器

%rax

的值为5x+7(不理解)

一元操作与二元操作

一元操作:只有一个操作数,既是源也是目的

二元操作:第二个操作数既是源也是目的

移位操作

移位量可以是一个立即数,或者放在单字节寄存器

%cl

中——移位指令只允许使用该寄存器作为操作数

移位量由

%cl

的低位决定

左移指令有两个名字:

SAL

SHL

,两者相同

右移指令:

SAR

(算术移位)与

SHR

(逻辑移位)

移位操作的目的操作数可以是一个寄存器或者是一个内存位置

上述的大多数指令既可以用于有符号运算,也可以用于无符号运算

只有右移才有区分

通常,一个寄存器会存放多个值,还会在寄存器之间传送程序值

特殊的算术操作

两个64位的整数相乘需要128位来表示结果

乘除法分为有符号与无符号,例如

imul

idiv

一个特殊的指令:

cqto

:转换为8字(16字节)

imul

的两种形式:

  1. 64位乘64位->64位,同时实现无符号乘法与补码乘法
  2. 计算两个64位值的全128位乘积:

    mulq

    imulq

    。要求必须有一个参数在

    %rax

    种,另一个作为源操作数给出,结果放在

    %rdx

    (高64位)与

    %rax

    (低64位)中

    汇编器能通过计算操作数的数目判断你运行的是哪一条指令

使用

inttype.h

——GCC提供的128位整数支持定义128位数字

除法与取模操作用单操作数除法指令提供。

idivl

将寄存器

%rdx

%rax

中的128数作为被除数,将指令的操作数作为除数给出

商存储在

%rax

中,余数存储在

%rdx

有符号除法:

%rax

全为符号位

无符号除法:

%rax

全为0

继续阅读