|
乘法和除法指令是处理器上最耗时的两种指令。但是像基于 2 的乘方的乘法和除法可以用移位运算来迅速完成。
1、移位乘法
向左移动 1 位相当于乘以 2,这里有两条指令,SAL(算术左移位) 和 SHL (逻辑左移位)。这两个指令执行相同的操作,它们有 3 种不同的格式:sal destination
sal %cl, destination
sal shifter, destination 第 1 种格式把 destination 的值向左移 1 位,等同于乘以 2。
第 2 种格式把 destination 的值向左移动 CL 寄存器里指定的位数。
第 3 种格式把 destination 的值向左移动 shifter 值指定的位数。
在具体的指令应用中,指令助记符的结尾要附加上一个字符,用于指出目标值的长度。
可以对带符号和无符号整数执行向左移指令。移位造成的空位用零填充,移出的数位放在位标志中,每次移动这个位标志里的值都会被移动出来的新值挤出。
测试程序:
# sal.s - An example of the SAL instruction
.section .data
value1:
.int 25
.section .text
.global _start
_start:
nop
movl $10, %ebx
sall %ebx
movb $2, %cl
sall %cl, %ebx
sall $2, %ebx
sall value1
sall $2, value1
movl $1, %eax
movl $0, %ebx
int $0x80 在 GDB 里可以看到程序执行移位指令后各自的值:(gdb) x/d &value1
0x804909c <value1>: 200
(gdb) info reg
eax 0x0 0
ecx 0x2 2
edx 0x0 0
ebx 0x140 320 如果在源程序中把 .section .text 不小心写错了,如写成 .section .dext ,那么在调试时会出现下面的错误提示:No symbol table is loaded. Use the "file" command.
2、移位除法
在移位除法里,当把整数向右移时,必须注意整数的符号。
对于无符号整数,向右移位产生的空位可以被填充为 0 ,而且不会有任何问题。不幸的是,对于带符号整数,使用 0 填充高位部分会对负数产生有害影响。为了解决这个问题,就有了两个右移指令。SHR 指令清空移位造成的空位,所以它只能用于对无符号整数进行的移位操作。SAR 指令根据整数的符号位,要么清空,要么设置移位造成的空位。对于负数,空位被设置为 1,而对于正数,则被清空为 0 。
和左移指令一样,右移指令移出的元素也会被移动到进位标志中去,如果再有移位,原先在进位标志里的元素会被挤掉。
3、循环移位
循环移位指令执行的功能和移位指令一样,只不过溢出位被存放回值的另一端,而不是被丢弃。下表是各种循环移位指令:
指令
| 描述
| ROL
| 向左循环移位
| ROR
| 向右循环移位
| RCL
| 向左循环移位,并且包含进位标志
| RCR
| 向右循环移位,并且包含进位标志
| 上表中最后 2 条指令使用进位标志作为附加位的位置来支持 9 位移位。循环移位指令的格式和移位指令相同,也有 3 种格式:
2个操作数:指定循环次数的 %cl 寄存器和目标操作数。
|
|