汇编语言八 编写程序实现,将缓冲区BUFFER中的100个字按递增排序

时间:2021-05-02 01:28:07

1.题目要求:
编写程序实现,将缓冲区BUFFER中的100个字按递增排序
2.代码:

DATAS SEGMENT 
A dw 100,344,3435,43433,3438,343,134,80,8,1000,65535,54,45 
N=$-A ;计算数字所占的字节数 
DATAS ENDS 
CODES SEGMENT 
ASSUME CS:CODES,DS:DATAS 
START:MOV AX,DATAS 
MOV DS,AX 
MOV SI,0 ;SI遍历数字;前一个数的地址 
MOV CX,N/2-1 ;设置循环次数,M(M=N/2)个数需要,循环M-1次 
CALL BUBBLE ;调用BUBBLE将原来的数排序 
;输出排序后的数 
MOV CX,N/2 ;循环M次输出排序后的M个数 
MOV SI,0 ;SI遍历排序后的数 
MOV DI,0 ;用DI记录数字的位数 
MOV BP,N+5 ;BP用于遍历存储的转化后的字符的位置 
SHOW: PUSH CX ;循环次数入栈 
MOV DX,0 ;由于将要进行16位除需要置高16位为0 
MOV AX,[SI] ;低16位为排序后的数 
CALL DTOC ;调用DTOC将十进制数转换为字符串 
CALL SHOW_STR ;调用SHOW_STR将一个数转化得到的字符串输出 
ADD SI,2 ;下一个数 
POP CX ;循环次数出栈栈 
LOOP SHOW 

MOV AH,4CH 
INT 21H 
;冒泡排序 
BUBBLE PROC 
L1: PUSH CX ;将循环次数入栈 
LEA SI,A ;SI遍历DATAS数据段的数字 
L2: MOV AX,A[SI] ;将前一个数存于AX 
CMP AX,A[SI+2] ;比较前后两个数 
JBE NEXT ;如果前一个数小于或等于后一个数则继续本轮的比较 
XCHG AX,A[SI+2] ;否则,交换前后两个数的位置 
MOV A[SI],AX 
NEXT:ADD SI,2 ;下一个数 
LOOP L2 ;注意内层循环的次数已经确定了 
POP CX ;将循环次数出栈 
LOOP L1 ;下一轮比较 
RET 
BUBBLE ENDP 

; 将十进制数转换为字符串并储存起来 
DTOC PROC 
S:MOV CX,10 ;将除数10,放入CX中 
CALL DIVDW ;调用DIVDW程序 
ADD CL,30H ;把数字转换为ASCII码,这样就能显示了 
MOV DS:[BP],CL ;把ASCII码放到内存中 
INC DI ;用DI记录循环的次数 
PUSH AX ;将低16位入栈 
ADD AX,DX ;将高位与低位相加,接着判断是否已经除尽 
JZ BACK ;除尽后返回调用处 
POP AX ;将低16位出栈 
DEC BP ;逆序存放转化后的字符,便于主程序调用SHOW_STR 
JMP S 

BACK:POP AX ;为了得到正确的IP值,需要出栈一次 
RET 
DTOC ENDP 

;子程序定义开始,功能是分离被除数的各个位的数字 
;公式:X/N=int(H/N)*65536+[rem(H/N)*65536+L]/N 
DIVDW PROC 
PUSH AX ;低16位入栈 
MOV AX,DX ;将高16位写入AX, 
MOV DX,0 ;将高16位置零 
DIV CX ;将新的数除10, 
MOV BX,AX ;将商int(H/N)转移到BX,默认余数rem(H/N)在DX 
POP AX ;将低16位出栈, 
DIV CX ;将[rem(H/N)*65536+L]除10,默认余数在DX 
MOV CX,DX ;将余数转移到CX 
MOV DX,BX ;将商int(H/N)转移到dx,相当于int(H/N)*65536 
RET ;子程序定义结束 
DIVDW ENDP 



;实现字符串的输出 
SHOW_STR PROC 
S2:MOV AH,2 ;输出数字转化后的字符串 
MOV DL,DS:[BP] 
INT 21H 
INC BP ;顺序输出 
DEC DI ;数字的位数减一 
JZ OK ;字符串输出完了就结束 
JMP S2 ;否则继续输出 

OK:MOV AH,2 ;输出空格 
MOV DL,0 
INT 21H 
RET 
SHOW_STR ENDP 

CODES ENDS 
END START 
;实现冒泡排序,并将排序后的数输出 
DATAS SEGMENT 
A dw 100,344,5483,8627,3542,8733,15243,55,878,3455,65535,87,3453
N=$-A ;计算数字所占的字节数 
DATAS ENDS 

CODES SEGMENT 
ASSUME CS:CODES,DS:DATAS 
START:MOV AX,DATAS 
MOV DS,AX 
MOV SI,0 ;SI遍历数字;前一个数的地址 
MOV CX,N/2-1 ;设置循环次数,M(M=N/2)个数需要,循环M-1次 
CALL BUBBLE ;调用BUBBLE将原来的数排序 
;输出排序后的数 
MOV CX,N/2 ;循环M次输出排序后的M个数 
MOV SI,0 ;SI遍历排序后的数 
MOV DI,0 ;用DI记录数字的位数 
MOV BP,N+5 ;用于遍历存储的转化后的字符的位置 
SHOW: PUSH CX ;循环次数入栈 
MOV DX,0 ;由于将要进行16位除需要置高16位为0 
MOV AX,[SI] ;低16位为排序后的数 
CALL DTOC ;调用DTOC将十进制数转换为字符串 
CALL SHOW_STR ;调用SHOW_STR将一个数转化得到的字符串输出 
ADD SI,2 ;下一个数 
POP CX ;循环次数出栈栈 
LOOP SHOW 

MOV AH,4CH 
INT 21H 

BUBBLE PROC 
L1: PUSH CX ;将循环次数入栈 
LEA SI,A ;SI遍历DATAS数据段的数字 
L2: MOV AX,A[SI] ;将前一个数存于AX 
CMP AX,A[SI+2] ;比较前后两个数 
JBE NEXT ;如果前一个数小于或等于后一个数则继续本轮的比较 
XCHG AX,A[SI+2] ;否则,交换前后两个数的位置 
MOV A[SI],AX 
NEXT:ADD SI,2 ;下一个数 
LOOP L2 ;注意内层循环的次数已经确定了 
POP CX ;将循环次数出栈 
LOOP L1 ;下一轮比较 
RET 
BUBBLE ENDP 
;将十进制数转换为字符串并储存起来 
DTOC PROC 
S:MOV CX,10 ;将除数10,放入CX中 
CALL DIVDW ;调用DIVDW程序 
ADD CL,30H ;把数字转换为ASCII码,这样就能显示了 
MOV DS:[BP],CL ;把ASCII码放到内存中 
INC DI ;用DI记录循环的次数 
PUSH AX ;将低16位入栈 
ADD AX,DX ;将高位与低位相加,接着判断是否已经除尽 
JZ BACK ;除尽后返回调用处 
POP AX ;将低16位出栈 
DEC BP ;逆序存放转化后的字符,便于主程序调用SHOW_STR 
JMP S 
BACK:POP AX ;为了得到正确的IP值,需要出栈一次 
RET 
DTOC ENDP 

;子程序定义开始,功能是分离被除数的各个位的数字 
;公式:X/N=int(H/N)*65536+[rem(H/N)*65536+L]/N 
DIVDW PROC 
PUSH AX ;低16位入栈 
MOV AX,DX ;将高16位写入AX, 
MOV DX,0 ;将高16位置零 
DIV CX ;将新的数除10, 
MOV BX,AX ; 

将商int(H/N)转移到BX,默认余数rem(H/N)在DX 
POP AX ;将低16位出栈, 
DIV CX ;将[rem(H/N)*65536+L]除10,默认余数在DX 
MOV CX,DX ;将余数转移到CX 
MOV DX,BX ;将商int(H/N)转移到dx,相当于int(H/N)*65536 
RET ;子程序定义结束 
DIVDW ENDP 

;实现字符串的输出 
SHOW_STR PROC 
S2:MOV AH,2 ;输出数字转化后的字符串 
MOV DL,DS:[BP] 
INT 21H 
INC BP ;顺序输出 
DEC DI ;数字的位数减一 
JZ OK ;字符串输出完了就结束 
JMP S2 ;否则继续输出 
OK:MOV AH,2 ;输出空格 
MOV DL,0 
INT 21H 
RET 
SHOW_STR ENDP 

CODES ENDS 
END START