|
带符号乘法指令 IMUL
一、使用 IMUL 进行带符号整数乘法
MUL 指令只能用于无符号整数,而 IMUL 指令可以用于带符号和无符号整数,但是必须小心结果不使用目标的最高有效位。
IMUL 指令有 3 种格式:
source 操作数可以是 8 位、16位或者 32 位寄存器或内存中的值,它与位于 AL、AX 或者 EAX 寄存器(取决于源操作数的长度)中的隐含操作数相乘。然后,结果放到 AX 寄存器、DX:AX 寄存器对或者是 EDX:EAX 寄存器对中。
IMUL 指令的第 2 种格式允许指定 EAX 寄存器之外的目标操作数:
其中,source 可以是 16 位或者 32 位寄存器或是内存中的值,destination 必须是 16 位或者是 32 位通用寄存器。这种格式允许指定把乘法操作的结果存放到哪个位置 (而不是强制使用 AX 和 DX 寄存器)。这种格式的缺陷是,乘法操作的结果被限制为单一目标寄存器的长度(非 64 位结果)。使用这种格式时必须非常小心,不要溢出目标寄存器!
IMUL 指令的第 3 种格式允许指定 3 个操作数:
imul multiplier, source, destination 其中,multiplier 是一个立即数,source 是 16 位或者 32 位寄存器或是内存中的值,destination 必须是通用寄存器。这种格式允许执行一个值 (source) 和一个带符号整数 (multiplier) 的快速乘法操作,最后结果存在通用寄存器(destination)中。
和 MUL 指令一样,使用 IMUL 指令,要记住在其结尾添加长度字符(b, w, l),以便指定源和目标操作数的长度。
测试程序:.section .data
value1:
.int 10
value2:
.int -35
value3:
.int 400
.section .text
.global _start
_start:
nop
movl value1, %ebx
movl value2, %ecx
imull %ebx, %ecx
movl value3, %edx
imull $2, %edx, %eax
movl $1, %eax
movl $0, %ebx
int $0x80 在调试器里查看运算后的相关值:(gdb) info reg
eax 0x320 800
ecx 0xfffffea2 -350
edx 0x190 400
ebx 0xa 10 在上面的 imull $2, %edx, %eax 里,如果把立即数改成一个很大的数,假设产生溢出,那么想成的结果就会不断的减去 n 个 0x100000000 ,直至剩下不至于使 32 位寄存器溢出的值。
检查溢出
当使用带符号整数和 IMUL 指令时,总要记住检查结果中的溢出,这可以用 JO 指令来检测(另一种方式是检查进位标志)。
测试程序:.section .text
.global _start
_start:
nop
movw $680, %ax
movw $100, %cx
imulw %cx
jo over
movl $1, %eax
movl $0, %ebx
int $0x80
over:
movl $1, %eax
movl $1, %ebx
int $0x80 运行与输出:从输出可以看到,结果发生了溢出。 |
|