音ノ木坂学院

叶え!みんなの夢――

0%

x86汇编急救指南:指令集

明天下午考试,今天赶快把知识点整理一下。为了节省时间,只整理bhh要考的……

1. xchg:交换

用法:

1
2
3
mov ax, 1 ; ax=1
mov bx, 2 ; bx=2
xchg ax, bx ; ax=2, bx=1

备注:不影响标志位;操作数中不能有段寄存器。

2. push/pop:入栈/出栈

说明:16位CPU中,SS:SP指向栈顶,每次push后SP-=2,pop后SP+=2

用法:

1
2
push ax ; SS:SP+1=al, SS:SP+2=ah, SP-=2
pop bx ; bh=SS:SP, bl=SS:SP-1, SP+=2

备注:不影响标志位;只能对16位进行操作(不能push/pop ah/al);push的操作数不能是立即数;pop的操作数不能为CS。

3. lea:取偏移地址

用法:

1
2
lea dx, ds:[1000h] ; dx=100h
lea ax, ds:[bx+si+3] ; ax=bx+si+3

4. cbw/cwd:符号数扩充

cbw: convert byte to word

1
2
3
4
5
if( AL & 80h != 0 )
AH = 0FFh
else
AH = 00h
endif
1
2
3
4
mov al, 7Fh ; al=+127, 8 bits signed
cbw ; ax=007Fh=+127, 16 bits signed
mov al, 0FCh ; al=-6
cbw ; ax=0FFFCh=-6

cwd: convert word to double word

1
2
3
4
5
if( AX & 8000h != 0 )
DX = 0FFFFh
else
DX = 0000h
endif
1
2
3
4
mov ax, 0FFFEh ; ax=-2
cwd ; dx:ax=0FFFFFFFEh, dx=0FFFFh, ax=0FFFEh
mov ax, 7FFFh ; ax=+32367
cwd ; ds:as=00007FFFh, dx=0000h, ax=7FFFh

5. add/adc/inc:加/带进位加/自增一

1
add dest, src

dest = dest + src
溢出时CF=1

1
2
add word ptr es:[bx], 1234h ; add mem, reg
add [bx], ax ; add mem, reg
1
inc op

op = op + 1
不影响CF

1
inc byte ptr ds:[10A0h]
1
adc dest, src

dest = dest + src + CF

1
2
3
4
mov ax, 0F365h
mov dx, 2
add ax, 0E024h
adc dx, 5 ; DX:AX=2F365h+5E024h

6. sub/sbb/dec

1
sub dest, src

dest = dest - src
溢出CF=1

1
sub [bp-8], ax ; sub mem, reg
1
dec op

op = op - 1

1
dec word ptr [bx+si+2]
1
sbb dest, src

dest = dest - src - CF

1
2
mov ax, 7546h
sbb ax, 9428h ; AX=0E11Eg, CF-1

7. mul/div

均为非符号数

1
mul src

AX = AX * src (8 bits src)
DX:AX = AX * src (16 bits src)

1
2
3
mov ax, 1234h
mov cx, 100h
mul cx ; DX:AX=AX*CX=1234h*1000h=123400h; DX=0012h, AX=3400h
1
div op

AL = AX / op (8 bits op)
AX = DX:AX / op (16 bits op)

1
2
3
4
5
6
mov ax, 3400h
mov dx, 12h
mov bx, 10h
div bx
; AX=DX:AX/BX=123400h/100h=1234h
; DX=DX:AX%BX=123400h%1000h=0 (余数)

8. and/or/xor/not/neg

1
and dest. src

dest = dest & src
OF=0
CF=0

1
or dest, src

dest = dest | src
OF=0
CF=0

1
xor dest, src

dest = dest ^ src
OF=0
CF=0

1
not op

op = ~op

1
neg op

op = -op

对非零求补时CF=1,对零求补CF=0

9. shl/shr/sal/sar/rol/ror/rcl/rcr

shl dest, count 逻辑左移:最高位移到CF,最低位补零

shr dest, count 逻辑右移:最低位移到CF,最高位补零

sal dest, count 算数左移:最高位移到CF,最低位补零(和shl完全相同)

sar dest, count 算数右移:最低位移到CF,最高位和原最高位相同

rol dest, count 循环左移:最高位移到CF,同时移到最低位

ror dest, count 循环右移:最低位移到CF,同时移到最高位

rcl dest, count 带进位循环左移:最高位移到CF,CF移到最低位

rcr dest, count 带进位循环右移:最低位移到CF,CF移到最高位

10. cmp

1
cmp op1, op2

NULL = op1 - op2

非符号数:

CF=1 -> a<b (有借位)

ZF=1 -> a=b (结果为零)

CF=0且ZF=0 -> a>b (无借位,结果不为零)

符号数:

SF!=OF -> a<b (SF=1,OF=0: a-b结果为负没有溢出;SF=0,OF=1: a-b结果为正溢出->a<b)

ZF=1 -> a=b

SF=OF且ZF!=0 -> a>b (SF=0,OF=0: a-b结果为正没有基础;SF=1,OF=1:a-b结果为负溢出->a>b)

11. jxx:ja/jb/jae/jbe // jg/jl/jge/jle/jc // jnc/je/jne/jz/jnz/jcxz // js/jns // jo/jno

非符号数或符号数:

je: 等于则跳 ZF=1

jne: 不等则跳 ZF=0

非符号数:

ja: 大于则跳 CF=0 && ZF=0

jae: 大于等于则跳 CF=0

jb: 小于则跳 CF=1

jbe: 小于等于则跳 CF=1 || ZF=1

符号数:

jg: 大于则跳 SF=OF && ZF=0

jge: 大于等于则跳 SF=OF

jl: 小于则跳 SF!=OF && ZF=0

jle: 小于等于则跳 SF!=OF

与标志寄存器相关:

见寄存器一章

jcxz: CX=0则跳

12. loop

1
2
3
4
CX = CX-1
if( CX != 0 )
IP = dest
endif

13. clc/stc/cli/sti/cld/std

见寄存器一章

14. call/ret/int/iret

call dest

1
2
push IP
IP = dest

ret idata

1
pop IP

ret [count]

1
2
pop IP
SP = SP + count

int n

1
2
3
4
5
6
pushf ;压入标志寄存器
push CS ;压入CS
push IP ;压入下条指令的偏移地址
TH = 0, IF = 0 ;清除陷阱标志和中断标志
IP = word ptr 0000h:[n*4] ;从中断向量表中取出IP
CS = word ptr 0000h:[n*4+2] ;从中断向量表中取出CS

iret

1
2
3
pop IP
pop CS
popf

15. mov jmp

mov用法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
; mov reg, idata
mov ah, 2
mov ax, 1234h
; mov mem, idata
mov byte ptr ds:[10A0h], 12h
mov word ptr es:[bx+si], 1234h
; mov reg, reg
mov ah, al
mov es, ax
; mov reg, mem
mov ah, [bx+2] ; OK!
mov si, es:[bi]
; mov mem, reg
mov ds:[10A0h], ah
mov [si], si

jmp

消失啦

16. repne scasb/repe scasb/rep movsb/lodsb/stosb/rep stosb

movsb:以字节为单位传送字符串 moving string byte

rep movsb:移动CX个字符(每次CX–)

1
2
3
4
5
6
7
8
byte ptr ES:[DI] = byte ptr DS:[SI]
if( DF == 0 ) ;正方向
SI = SI + 1
DI = DI + 1
else ;反方向
SI = SI - 1
DI = DI - 1
endif

repe scasb/renpe scasb:在字符串中查找一个字符 scan string byte

repe: 若相等则继续扫描

renpe: 若不相等则继续扫描

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
again:
if( CX == 0 )
goto done
endif
NULL = AL - byte ptr ES:[DI]
temp = FL
if( DF == 0 )
DI = DI + 1
else
DI = DI - 1
endif
CX = CX - 1
FL = temp
if( ZF == 1 ) ; renpe: ZF == 0 若不相等
goto again
endif
done:

lodsb: 从字符串取字节

1
2
3
4
5
6
AL = byte ptr DS:[SI]
if( DF == 0 )
SI = SI + 1
else
SI = SI - 1
endif

stosb: 存入字节到字符串

1
2
3
4
5
6
byte ptr ES:[DI] = AL
if( DF == 0 )
DI = DI + 1
else
DI = DI - 1
endif