0x01 常见的算术运算指令
我们常见的算术运算指令有:
add (加法)、adc(带进位加法)、inc(加一)、dec(减一)、sub(减法)、sbb(带借位减法)、neg(求补)、cmp(比较)、mul(无符号数乘法)、imul(带符号数乘法)、div(无符号数除法)、idiv(带符号数除法)、cbw(字节转换为字)、cwd(字转换为双字)。
下面介绍其中的一部分比较麻烦的。
0x02 加法
add 和 adc 都是加法,前者是加法,后者是带进位的加法。主要区别在于前者运算不考虑 CF 位,后者考虑了 CF 位。
adc 指令的引入主要是为了实现多字节的运算个。当进行32位以上运算时,就需要用多个寄存器进行运行算,要求低位字节相加,而高位字节再相加时就要考虑低位相加的进位,即 CF,这时就要用到 adc 指令
add eax,1 ;eax = eax +1
adc eax,1 ;eax = eax +1 +CF
inc 指令的意思是加一,类似于 c 语言中 +=1
。
0x03 减法
sub 和 sbb 都是减法,前者是减法,后者是带借位的减法。主要区别与 add 和 adc 的区别类似,都是对于是否考虑 CF 位。
假设我们需要用一个 36 位整数减去 64 位的整数,这时我们先用低 32 位寄存器进行运算,根据运算中是否有向高位借位,决定是否修改 CF ,而高位运算则考虑 CF 的值来判定低位运算中是否出现了借位。这就是 sbb 。
sub eax,ebx ;eax = eax - ebx;
sbb eax,ebx ;eax = eax - ebx - CF
dec 指令的意思是减一,类似于 C 语言的 +=1
。
0x04 neg 求补
可以理解为 0 - eax ,然后将结果由负转为正数。
0x05 乘法
两种乘法相差不大,mul 指令就是将指令后的寄存器中的操作数乘上某寄存器中的数,结果存放在寄存器中。mul res
指令后的操作数寄存器为 16 位,相乘的寄存器为 al ,结果存放在 eax 中;
指令后的操作数寄存器位 32 位,相乘的寄存器为 eax ,结果存放在 edx:eax 中;
对于 imul 指令,其指令格式可以有多种,可以是 mul 一样的,也可以有两个操作数、三个操作数。其中同 mul 一样一个操作数的乘法规则相类似。
0x06 除法
除法指令 div 其后面接一个寄存器或一个内存,其为除数,被除数存放在 eax 或者 eax 和 edx 中,结算出的结果商、余数分别存放在 al 和 ah 或者 eax 和 edx 中。