6.1 整數運算指令#
ADD#
ADD A,B
指令將 B 的值與 A 相加,並將結果保存到 A。A 可以是一個寄存器或者內存值。B 可以是一個寄存器、一個常量或者內存值。在同一條指令中,A 和 B 不能同時是內存值。
add 文本搜索結果
在上圖中,有很多 ADD 指令的實例,在這些例子中第一個操作數是寄存器,第二個操作數是常數,那麼在程序運行時,常數加寄存器值的結果將保存回這個寄存器當中。
實例 1 寄存器加常數
在上圖中,如果ECX = 10000
,加上常數 4, 結果是 10004,結果重新保存到ECX
當中。
實例 2 內存值加常數
上圖中,ADD 指令將在ECX+30
指向地址存儲的值上加上0xffffffff
常數,如果程序對這個地址有寫入權限的話,計算結果也會傳回存儲在這個地址上。假設ECX = 0x10000
那麼加上 30 就是0x10030
,如果這個地址保存的數是 1, 加上常數0xffffffff
也就是 - 1, 結果是 0 並且保存到0x10030
地址上。
實例 3 寄存器相加
上圖中,兩個寄存器相加的結果保存到 eax 中。ADD 指令另外也可以對 16 位和 8 位寄存器進行操作。
例如:
ADD AL,8
ADD AX,8
ADD BX,AX
ADD byte ptr ds: [EAX],7 # 在EAX指向的字節上加上7,並且保存在同一地址。
ADD 指令的操作數只要 A 不是常數,或者 A、B 都是內存值,其他寄存器、內存的組合都是允許的。
SUB#
SUB A,B
這個指令和ADD
指令一致,只不過它是對兩個操作數相減,最後結果保存到 A。SUB 允許的操作數組合和 ADD 是一樣的。
實例 1 sub 搜索結果
INC & DEC#
INC A
和DEC A
指令對一個寄存器或者內存值 ±1。這是加減操作的一個特例。一般這兩個指令用來對計數器 ±1。
IMUL#
IMUL 是帶符號整數乘法指令,這裡介紹兩種使用方式。
IMUL A,B
和IMUL A,B,C
- 第一種對 A 和 B 相乘,結果返回給 A
- 第二種方式對 B 和 C 相乘,將結果返回給 A。
在這兩種方式下,A 只能是一個寄存器,B 可以是寄存器或者內存值 (第一種方式下可以是常數) , 而 C 只能是個常數。
例如:
Imul eax, [ecx]
Imul esi, edi, 25
實例 1 imul 使用指令
上述只有一種使用方法,對兩個操作數相乘並把結果保存到第一個操作數中。
IDIV#
IDIV A
指令中,僅僅指定了除法的除數。被除數沒有指定,因為存放的地方是固定的。
Dividend (D) ➗ divider (d) = quotient (q)
Dividend (D) 是被除數,divider (d) 是除數,quotient (q) 是除法的結果,也就是商。
在 32 位運算中,EDX 和 EAX 組成一個 64 位數,EDX 在高位,EAX 在低位,這個 64 位數除以 A 後,商返回給 EAX,餘數返回給 EDX。
實例 1 IDIV 使用實例
上圖中,假如 EAX=5,EDX=0,ECX=2,那麼 5➗2 的結果是 2,保存導 EAX 中,餘數 1 保存到 EDX 中。
如果 A 十個內存值也是一樣,EDX被 A 除,商返回給 EAX,餘數返回給 EDX。
6.2 邏輯運算指令#
首先是 AND (按位與) 、OR (按位或) 和 XOR (異或) 運算。
AND A,B 對 A 和 B 進行與運算,將最終結果保存到 A。對於 OR 和 XOR 運算也是一樣的。
A 和 B 可以是寄存器或者內存值,但同一條指令中 A 和 B 都是內存值是不允許的。
XOR#
最常用的例子對同一個寄存器 XOR (異或) 運算,將它的值清零。例如XOR EAX,EAX
或者其他寄存器將清零,XOR (異或) 運算的真值表上圖。對同一個數進行異或運算結果都是 0,操作是在二進制模式下進行的。
在 16 進制下也可以進行異或操作,在 python 中異或用符號^
表示,兩個相同的值異或最後結果為 0。
AND#
and eax,0xf
0xf 二進制表示位 1111。
由於 0xf 最後 4 位為 1,eax 的最後 4 位保持不動,其他位全部變成 0,通過這種方式留下了 eax 最後 4 位,並對其他位進行清零。
and 在 python 中用 & 符號進行表示,上圖中的結果為 0b111,也就是最低位的 4 個 bit。
OR#
OR 運算在 Python 中是 “|” 符號。
NOT#
NOT A
將 A 所有的位取反然後保存到 A。Python 中按位取反是~
符號。對於 0101,結果會對每一位取反。所有的 0 反轉為 1,1 反轉為 0。
實例 1 對 0b0101 取反
實例 2 結果位 0b1010
NEG#
NEG A
將 A 轉變成 - A。NEG 運算和按位取反不一樣,按位取反多減了 1。
在 python 中使用 NEG 可以取反後再加 1。
SHL#
SHL A,B
SHR A,B 中 A 是一個寄存器或內存值,B 是一個常數或者一個 8 位寄存器。 這兩個指令將操作數按位向左或向右偏移,缺少的位用 0 來填補,舉個例子,例如 - 1。
實例 1 -1 的二進制
執行 SHL 2 之後,如下圖所示。
當這些比特向左偏移時,最左邊的 2 個比特被丟棄,右側的 2 個比特用 0 表示。
對於 SHR 來說也是一樣的,這些比特向右偏移,右側的比特被丟棄,左側的空位用 0 來填充。
還有 2 個類似的指令 ROL 和 ROR,指令會將每個比特移動一定的位置,但是一端超出的字節會返回給另一端,指令對每個比特進行了偏移但不改變內容。
本章主要介紹了匯編語言中的整數和邏輯運算指令,夯實一些基礎。