Fork me on GitHub

8086汇编:指令系统(下)

控制转移指令

1. jmp(无条件转移)

1
2
3
jmp label ; 跳到 label 的地址
jmp reg16/mem16 ; 段内转移,ip = reg16/[mem16]
jmp mem32 ; 段间转移,cs = mem32高字,ip = mem32低字

可以加上 short, near, far 等标识符,分别表明是短转移(ip修改范围 -128 ~ 127)、近转移(ip修改范围 -32768 ~ 32767)、远转移(cs:ip都修改)。

2. jcc(条件转移)

1
jcc label ; 若成立,ip 修改为 label 的偏移地址(-128~127),否则忽略该指令

简单测试条件的jcc指令

jcc 指令 描述 转移条件
jz/je 为零(相等)时转移 zf = 1
jnz/jne 非零(不等)时转移 zf = 0
jc/jb 有进位时转移 cf = 1
jnc/jnb 无进位时转移 cf = 0
js 为负时转移 sf = 1
jns 为正时转移 sf = 0
jo 溢出时转移 of = 1
jno 不溢出时转移 of = 0
jp/jpe 奇偶位为1时转移 pf = 1
jnp/jpo 奇偶位为0时转移 pf = 0
jcxz cx0时转移 cf = 0

带符号数比较的jcc指令

jcc 指令 描述 转移条件
jg/jnle 大于(不小于等于)时转移 sf = ofzf = 0
jge/jnl 大于等于(不小于)时转移 sf = pf
jl/jnge 小于(不大于等于)时转移 sfof
jle/jng 小于等于(不大于)时转移 sfofzf ≠ 0

无符号数比较的jcc指令

jcc 指令 描述 转移条件
ja/jnbe 高于(不低于等于)时转移 cf = 0 且 zf = 0
jae/jnb 高于等于(不低于)时转移 cf = 0
jb/jnae 低于(不高于等于)时转移 cf = 1
jbe/jna 低于等于(不高于)时转移 cf = 1 或 zf = 1

3. loop(循环)

1
2
3
loop label ; cx=cx-1, 若cx!=0则转到label
loopz/loope label ; cx=cx-1,若cx!=0且zf=1则转到label
loopnz/loopne label ; cx=cx-1,若cx!=0且zf=0则转到label

label的相对偏移量必须在-128~127之间

4. call(调用)/ ret(返回)

1
2
3
call label ; 段内直接调用,ip入栈
call reg16/mem16 ; 段内间接调用,ip入栈
call mem32 ; 段间间接调用,cs和ip入栈

CPU执行call指令时,分两步操作:

  1. ip(16位操作)或cs:ip(32位操作)入栈
  2. 转移
1
2
ret ; 近转移
retf ; 远转移

CPU执行ret指令时,相当于

1
pop ip

CPU执行retf指令时,相当于

1
2
pop ip
pop cs

call指令与ret指令必须配合使用。

标志处理指令

指令 功能
clc cf = 0
stc cf = 1
cmc cf = not cf
cld df = 0
std df = 1
cli if = 0
sti if = 1

串处理指令

串操作指令有以下特点:

  1. si 寄存器寻址源操作数,用 di 寄存器寻址目的操作数
  2. 源操作数隐含的段寄存器为 ds,但允许段超越;目的操作数的段寄存器约定为 es,不允许段超越
  3. 每当串操作指令执行后,自动执行源变址或目的变址,当 df=0 时,地址增量为正,否则为负。增量的大小与操作数类型有关,字节为1,字为2,双字为4

※ 这也表明了为什么si是源变址寄存器,di是目的变址寄存器,而ds为数据段,es为附加段。

1. rep(重复串操作直到cx为0)

rep常与 [movs,stos,lods,ins,outs] 指令配合使用。

1
rep string op[movs/stos/lods/ins/outs]

执行过程如下:

  1. cx=0,退出rep,否则往下执行
  2. dec cx
  3. 执行 string op
  4. 返回 1

2. movs(串传送)

movs后加上b,w等表示操作类型为字节

1
2
movsb dst, src ; 传送字节
movsw dst, src ; 传送字

作用: es:[di] = ds:si,将ds:si所指的串复制cx个字节/字到es:di所指的内存单元中,当df=0时,每次操作后sidi递增size,否则递减size。其中,size等于1(字节)或2(字)。

例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
assume cs:code, ds:data, es:extra
data segment
srcstr db 'hello world!$'
data ends
extra segment
dststr db 13 dup(0)
extra ends
code segment
main:
mov ax, data
mov ds, ax
mov ax, extra
mov es, ax
lea si, srcstr
lea di, dststr
mov cx, 13
cld
rep movsb
lea dx, dststr
mov ah, 9
int 21h
mov ax, 4c00h
int 21h
code ends
end main

3. lods(串载入)/ stos(串存储)

1
2
lodsb ; 载入字节
lodsw ; 载入字

作用:将 ds:si 所指串的值复制到 al/ax 中,然后根据df增加或减少si

1
2
stosb ; 存入字节
stosw ; 存入字

作用:将 al/ax 的值 复制到 es:di 所指的内存单元中,然后根据df增加或减少di

例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
assume cs:code, es:extra
extra segment
buf db 10 dup(0)
extra ends
code segment
main:
mov ax, extra
mov es, ax
mov ax, 20h
lea di, buf
mov cx, 10
cld
rep stosb
mov ax, 4c00h
int 21h
code ends
end main

4. cmps(串比较)

1
2
cmpsb ; 比较源串与目的串的一个字节
cmpsw ; 比较源串与目的串的一个字

作用:将 ds:si 所指串的值与 es:di 所指串的值进行比较,并根据比较结果(两个值相减)设置标志位,然后,对 sidi 做相应的调整。

-------------------------------- 全文完 感谢您的阅读 --------------------------------
「写的那么辛苦,连一块钱都不打赏吗/(ㄒoㄒ)/~~」