啥都不会 发表于 2022-8-15 01:35

8086汇编-程序设计

本帖最后由 啥都不会 于 2022-8-15 10:10 编辑

前言:
这篇笔记主要学习8086汇编程序设计。参考自 "杨季文《80x86汇编语言程序设计》"

每个人的思路想法都是不一样的,不建议大家照着我写的代码抄。不论用什么语言,写代码只是将我们的思路以代码的形式写出来。因此在写代码之前,要先把思路、算法、程序逻辑结构图都理出来,不然直接蒙头写代码很容易出错。
编程语言:
汇编语言

以下为主题内容:

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

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

程序逻辑结构图


加法运算

;程序名:T3-2.asm
;算法1:加法运算
;功能:计算 16X+Y(X 和 Y 均为 16 位无符号数)。
DESG SEGMENT
X DW2345H
Y DW5678H
Z DD?
DESG    ENDS

CSEG SEGMENT
    ASSUMEcs: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

移位法

;程序名:T3-2-1.asm
;算法2:移位法
;程序结构:顺序结构
;功能:计算 16X+Y(X 和 Y 均为 16 位无符号数),使用移位法运算。
DESG SEGMENT
XXX DW2345H
YYY DW5678H
ZZZ DD?
DESG    ENDS

CSEG SEGMENT
    ASSUMEcs: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


乘法指令



;程序名:T3-2-2.asm
;算法3:乘法运算
;程序结构:顺序结构
;功能:计算 16X+Y(X 和 Y 均为 16 位无符号数),使用mul指令。
DESG SEGMENT
XXX DW2345H
YYY DW5678H
ZZZ DD?
result dw 0,0
db 24h
DESG    ENDS

CSEG SEGMENT
    ASSUMEcs: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. 程序逻辑结构图


2. 代码
;程序名: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. 程序逻辑结构图


2. 代码
;程序名: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.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
    mov ah,2
    int 21h
    ;
    mov ax,4c00h
    int 21h

code ends
    end start


查表指令


;程序名: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.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
    mov ANSWER,ax
    mov ax,4c00h
    int 21h
code ends
    end start

分支程序设计

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

程序逻辑结构图


寄存器数据交换

;程序名: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,
    mov bl,
    mov cl,
    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 ,al
    mov ,bl
    mov ,cl
    mov ax,4c00h
    int 21h
code ends
    end start


内存数据交换

;程序名: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
    cmp al,
    jae next1
    xchg al,
    xchg ,al
next1:
    mov al,buffer
    cmp al,
    jae next2
    xchg ,al
    xchg ,al
next2:
    mov ax,
    cmp al,ah
    jae next3
    xchg al,ah
    mov ,ax
next3:
    mov ax,4c00h
    int 21h
code ends
    end start


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

程序逻辑结构图


算法1


;程序名: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

;程序名: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. 程序逻辑结构图


2. 代码
;程序名:T3-8.asm
;功能:写一个实现把一位十六进制数所对应的 ASCII 码转换为十六进制数的程序。如果要转换的ASCII码没有对应的十六进制码,则转换为特殊值负1
assume ds:data,cs:code

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

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. 程序逻辑结构图


2. 代码
;程序名:T3-8-1.asm
;功能:写一个实现把一位十六进制数所对应的 ASCII 码转换为十六进制数的程序。
assume ds:data,cs:code

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

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.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:
    add si,2
    loop summer
    mov sum,ax
    mov ax,4c00h
    int 21h
code ends
end start


例2
不使用乘法实现乘法运算

累加法

1. 程序逻辑结构图


2. 代码

;程序名: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. 程序逻辑结构图



2. 代码

;程序名: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位十进制数,并输出。


程序逻辑结构图


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

代码


;程序名: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
    div bx
    add ax,30h
    pop bx
    mov result,al
    add si,2
    inc bx
    push bx
divs:
    mov ax,dx
    xor dx,dx
    mov bx,jm
    div bx
    add ax,30h
    pop bx
    mov result,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。

;程序名: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,
    div cx
    add al,30h
    mov ,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
之前是利用商作为结果来存储,这里使用余数作为结果来存储。这种方法大大减少了代码,不需要再去到内存中一一读取除数。

写代码时,多换几种思路会减少很多麻烦。同时你所理解的知识多少,也影响写代码的思路。

;程序名: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,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.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
    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.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,
    cmp ah,al
    jnz loops
    inc di
    mov ,si
loops:
    inc si
    loop find
    mov di,03FEh
    mov dh,
    cmp dh,ah
    jz stop
    mov dx,-1
    mov ,dx
stop:
    mov ax,4c00h
    int 21h
code ends
    end start


例6

设缓冲区 DATA 中有一组单字节有符号数,以0为结束标志。把前5个正数依次送入缓冲区 PDATA,把前 5 个负数依次送入缓冲区MDATA;如正数或负数不足5个,则用 0 补足。

程序逻辑结构图


代码

;程序名: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
    cmp al,0
    jz supp1
    and al,80h
    cmp al,0
    jnz pnum
    mov al,DATA1
    mov MDATA,al
    inc di
    inc si
    loop mnum
    jmp supp1
pnum:
    mov al,DATA1
    mov PDATA,al
    inc bx
    inc si
    loop mnum
supp1:
    mov ax,5
    sub ax,di
    jz supp2
    mov cx,ax
P0:
    mov PDATA,0
    inc di
    loop P0
supp2:
    mov ax,5
    sub ax,bx
    jz stop
    mov cx,ax
m0:
    mov MDATA,0
    inc bx
    loop m0
stop:
    mov ax,4c00h
    int 21h
code ends
    end start

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

算法1

1. 程序逻辑结构图


2. 代码

;程序名: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,
    cmp al,
    jbe nextJ
    xchg al,
    mov ,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
    add dl,30h
    mov ah,2
    int 21h
    inc si
    loop print
    ;
    mov ax,4c00h
    int 21h
cseg ends
end start


算法2

1. 程序逻辑结构图


2. 代码

;程序名: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
    cmp al,number       ;第一个数(a)和第二个数(b)进行比较
    jnb move                ;如果 a>b,交换数据
    dec cx                  ;循环次数-1
    jz reset                ;内循环结束后,初始化数据,准备外循环
    jmp L2                  ;不交换数据,继续内循环
move:
    xchg al,number
    mov number,al
    loop L2               ;交换数据,继续内循环
reset:
    inc bx
    xor si,si
    jmp L0
output:
    xor si,si
    mov cx,10
print:
    mov dl,number
    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.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
    cmp bl,0
    jz stop
    mov al,char2
    cmp al,bl
    jz find
    inc si
    jmp not_find
find:
    inc si
    mov bl,char1
    inc di
    mov al,char2
    cmp al,bl
    jnz not_find
    loop find
    mov flag,1
stop:
    mov ax,4c00h
    int 21h
code1 ends
end start

小声点我布隆 发表于 2022-8-15 20:38

逻辑是真的清晰,拜谢大佬!

sjtkxy 发表于 2022-9-30 05:25

龍自在 发表于 2022-10-7 15:20

汇编更能体现地址的运用

后学真 发表于 2022-10-7 16:00

程序设计,难度很高,谢谢老师分享

吾爱稀饭 发表于 2022-10-11 23:26

感谢分享
页: [1]
查看完整版本: 8086汇编-程序设计