masm匯編語言常用指令 (上)


注釋/說明

L : 字面量

R: 內存變量

M: 寄存器

S: 標號

寄存器

在 masm 匯編中, 一般有以下幾種寄存器

通用目的寄存器 段寄存器 指令指針寄存器 標志位寄存器
eax cs eip OF
ebx ds SF
ecx es ZF
edx ss CF
esi AF
edi PF
ebp DF
esp IF
TF

通用目的寄存器

eax : 全稱為 Accumulator Register(累加器). 在進行乘法和除法時會將其中一部分操作結果自動放在 eax 中, 調用函數時也需要把返回值保存在 eax 中. 因此在執行這些操作時不要用 eax 存儲數據

ebx : 全稱為 Base Register(基地址寄存器). 一般沒什么專門的用途, 常用來充當臨時變量或地址

ecx : 全稱為 Counter Register(計數寄存器). 一般用來充當計數器, 在循環中的使用較多.

edx : 全稱為 Data Register(數據寄存器). edx 常被 eax 用來擴展數位 (例如進行有符號除法時, edx : eax 共同組成被除數, edx 的最高位充當符號位)

esi 和 edi : 全稱為 Source Index (源變址寄存器) / The Destination Index (目的變址寄存器). 這兩者的區別不是很大, 不過在 CPU 中往往是 esi 讀取數據, 而 edi 寫入數據. 一般在字符串操作上面的用途較多, 且往往和循環指令 STOS, MOVSB, SCASB 一起出現來完成大量數據的保存, 加載與掃描工作.

ebp : 全稱為 Base Pointer (棧基指針寄存器). 在函數調用時常用來作棧底指向棧中的數據, 在整個函數運行的過程中其內部存放的地址不會發生改變. 該寄存器為特殊寄存器, 不能對其進行修改.

esp : 全稱為 Stack Pointer (棧頂指針寄存器). 與 ebp 一樣與函數調用有關, 且每一次的 push, pop, ret, call 操作時其內部的地址都會發生改變. 該寄存器為特殊寄存器, 不能對其進行修改.

段寄存器

cs : 全稱是Code Segement (代碼段寄存器).

ds : 全稱是Data Segment (數據段寄存器).

es : 全稱是Extra(Data) Segment (擴展數據段寄存器)

ss : 全稱是Stack Segment (棧段寄存器)

由於我還沒能了解段寄存器的作用, 因此只能將完整的名稱寫上, 后續會補

指令指針寄存器

eip : 全稱是Extend Instruction Pointer (擴展指令指針寄存器). 主要用來指向內存中的地址, 以表示接下來應該獲取, 解碼並執行的指令. 該寄存器也是一種特殊寄存器, 不能對其進行修改.

標志位寄存器

寄存器 功能 全稱 標志形式
OF 溢出標志 overflow flag 溢出置1, 否則置0
SF 符號標志 sign flag 正數置0, 負數置1
ZF 零標志 zero flag 結果為0置1, 否則置0
CF 進位標志 carry flag 無符號數最高有效位進位, 或有符號數最高有效位需要借位, 則置1. 否則置0
AF 輔助進位標志 auxiliary carry flag 用以表示加減法做到一半時有沒有形成進位/借位,如果有則置1, 否則置0
PF 奇偶標志 parity flag 若結果為1的二進制位個數是偶數則置1, 為奇數置0
DF 方向標志 direction flag 用以代表esi和edi的增減, 置1遞減, 指令遞增
IF 中斷標志 interrupt flag IF置1,響應外部中斷,置0則屏蔽外部中斷;
TF 陷進標志 trap flag TF置1時,處理器每次只執行一條指令,即單步執行. 置0反之

mov 和 movl

將源操作數的內容復制到目標操作數, 兩者必須有一個是寄存器

mov M/R, L/M/R

xchg

交換兩個操作數的內容, 兩者必須有一個是寄存器

xchg M/R, M/R

add 和 sub

add 為加法指令, sub 為減法指令. 兩個操作數必須有一個是寄存器

add M/R, L/M/R
sub M/R, L/M/R

neg

切換操作數的正負號, 即求補碼

neg M/R

inc 和 dec

inc 自加指令, dec 自減指令

inc M/R
dec M/R

mul 和 imul

mul 為無符號乘法, imul 為有符號乘法.

mul 的積存儲在 edx : eax 中, 其中eax作被乘數, 只支持單個操作數. imul 的積存儲在自定義的寄存器中, 被乘數和乘數也可存儲在自定義的寄存器中, 最多支持三個操作數.

mul M/R

imul M/R
imul R, L/M/R
imul R, M/R, L

div 和 idiv

div 為無符號除法, idiv 為有符號除法.

div 計算的被除數存儲在 edx : eax 中, 除數為自定義的內存變量或寄存器, 商存儲在 eax 中, 余數存儲在 edx 中. 只支持單操作數

idiv 與 div 差不多. 不過在進行有關負數除法運算時, 需要將 edx 和 eax 全部求補才可進行運算, 否則會出錯.

div M/R

idiv M/R

SHL 和 SHR

SHL 和 SHR 為邏輯左移 / 邏輯右移. 每移動 n 位二進制數, 結果擴大 / 縮小原來的 \(2^{n}\) 倍, 注意如果值為負數, 進行邏輯右移后其可能會出錯.

shl M/R, L
shr M/R, L

SAL 和 SAR

SAL 和 SLR 為算數左移 / 算術右移. 每移動 n 位二進制數, 結果擴大 / 縮小原來的 \(2^{n}\) 倍, 負數進行算術右移不會像邏輯右移一樣出現錯誤.

sal M/R, L
sar M/R, L

數位擴展

指令 寄存器 大小 擴展到 寄存器 大小
cwd ax 16 dx : ax 32
cdq eax 32 edx : eax 64
cqo rax 64 rdx : rax 128

有了數位擴展指令, 就可以很方便的進行負數的有符號除法.

xor edx, edx
xor eax, eax
		
mov eax, -1
cdq
		
mov ebx, 1
idiv ebx

寄存器結果

eax = FFFFFFFF
edx = 00000000

lea

加載有效地址, 將源操作數的地址加載到目標操作數中. 由於實際地址要在程序運行時才能知道, 因此涉及這些地址的操作應該用 lea 來完成. 該指令的目標操作數必須是寄存器

lea R, M

ptr

用來將數據移動到與之大小不符的另一個區域所需要使用的指令, 例如一個為 4 個字節的 int 內存變量, 若移動到一個其大小為 2 個字節的 ax 寄存器中, 則需要 ptr 進行轉換; 或一個為 2 個字節的 int 內存變量, 若移動到一個其大小為 4 個字節的 eax 寄存器中, 也需要 ptr 進行轉換. size 必須與 R 的大小相符, 源操作數必須是內存變量

mov R, size ptr M

int x = -1;

__asm
{
    xor eax, eax
        
    mov ax, word ptr x
}

寄存器結果

;轉換前的eax
eax = 00000000

;轉換后的eax
eax = 0000FFFF

movzx 和 movsx

與 ptr 指令一樣, 用來將數據移動到與之大小不符的另一個區域所需要使用的指令, 但是限制沒有 ptr 那么多. 擴展的大小視目標操作數大小而定

movzx 的 zx 表示 Zero eXtend , 用 0 來擴展數位, movsx 的 sx 表示 Sign eXtend, 用符號位來擴展數位

movzx R, M/R
movsx R, M/R

offset

offset 看上去也是和 lea 一樣用來獲取地址的, 不過與 lea 不同的是, offset 獲取的是內存變量或標號到數據段數據段的起始地址的距離. 源操作數只能是內存變量或標號. 且 offset 只能獲取編譯時已知的地址 (如符號常量等)

mov M/R, offset M/S


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM