顺序程序设计 使用汇编些顺序程序时,要注意指令的先后顺序,写代码时有些指令顺序可以前后颠倒,有些则不行。此外,还需要注意顺序的优化,充分利用前面指令的处理结果,尽量避免重复操作。
例1 设 X 和 Y 均为16位无符号数,写一个求表达式 16X+Y 值的程序。
程序逻辑结构图
加法运算 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 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 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 进制数转换成七段数码管
程序逻辑结构图
查表法 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)值的程序。
程序逻辑结构图
代码 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 实现三个无符号数的有大到小的排序
程序逻辑结构图
寄存器数据交换 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 码的程序。
程序逻辑结构图
算法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 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 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 个字的字校验和。
程序逻辑结构图
代码 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 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 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位十进制数,并输出。
程序逻辑结构图
循环中有这行代码 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 把一个字符串中的所有大写字母改写成小写。
程序逻辑结构图
代码 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 单元
程序逻辑结构图
代码 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 程序逻辑结构图
代码 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 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 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。
程序逻辑结构图
代码 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