8086汇编-程序设计
9unk Lv5

顺序程序设计

使用汇编些顺序程序时,要注意指令的先后顺序,写代码时有些指令顺序可以前后颠倒,有些则不行。此外,还需要注意顺序的优化,充分利用前面指令的处理结果,尽量避免重复操作。

例1

设 X 和 Y 均为16位无符号数,写一个求表达式 16X+Y 值的程序。

程序逻辑结构图

T3-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
32
33
;程序名:T3-2.asm
;算法1:加法运算
;功能:计算 16X+Y(X 和 Y 均为 16 位无符号数)。
DESG SEGMENT
X DW 2345H
Y DW 5678H
Z DD ?
DESG ENDS

CSEG SEGMENT
ASSUME cs:CSEG,ds:DESG
start:
mov AX,DESG
mov DS,AX
mov AX,X
xor DX,DX
add AX,AX ;x * 2
adc dx,dx
add ax,ax ;x * 4
adc dx,dx
add ax,ax ;x * 8
adc dx,dx
add ax,ax ;x * 16
adc dx,dx
add ax,Y ;在 x*16的结果上加上y
adc dx,0
mov word ptr Z,ax
mov word ptr Z+2,dx

mov ax,4c00h
int 21h
CSEG ENDS
END start

移位法

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
32
33
34
35
36
37
38
;程序名:T3-2-1.asm
;算法2:移位法
;程序结构:顺序结构
;功能:计算 16X+Y(X 和 Y 均为 16 位无符号数),使用移位法运算。
DESG SEGMENT
XXX DW 2345H
YYY DW 5678H
ZZZ DD ?
DESG ENDS

CSEG SEGMENT
ASSUME cs:CSEG,ds:DESG
start:
mov AX,DESG
mov DS,AX
mov ax,xxx
mov dl,ah
;这两段指令操作是一样的,只不过一个是手写4次;另一个是让CPU自行循环重复执行4次。
;shl ax,1
;adc dx,0
;shl ax,1
;adc dx,0
;shl ax,1
;adc dx,0
;shl ax,1
;adc dx,0
mov cx,4
shl ax,cl
shr dx,cl
mov bx,yyy
add ax,bx
mov word ptr zzz,ax
mov word ptr zzz+2,dx
;
mov ax,4c00h
int 21h
CSEG ends
end start

乘法指令

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
32
33
34
;程序名:T3-2-2.asm
;算法3:乘法运算
;程序结构:顺序结构
;功能:计算 16X+Y(X 和 Y 均为 16 位无符号数),使用mul指令。
DESG SEGMENT
XXX DW 2345H
YYY DW 5678H
ZZZ DD ?
result dw 0,0
db 24h
DESG ENDS

CSEG SEGMENT
ASSUME cs:CSEG,ds:DESG
start:
mov AX,DESG
mov DS,AX
mov ax,16
;
;mov bx,xxx
;mul bx
mul xxx
;
;mov cx,yyy
;add ax,cx
add ax,yyy
adc dx,0
mov word ptr zzz,ax
mov word ptr zzz+2,dx
;
mov ax,4c00h
int 21h
CSEG ends
end start

代码越短并不意味着执行速度越快,因为一条乘除法指令所花的时间较多。当乘数是2的倍数时,往往可使用移位指令实现乘法运算;当乘数较小时,往往可采用加法实现乘法运算;对执行速度要求不大的情况下,可直接使用乘法指令实现乘法运算。

例2

把压缩存放的 8421 BCD码,转换为对应十进制数字 ASCII 码的程序。

8421 BCD码就是,将4位二进制数,转换为1位十进制的编码方式
图片

所谓压缩存放是指一个字节中存放两个BDC码,即低4位存放一个BCD码,高4位存放一个BCD码。如果仅仅低4位存放一个BCD码,就称为非压缩BCD码。

算法1

  1. 程序逻辑结构图

T3-3

  1. 代码
    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
    32
    33
    ;程序名:T3-3.asm
    ;功能:把压缩存放的 8421 BCD码,转换为对应十进制数字 ASCII 码的程序。
    ;算法1:使用左移+与运算
    assume cs:code,ds:data

    data segment
    number db 12h
    result db 0,0,'$'
    data ends

    code segment
    start:
    mov ax,data
    mov ds,ax
    ;
    mov al,number
    mov cl,4
    shr al,cl
    add al,30h
    mov result,al
    mov al,number
    and al,0fh
    add al,30h
    mov result+1,al
    ;
    mov dx,offset result
    mov ah,9
    int 21h
    ;
    mov ax,4c00h
    int 21h
    code ends
    end start

算法2

  1. 程序逻辑结构图

T3-3-1

  1. 代码
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
32
;程序名:T3-3-1.asm
;功能:把压缩存放的 8421 BCD码,转换为对应十进制数字 ASCII 码的程序。
;算法2:使用循环右移+右移
assume cs:code,ds:data

data segment
number db 12h
result dw 0
db '$'
data ends

code segment
start:
mov ax,data
mov ds,ax
;
xor ax,ax
mov al,number
mov cl,4
ror ax,cl
shr ah,cl
add ax,3030h
mov result,ax
;
mov dx,offset result
mov ah,9
int 21h
;
mov ax,4c00h
int 21h
code ends
end start

注意:ah是高4位,al是低4位,计算机输出是从低内存数到高内存数打印。即低4位是31h,高4位是32h

例3

把 16 进制数转换成七段数码管

程序逻辑结构图

T3-4

查表法

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
32
;程序名:T3-4.asm
;功能:把 16 进制数转换成七段数码管并输出
;============================================
;算法一:查表法(类似于数组)
assume cs:code,ds:data

data segment
tab db 1000000B,1111001B,0100100B,0110000B
db 0011001B,0010010B,0000010B,1111000B
db 00000000B,0010000B,0001000B,0000011B
db 1000110B,0100001B,0000110B,0001110B
number db 0
result db 0
data ends

code segment
start:
mov ax,data
mov ds,ax
;
xor bx,bx
mov bx,number
;
mov dl,tab[bx]
mov ah,2
int 21h
;
mov ax,4c00h
int 21h

code ends
end start

查表指令

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
;程序名:T3-4-1.asm
;功能:把 16 进制数转换成七段数码管并输出
;============================================
;方法二:查表指令xlat
assume cs:code,ds:data

data segment
tab db 1000000B,1111001B,0100100B,0110000B,0011001B,0010010B,0000010B,1111000B,00000000B,0010000B,0001000B,0000011B,1000110B,0100001B,0000110B,0001110B
number db 0
result db 0
data ends

code segment
start:
mov ax,data
mov ds,ax
;
mov bx,offset tab ;bx为首地址
mov al,number ;al为偏移地址
and al,0fh ;number 最大值是 F(16)
xlat ;取出偏移地址(al)的值,传给al寄存器
;
mov dl,al
mov ah,2
int 21h
;
mov ax,4c00h
int 21h

code ends
end start

例4

设X是一个1~10之间的整数,写一个求函数Y=LG(X)值的程序。

程序逻辑结构图

T3-5

代码

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
;程序名:T3-5.asm
;例4:设X是一个1~10之间的整数,写一个求函数Y=LG(X)值的程序。
;求1~10的对数值,以10为底的对数在0~1之间,为了表示方便和考虑精度,对数值放大10000倍。

assume cs:code,ds:data

data segment
VLAUE DB 4
ANSWER DW ?
TAB DW 0,3010,4771,6021,6990,7782,8451,9031,9542,10000 ;对数表
data ends

code segment
start:
mov ax,data
mov ds,ax
;
xor ax,ax
mov al,VLAUE
dec ax
add ax,ax
mov bx,ax
mov ax,TAB[bx]
mov ANSWER,ax
mov ax,4c00h
int 21h
code ends
end start

分支程序设计

例1

实现三个无符号数的有大到小的排序

程序逻辑结构图

T3-6

寄存器数据交换

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
32
33
34
35
36
37
;程序名:T3-6.asm
;功能:实现三个无符号数的有大到小的排序
;方法一:使用寄存器实现数据交换
assume cs:code,ds:data

data segment
buffer db 87,234,123
data ends

code segment
start:
mov ax,data
mov ds,ax
;
mov si,offset buffer
mov al,[si]
mov bl,[si+1]
mov cl,[si+2]
cmp al,bl
jae next1
xchg al,bl
next1:
cmp al,cl
jae next2
xchg al,cl
next2:
cmp bl,cl
jae next3
xchg bl,cl
next3:
mov [si],al
mov [si+1],bl
mov [si+2],cl
mov ax,4c00h
int 21h
code ends
end start

内存数据交换

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
32
33
34
35
36
;程序名:T3-6-1.asm
;功能:实现三个无符号数的有大到小的排序
;方法二:使用内存实现数据交换
assume cs:code,ds:data

data segment
buffer db 87,123,234
data ends

code segment
start:
mov ax,data
mov ds,ax
;
mov al,buffer[si]
cmp al,[si+1]
jae next1
xchg al,[si+1]
xchg [si],al
next1:
mov al,buffer[si]
cmp al,[si+2]
jae next2
xchg [si+2],al
xchg [si],al
next2:
mov ax,[si+1]
cmp al,ah
jae next3
xchg al,ah
mov [si+1],ax
next3:
mov ax,4c00h
int 21h
code ends
end start

例2

实现把一个十六进制数转换为对应的 ASCII 码的程序。

程序逻辑结构图

T3-7

算法1

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
;程序名:T3-7.asm
;功能:实现把一个十六进制数转换为对应的 ASCII 码的程序。
;方法一:分开计算,数字+30h,字母+37h
assume ds:data,cs:code

data segment
number db 0Fh
data ends

code segment
start:
mov ax,data
mov ds,ax
;
mov al,number
and al,0fh
cmp al,0ah
jb num_add
add al,37h
mov dl,al
jmp output
num_add:
add al,30h
mov dl,al
output:
mov ah,2
int 21h
mov ax,4c00h
int 21h
code ends
end start

算法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
;程序名:T3-7-1.asm
;功能:实现把一个十六进制数转换为对应的 ASCII 码的程序。
;方法二:分开计算,如果是字母+7h,再加30h;如果是数字+30h
assume ds:data,cs:code

data segment
number db 0Fh
data ends

code segment
start:
mov ax,data
mov ds,ax
;
mov al,number
and al,0fh
cmp al,0ah
jb num
add al,7
num:
add al,30h
mov dl,al
output:
mov ah,2
int 21h
mov ax,4c00h
int 21h
code ends
end start

例3

写一个实现把一位十六进制数所对应的 ASCII 码转换为十六进制数的程序。

方法1

存入一个 ASCII,先判断是否为数字(是 -30h),再判断是否为大写字母(是 -37h),再判断是否为小写字母(是 -57h),最后输出结果。

  1. 程序逻辑结构图

T3-8

  1. 代码
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
;程序名:T3-8.asm
;功能:写一个实现把一位十六进制数所对应的 ASCII 码转换为十六进制数的程序。如果要转换的ASCII码没有对应的十六进制码,则转换为特殊值负1
assume ds:data,cs:code

data segment
ascii db '$'
err db '-','1','$'
data ends

code segment
start:
mov ax,data
mov ds,ax
;
mov dl,ascii
cmp dl,'0'
jb error
cmp dl,'9'
ja char_A
sub dl,30h
jmp output
char_A:
cmp dl,'A'
jb error
cmp dl,'F'
ja char_aa
sub dl,37h
jmp output
char_aa:
cmp dl,'a'
jb error
cmp dl,'f'
ja error
sub dl,57h
jmp output
error:
xor dh,dh
mov dh,-1
output:
cmp dh,-1
jz char_error
cmp dl,9
ja char
add dl,30h
char:
add dl,37h
;
mov ah,2
int 21h
jmp stop
char_error:
mov dx,offset err
mov ah,9
int 21h
stop:
mov ax,4c00h
int 21h
code ends
end start

这段代码的问题是,一直在重复判断,重复运算。写了很多冗余代码

方法2

  1. 程序逻辑结构图

T3-8-1

  1. 代码
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
;程序名:T3-8-1.asm
;功能:写一个实现把一位十六进制数所对应的 ASCII 码转换为十六进制数的程序。
assume ds:data,cs:code

data segment
ascii db 'g'
err db '-','1','$'
data ends

code segment
start:
mov ax,data
mov ds,ax
;
mov dl,ascii
sub dl,30h
cmp dl,9
jbe output
cmp dl,0f0h
ja error
char_a:
sub dl,7
cmp dl,0ah
jb error
cmp dl,0fh
jbe output
cmp dl,0f0h
ja error
char_AA:
sub dl,20h
cmp dl,0ah
jb error
cmp dl,0fh
jbe output
jmp error
output:
mov dl,ascii
mov ah,2
int 21h
jmp stop
error:
mov al,0ffh
mov dx,offset err
mov ah,9
int 21h
stop:
mov ax,4c00h
int 21h
code ends
end start

循环程序设计

例1

求内存中从地址 0040:0000H 开始的 1024 个字的字校验和。

程序逻辑结构图

T3-9

代码

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
;程序名:T3-9.asm
;功能:求内存中从地址 0040:0000H 开始的 1024 个字的字校验和。
assume cs:code,ds:data

data segment
sum dw 0
data ends

code segment
start:
mov ax,data
mov ds,ax
;
mov ax,0040h
mov es,ax
;
xor ax,ax
mov cx,1024
summer:
add ax,es:[si]
add si,2
loop summer
mov sum,ax
mov ax,4c00h
int 21h
code ends
end start

例2

不使用乘法实现乘法运算

累加法

  1. 程序逻辑结构图

T3-10

  1. 代码
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
;程序名:T3-10.asm
;功能:不使用乘法实现乘法运算(累加法)

assume ds:data,cs:code

data segment
x db 234 ;被乘数
y db 125 ;乘数
z dw 0
data ends

code segment
start:
mov ax,data
mov ds,ax
;
mov al,x
xor ah,ah
mov cl,y
xor ch,ch ;设置循环次数
xor dx,dx
muls:
add dx,ax
loop muls
mov z,dx
stop:
mov ax,4c00h
int 21h
code ends
end start

位移相加法

  1. 程序逻辑结构图

T3-10-1

  1. 代码
    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
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    ;程序名:T3-10-1.asm
    ;功能:不使用乘法实现乘法运算(位移相加法)
    ;例:AX(乘数)、bl(被乘数),dx(乘积)
    ;此时 bl=4=0100,ax=12=2^0, dx=0
    ;bl 右移1位,发现是0,也就是被乘数比2^0大
    ;既然被乘数不是2^0,那有可能是2^1,那么 ax 提前累加,ax=ax+ax=24
    ;bl 右移1位,发现是0,也就是被乘数比2^1大
    ;那么 ax 提前累加,ax=ax+ax=48
    ;bl 右移1位,发现是1,也就是被乘数包含2^2,那么 dx(乘积) = ax+dx=48
    ;就这样,循环8次,只要 bl 的 bit 位是1,ax的累加值就放到乘积dx中;反之ax继续累加,直到循环结束

    assume ds:data,cs:code

    data segment
    x db 234 ;被乘数
    y db 125 ;乘数
    z dw 0
    data ends

    code segment
    start:
    mov ax,data
    mov ds,ax
    ;
    mov al,x
    xor ah,ah
    mov bl,y
    xor dx,dx
    mov cx,8 ;按位相加运算,两个都是 8 位的值
    muls:
    shr bl,1
    JNC next ;乘数右移一位,如果溢出说明该值是1
    add dx,ax ;溢出 dx=dx+ax
    next:
    add ax,ax ;没有溢出 ax*2
    loop muls
    mov z,dx
    stop:
    mov ax,4c00h
    int 21h
    code ends
    end start

例3

把一个16位二进制数转换为一个5位十进制数,并输出。

程序逻辑结构图

T3-11

循环中有这行代码 mov ax,dx,当时考虑到 “被除数不能是0”,所以把第一次计算排除在循环中。

代码

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
;程序名:T3-11.asm
;功能:把一个16位二进制数转换为一个5位十进制数,并输出。
;算法:假设X为12345,除以 10000,1000,100,10,1 获取商进行输出
assume ds:data,cs:code

data segment
number dw 0ABCDh
result db 0,0,0,0,0,'$'
jm dw 10000,1000,100,10,1
data ends

code segment
start:
mov ax,data
mov ds,ax
;
mov ax,number
mov bx,0
push bx
xor dx,dx
xor si,si
mov cx,4
;
mov bx,jm[si]
div bx
add ax,30h
pop bx
mov result[bx],al
add si,2
inc bx
push bx
divs:
mov ax,dx
xor dx,dx
mov bx,jm[si]
div bx
add ax,30h
pop bx
mov result[bx],al
add si,2
inc bx
push bx
loop divs
;
mov dx,offset result
mov ah,9
int 21h
;
mov ax,4c00h
int 21h
code ends
end start

优化1

利用di作为循环次数,cx作为除数,bx和si存储偏移地址,同时把 “divs” 标号,上面一段代码去掉。

去掉第一段代码的方法:把原始的 “被除数” 作为 “余数” 看待,提前把这个值传给dx。

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
;程序名:T3-11-1.asm
;功能:把一个16位二进制数转换为一个5位十进制数,并输出。
;算法:假设X为12345,除以 10000,1000,100,10,1 获取商进行输出
;优化1:不使用loop 指令,可优化掉大多数重复指令
assume ds:data,cs:code

data segment
number dw 0ABCDh
result db 0,0,0,0,0,'$'
jm dw 10000,1000,100,10,1
data ends

code segment
start:
mov ax,data
mov ds,ax
;
mov ax,number
lea bx,jm
lea si,result
;初始化
mov dx,ax ;备份要转换的值
mov di,si
add di,5 ;定义循环次数
L1:
mov ax,dx ;每次循环将余数传给ax
xor dx,dx ;div使用 DX:AX 除以16位,需要将dx置为0(被除数扩展)
;div指令除以16位,商在ax中,余数在dx中
mov cx,[bx]
div cx
add al,30h
mov [si],al
inc si
add bx,2
cmp si,di
jnz L1
sub si,5
;
mov dx,offset result
mov ah,9
int 21h
;
mov ax,4c00h
int 21h
code ends
end start

优化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
32
33
34
;程序名:T3-11-2.asm
;功能:把一个16位二进制数转换为一个5位十进制数,并输出。
;算法:假设X为12345,每次循环除以 10,获取余数进行输出
;优化2:使用余数来处理,省掉除数列表
assume cs:code,ds:data

data segment
number dw 0ABCDh
result db 0,0,0,0,0,'$'
data ends

code segment
start:
mov ax,data
mov ds,ax
;
mov di,5
mov cx,10
mov ax,number
L1:
xor dx,dx
div cx
add dl,30h
mov result[di-1],dl ;用di判断循环,但是存储结果di需要减1
dec di
jnz L1
;
lea dx,result
mov ah,9
int 21h
mov ax,4c00h
int 21h
code ends
end start

例4

把一个字符串中的所有大写字母改写成小写。

程序逻辑结构图

T3-12

代码

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
32
33
34
35
36
;程序名:T3-12.asm
;功能:把一个字符串中的所有大写字母改写成小写。

assume ds:data,cs:code

data segment
char db 'HOW are yoU !',0
data ends

code segment
start:
mov ax,data
mov ds,ax
;
char_A:
mov dl,char[si]
cmp dl,0
jz stop
;
cmp dl,41h
jb output
cmp dl,5Ah
ja output
add dl,20h
;
output:
inc si
mov ah,2
int 21h
jmp char_A
;
stop:
mov ax,4c00h
int 21h
code ends
end start

例5

判定从地址 0040:0000H 开始的 2048 个内存字节单元中是否有字符 ‘A’。
如有则把第一个(按地址由小到大为序)含此指定字符的存储单元的地址偏移送到 0000:03FEH 单元中
如果没有把特征值 0FFFFH 送到 0000:03FEH 单元

程序逻辑结构图

T3-13

代码

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
;程序名:T3-13.asm
;功能:判定从地址 0040:0000H 开始的 2048 个内存字节单元中是否有字符 'A'。
;如有则把第一个(按地址由小到大为序)含此指定字符的存储单元的地址偏移送到 0000:03FEH 单元中
;如果没有把特征值 0FFFFH 送到 0000:03FEH 单元

assume cs:code
;常量定义
segaddr = 40h ;源地址段值
offaddr = 0 ;源地址偏移
count = 2048 ;长度(计数)
keychar = 'A' ;指定字符
segresu = 0 ;目的保存单元段值
offresu = 03FEh ;目的保存单元偏移

code segment
start:
mov ax,segaddr
mov ds,ax
mov ax,offaddr
mov si,ax
mov ax,segresu
mov es,ax
mov ax,offresu
mov di,ax
mov cx,count
mov ah,keychar
;
find:
mov al,[si]
cmp ah,al
jnz loops
inc di
mov [di],si
loops:
inc si
loop find
mov di,03FEh
mov dh,[di]
cmp dh,ah
jz stop
mov dx,-1
mov [di],dx
stop:
mov ax,4c00h
int 21h
code ends
end start

例6

程序逻辑结构图

T3-14

代码

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
;程序名:T3-14.asm
;功能:设缓冲区 DATA 中有一组单字节有符号数,以0为结束标志。
;程序功能:把前5个正数依次送入缓冲区 PDATA,把前 5 个负数依次送入缓冲区MDATA;如正数或负数不足5个,则用 0 补足

assume cs:code,ds:data

data segment
DATA1 db 1,2,-1,3,-4,-5,0
PDATA db 0Ch,0Ch,0Ch,0Ch,0Ch
MDATA db 0Ch,0Ch,0Ch,0Ch,0Ch
data ends

code segment
start:
mov ax,data
mov ds,ax
mov es,ax
;
mov cx,10
xor bx,bx
mnum:
mov al,DATA1[si]
cmp al,0
jz supp1
and al,80h
cmp al,0
jnz pnum
mov al,DATA1[si]
mov MDATA[di],al
inc di
inc si
loop mnum
jmp supp1
pnum:
mov al,DATA1[si]
mov PDATA[bx],al
inc bx
inc si
loop mnum
supp1:
mov ax,5
sub ax,di
jz supp2
mov cx,ax
P0:
mov PDATA[di],0
inc di
loop P0
supp2:
mov ax,5
sub ax,bx
jz stop
mov cx,ax
m0:
mov MDATA[BX],0
inc bx
loop m0
stop:
mov ax,4c00h
int 21h
code ends
end start

例7

设 BUFFER 缓冲区中有10各单字节无符号整数,写一个程序将他们由小到大排序

算法1

  1. 程序逻辑结构图

T3-15

  1. 代码
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
;程序名:T3-15.asm
;功能:说明二重循环的实现
;算法:简单选择法
assume cs:cseg,ds:dseg

dseg segment
;buffer db 23,12,45,32,127,3,9,58,81,72
number db 4,1,6,0,3,2,9,8,7,5
N EQU 10
dseg ends

cseg segment
start:
mov ax,dseg
mov ds,ax
mov bx,offset number-1
mov si,1
forI:
mov di,si
inc di
forJ:
mov al,[bx+si]
cmp al,[bx+di]
jbe nextJ
xchg al,[bx+di]
mov [bx+si],al
nextJ:
inc di
cmp di,N
jbe forJ
nextI:
inc si
cmp si,N-1
jbe forI
;
xor si,si
mov cx,10
print:
mov dl,number[si]
add dl,30h
mov ah,2
int 21h
inc si
loop print
;
mov ax,4c00h
int 21h
cseg ends
end start

算法2

  1. 程序逻辑结构图

T3-15-2

  1. 代码
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
;程序名:T3-15-2.asm
;功能:设 BUFFER 缓冲区中有10各单字节无符号整数。
;算法一:冒泡排序
assume cs:code,ds:data

data segment
number db 3,4,6,5,7,8,1,2,0,9
;3,4,5,6,7,1,2,0,8,9
data ends

code segment
start:
mov ax,data
mov ds,ax
;
L0:
mov cx,9
L1:
sub cx,bx ;BX 表示外循环次数
jz output ;外循环结束后,结束程序
L2:
inc si
mov al,number[si-1]
cmp al,number[si] ;第一个数(a)和第二个数(b)进行比较
jnb move ;如果 a>b,交换数据
dec cx ;循环次数-1
jz reset ;内循环结束后,初始化数据,准备外循环
jmp L2 ;不交换数据,继续内循环
move:
xchg al,number[si]
mov number[si-1],al
loop L2 ;交换数据,继续内循环
reset:
inc bx
xor si,si
jmp L0
output:
xor si,si
mov cx,10
print:
mov dl,number[si]
add dl,30h
mov ah,2
int 21h
inc si
loop print
;
mov ax,4c00h
int 21h
code ends
end start

例8

分别有两个以0结尾的字符串在不同的数据段中。如果数据段1的字符串,包含了数据段2的字符串,flag变量置为1,否则将其清0。

程序逻辑结构图

T3-16

代码

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
;程序名:T3-16.asm
;功能:分别有两个以0结尾的字符串在不同的数据段中。如果数据段1的字符串,包含了数据段2的字符串,flag变量置为1,否则将其清0。
assume cs:code1,ds:data1,es:data2

data1 segment
char1 db 'welcome to masm!',0
data1 ends

data2 segment
char2 db 'masm',0
len = ($ - char2)-1
flag db 0
data2 ends


code1 segment
start:
mov ax,data1
mov ds,ax
mov ax,data2
mov es,ax
;
mov cx,len-1
not_find:
xor di,di
mov bl,char1[si]
cmp bl,0
jz stop
mov al,char2[di]
cmp al,bl
jz find
inc si
jmp not_find
find:
inc si
mov bl,char1[si]
inc di
mov al,char2[di]
cmp al,bl
jnz not_find
loop find
mov flag,1
stop:
mov ax,4c00h
int 21h
code1 ends
end start
  • 本文标题:8086汇编-程序设计
  • 本文作者:9unk
  • 创建时间:2022-08-09 10:09:00
  • 本文链接:https://9unkk.github.io/2022/08/09/8086-hui-bian-cheng-xu-she-ji/
  • 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!