注釋/說明
masm 匯編語言常用指令 (上) : https://www.cnblogs.com/ICeVe/p/14589519.html
L: 立即數
M: 內存變量
R: 寄存器
S: 標號
not
按位進行非運算, 操作數只有一個
not M/R
and
按位與運算
and M/R, L/M/R
or
按位或運算
or M/R, L/M/R
xor
按位異或運算
xor M/R, L/M/R
test 和 cmp
test 和 cmp 都是比較指令. 不過實現方式不同
test 是將兩個操作數進行 and 運算, 結果將由標志位寄存器 (如 pf, sf, zf 等) 來判斷. test 不會修改兩個操作數的值, 也不會讓其中一個操作數保存計算結果
cmp 是用目標操作數減去源操作數, 結果將由標志位寄存器 (如 pf, sf, zf 等) 來判斷. cmp 同樣不會修改兩個操作數的值, 也不會讓其中一個操作數保存計算結果
test M/R, L/M/R
cmp M/R, L/M/R
跳轉指令
無條件跳轉 : jmp
即直接跳轉, 沒有條件
jmp S
有條件跳轉
有條件跳轉比較繞, 因此判斷是否跳轉一定要看准標志位寄存器和比較指令, 比較指令決定標志寄存器的狀態, 既而決定跳轉結果
有符號數與無符號數
標志 | 指令 | 描述 |
---|---|---|
of = 1 | jo | 如果溢出, 則跳轉 |
of = 0 | jno | 如果不溢出, 則跳轉 |
pf = 1 | jp | 如果奇偶校驗位置1, 則跳轉 |
pf = 0 | jnp | 如果奇偶校驗位置 0, 則跳轉 |
sf = 1 | js | 如果符號位置 1, 則跳轉 |
sf = 0 | jns | 如果符號位置 0, 則跳轉 |
zf = 1 | je jz |
如果相等, 則跳轉 如果為 0, 則跳轉 |
zf = 0 | jne jnz |
如果不想等, 則跳轉 如果不為 0, 則跳轉 |
有符號數
標志 | 指令 | 描述 |
---|---|---|
sf != of | jl jnge |
如果小於, 則跳轉 如果不大於等於, 則跳轉 |
sf = of | jge jnl |
如果大於等於, 則跳轉 如果不小於, 則跳轉 |
zf = 1 or sf != of | jle jng |
如果小於等於, 則跳轉 如果不大於, 則跳轉 |
zf = 0 and sf != of | jg jnle |
如果大於, 則跳轉 如果不小於或不等於, 則跳轉 |
無符號數
標志 | 指令 | 描述 |
---|---|---|
cf = 1 | jb jc jnae |
如果低於, 則跳轉 如果進位標志位置 1, 則跳轉 如果不高於或不等於, 則跳轉 |
cf = 0 | jae jnb jnc |
如果高於或等於, 則跳轉 如果不低於, 則跳轉 如果標志不置 1, 則跳轉 |
cf = 1 or zf = 1 | jbe jna |
如果低於或等於, 則跳轉 如果不高於, 則跳轉 |
cf = 0 and zf = 0 | ja jnbe |
如果高於, 則跳轉 如果不低於或不等於, 則跳轉 |
loop
即循環指令, ecx 作為計數器, 每執行一次 loop 指令, ecx 都會減 1, 當 ecx 為 0 時跳過 loop 指令, 繼續執行下一條指令
loop S
push
將內存變量或寄存器的值壓入棧中進行保存, 同時 esp - n. 其中 n 為壓棧的字節數
push L/M/R
pop
將壓入棧中的內存變量或寄存器的值彈出到指定的 寄存器/內存變量
pop M/R
call
call 可看作是一種跳轉指令, 執行 call 指令后會自動跳轉到操作數 (一般為標號) 所在的地址上. 同時還會將 call 下方的一條指令的地址壓入棧中, 以確保函數執行完畢后能正常運行.
call S
ret
將棧頂的值彈出至 eip, 以便函數執行完畢后能正常運行. 該指令不需要操作數 (僅在 stdcall 調用約定下)
ret
nop
空操作, 不做任何行為
nop
cld
將方向標志 (df) 清零, 使程序在執行字符串操作時按從左到右的順序讀取字符 ( 即先從地址較低的位置上讀取 ). 該指令不需要操作數
cld
std
將方向標志 (df) 置 1, 使程序在執行字符串操作時按從右到左的順序讀取字符 ( 即先從地址較搞的位置上讀取 ). 該指令不需要操作數
std
rep
性質和 loop 類似, 也是一種循環指令, ecx 作為 計數器, 當 ecx 為 0 時 rep 結束指令. 常和字符串指令配合使用. rep 后面跟字符串指令.
每執行一次指令, edi / esi 會 + 4
rep opreate
repz / repe
與 rep 相同, 不過需要對標志位寄存器 zf 作判斷. 如果 zf 或 ecx 為 0 時 結束指令. 常和字符串指令配合使用. repz / repe 后面跟字符串指令
每執行一次指令, edi 或 esi 會 + 4
repz opreate
repe opreate
repnz / repne
與 repz / repe 相同, 如果 zf 置 1 或 ecx 為 0 時 結束指令. 常和字符串指令配合使用. repz / repne 后面跟字符串指令
每執行一次指令, edi 或 esi 會 + 4
repnz opreate
repne opreate
movs
和 mov 類似, 不過它專門用來將字符從一個地方復制到另一個地方. movs 通常有后綴 (如 b, 字節; w, 字; d, 雙字; q, 四字), 用來表示每次復制字符的字節大小. movs 默認由 esi 作為源操作數, edi 為目標操作數, 因此不需要寫操作數. esi 和 edi 一般獲取的都是字符串的首或字符的地址
movsb
movsw
movsd
movsq
cmps
字符比較指令, 與 cmp 類似, 用目標操作時減去源操作數的字符來判斷, 如果在執行 cmps 時若兩個字符串中發現字符不同時則結束指令. 由於每次只能比較一個字符, 因此通常和 repnz / repne 配合使用. 默認由 esi 作為源操作數, edi 為目標操作數, 因此不需要寫操作數.
cmps 可以像 movs 一樣添加后綴 ( 如 b, 字節; w, 字; d, 雙字; q, 四字 )
cmpsb
cmpsw
cmpsd
cmpsq
scas
scas 的作用與 cmps 差不多, 不同的是 scas 在執行 scas 時若兩個字符串中發現字符相同時則結束指令. 由於每次只能比較一個字符, 因此通常和 repnz / repne 配合使用. 默認由 esi 作為源操作數, edi 為目標操作數, 因此不需要寫操作數.
scasb
scasw
scasd
scasq
stos
用來將 eax 中的值復制到由 edi 所表示的內存地址上. 可以與 rep 配合起來用, 實現多個位置的初始化. stos 可以添加后綴 ( 如 b, 字節; w, 字; d, 雙字; q, 四字 ) . 默認由 edi 操作數, 因此不需要寫操作數.
stosb
stosw
stosd
Stosq
lods
與 stos 相反, 將 esi 所表示的內存地址上的值復制到 eax 中, 不需要與 rep 配合起來用, 因為這樣會使 eax 頻繁遭到復寫. lods 可以添加后綴 ( 如 b, 字節; w, 字; d, 雙字; q, 四字 ) . 默認由 esi 操作數, 因此不需要寫操作數.
lodsb
lodsw
lodsd
lodsq