流程转移与子程序

jmp

段内转移:只修改ip,例如jmp ax
段间转移:修改cs:ip,例如jmp 1000:0(debug使用,源程序不可以使用)

jmp 标号

  • jmp far ptr 标号;段间转移
  • jmp short 标号;段内短转移
  • jmp near ptr 标号;段内近转移

jcxz 标号
如果cx = 0,跳转到标号处执行

call和ret

call 标号;跳转到标号处执行
ret;返回调用处

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
assume cs:code
data segment
db 'conversation',0;0用来标定字符串的结束
data ends
code segment
start: mov ax,data
moc ds,ax
mov si,0
call capital
mov ax,4c00h
int 21h

capital:mov cl,[si]
mov ch,0
jcxz ok;如果cx = 0,即到了字符串结尾
and byte ptr [si],11011111b
inc si
jmp short capital
ok: ret
code ends
end start

寄存器冲突问题

子程序使用的寄存器可能造成调用程序寄存器值的丢失,所谓寄存器冲突

解决方案,调用子程序首先备份所使用的寄存器到栈,子程序结束时再出栈

子程序开始: 子程序使用的寄存器入栈
子程序内容
子程序使用的寄存器出栈
ret

标志寄存器

flag寄存器按位起作用

首字母 标志 值为1 值为0 意义
Overflow OF OV NV 溢出
Direction DF DN UP 方向
Sign SF NG PL 符号
Zero ZF ZR NZ 零值
Parity PF PE PO 奇偶
Carry CF CY NC 进位

带进位的加减法

adc al,3

(al)=(al)+3+(CF)

sbb ax,bx

(ax)=(ax)-(bx)-

cmp命令

cmp ah,bh

关系 (ax)-(bx)特点 标志寄存器
(ah)=(bh) 结果为0 ZF=1
(ah)!=(bh) 结果不为0 ZF=0
(ah)<(bh) 借位 CF=1
(ah)>=(bh) 不借位 CF=0
(ah)>(bh) 既不借位,又不为0 CF=0且ZF=0
(ah)<=(bh) 或借位,或为0 CF=1或ZF=1
1
2
3
4
5
6
    cmp ah,bh
je s
add ah,bh
jmp short ok
s: add ah,ah
ok: ret

相当于

1
2
3
4
5
6
7
8
if(a==b)
{
a = a + a;
}
else
{
a = a + b;
}

DF标志和串传送指令

对DF标志进行设置

  1. cld;将DF设为0
  2. std;将DF设为1

串传送

movsb

(1)((es)*16 + (di))=((ds)*16+(si))

(2)

  • 如果DF=0,则:(si)=(si)+1, (di)=(di)+1
  • 如果DF=1,则:(si)=(si)-1, (di)=(di)-1

movsw

(1)((es)*16 + (di))=((ds)*16+(si))

(2)

  • 如果DF=0,则:(si)=(si)+2, (di)=(di)+2
  • 如果DF=1,则:(si)=(si)-2, (di)=(di)-2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
assume cs:code,ds:data
data segment
db 'welcome to masm!'
db 16 dup (0)
data ends
code segment
start: mov ax,data
mov ds,ax
mov si,0
mov es,ax
mov di,16
cld

mov cx,16
s: movsb
loop s
mov ax,4c00h
int 21h
code ends
end start

rep movsb(movsw)相当于

1
2
s:movsb(movsw)
loop s