我尝试了三种,第一种方法是处理无符号数比较简单的将数据存放在数据段不进行输入,第二种是处理无符号数手动输入数据,第三种是处理有符号数据手动输入。
算法都是一样的,求最值利用的打擂台算法,排序利用的冒泡法。
首先是第一种,
DATAS SEGMENT
;此处输入数据段代码
buf db 90h,20h,46h,80h,59h,78h,34h,00h,12h,88h
db 0ffh,0a4h,04ah,07fh,035h,0c8h,0b3h,0d4h,0e3h
count equ $-buf
max db ?
min db ?
buf2 db 'Please input ten number(0~9):',0dh,0ah,'$'
buf3 db 0ah,'The biggest number is:',0dh,0ah,'$'
buf4 db 0ah,'The smallest number is:',0dh,0ah,'$'
buf5 db 0ah,'The sorted array is:',0dh,0ah,'$'
DATAS ENDS
STACKS SEGMENT
;此处输入堆栈段代码
dw 50 dup(?)
top label byte
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
mov ax,stacks
mov ss,ax
mov sp,offset top
MOV AX,DATAS
MOV DS,AX
;显示内存中所有数据
mov cx,count
lea bx,buf
LOOP1:
mov al,[bx]
CALL show_high
call kong_ge
inc bx
loop loop1
;计算最大数
mov cx,count
lea bx,buf
mov al,[bx]
inc bx
dec cx
again:
cmp al,[bx]
jae next
mov al,[bx]
next:
inc bx
loop again
mov max,al
;显示部分
mov dx,offset buf3
mov ah,9h
int 21h
call show_high
;计算最小数
mov cx,count
lea bx,buf
mov al,[bx]
inc bx
dec cx
again_min:
cmp al,[bx]
jb next_min
mov al,[bx]
next_min:
inc bx
loop again_min
mov min,al
;显示部分
mov dx,offset buf4
mov ah,9h
int 21h
call show_high
;jmp end_pro
mov cx,count-1;cx为比较轮数,大循环次数
loop3:
mov dx,cx;dx表示大循环次数
mov bx,0;地址指针
loop4:
mov al,buf[bx]
cmp al,buf[bx+1]
jbe no_change
xchg al,buf[bx+1]
mov buf[bx],al
no_change:
inc bx
loop loop4
mov cx,dx;一轮比完之后,cx再次赋值比较轮数
loop loop3
;提示语
mov dx,offset buf5
mov ah,9h
int 21h
lea bx,buf
mov cx,count
LOOP5:
mov al,[bx]
CALL show_high
call kong_ge
inc bx
loop loop5
jmp end_pro
show_high proc near;显示字节的高位
mov dh,al
;原先的cx要压栈
push cx
mov cl,04h
and al,0f0h
shr al,cl
pop cx
cmp al,09h
ja special1
add al,30h
output1:
cmp al,30h
jz show_low
mov dl,al
mov ah,02h
int 21h
show_low:;显示字节的低位
mov al,dh
and al,0fh
cmp al,09h
ja special2
add al,30h
output2:
mov dl,al
mov ah,02h
int 21h
ret
special1:
add al,37h
jmp output1
special2:
add al,37h
jmp output2
show_high endp
kong_ge proc near
mov dl,' '
mov ah,02h
int 21h
ret
kong_ge endp
end_pro:
MOV AH,4CH
INT 21H
CODES ENDS
END START
第二种方法是在第一种的基础上的改进最大的区别就是加入了输入和输出函数。我设置的输入十个数,这个可以任意修改。
DATAS SEGMENT
;此处输入数据段代码
buf db 10 dup(?)
count equ $-buf
max db ?
min db ?
buf1 db 'The original array is:',0dh,0ah,'$'
buf2 db 'Please input ten number:',0dh,0ah,'$'
buf3 db 0ah,'The biggest number is:',0dh,0ah,'$'
buf4 db 0ah,'The smallest number is:',0dh,0ah,'$'
buf5 db 0ah,'The sorted array is:',0dh,0ah,'$'
DATAS ENDS
STACKS SEGMENT
;此处输入堆栈段代码
dw 50 dup(?)
top label byte
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
mov ax,stacks
mov ss,ax
mov sp,offset top
MOV AX,DATAS
MOV DS,AX
;输入所有数据
lea di,buf
mov cx,count
mov dx,offset buf2
mov ah,9h
int 21h
input_loop:
mov bx,0
call input
inc di
loop input_loop
mov dx,offset buf1
mov ah,9h
int 21h
;显示内存中所有数据
mov cx,count
lea bx,buf
LOOP1:
mov al,[bx]
CALL show_high
call kong_ge
inc bx
loop loop1
;计算最大数
mov cx,count
lea bx,buf
mov al,[bx]
inc bx
dec cx
again:
cmp al,[bx]
jae next
mov al,[bx]
next:
inc bx
loop again
mov max,al
;显示部分
mov dx,offset buf3
mov ah,9h
int 21h
call show_high
;计算最小数
mov cx,count
lea bx,buf
mov al,[bx]
inc bx
dec cx
again_min:
cmp al,[bx]
jb next_min
mov al,[bx]
next_min:
inc bx
loop again_min
mov min,al
;显示部分
mov dx,offset buf4
mov ah,9h
int 21h
call show_high
;冒泡排序部分
mov cx,count-1;cx为比较轮数,大循环次数
loop3:
mov dx,cx;dx表示大循环次数
mov bx,0;地址指针
loop4:
mov al,buf[bx]
cmp al,buf[bx+1]
jbe no_change
xchg al,buf[bx+1]
mov buf[bx],al
no_change:
inc bx
loop loop4
mov cx,dx;一轮比完之后,cx再次赋值比较轮数
loop loop3
;提示语
mov dx,offset buf5
mov ah,9h
int 21h
lea bx,buf
mov cx,count
LOOP5:
mov al,[bx]
CALL show_high
call kong_ge
inc bx
loop loop5
jmp end_pro
show_high proc near;显示字节的高位
mov dh,al
;原先的cx要压栈
push cx
mov cl,04h
and al,0f0h
shr al,cl
pop cx
add al,30h
cmp al,30h
jz show_low
mov dl,al
mov ah,02h
int 21h
show_low:;显示字节的低位
mov al,dh
and al,0fh
add al,30h
mov dl,al
mov ah,02h
int 21h
ret
show_high endp
kong_ge proc near
mov dl,' '
mov ah,02h
int 21h
ret
kong_ge endp
input proc near
push cx
mov ch,00h;用来记录输入的位数不超过两位
get_char:
mov ah,01h
int 21h
inc ch;计算位数
cmp al,0dh
je exit
sub al,30h
jb exit
cmp al,9
ja exit
cmp ch,03h;超出位数
jae exit
xchg al,bl;bl起始时为0
mov cl,04h
shl al,cl
xchg al,bl
add bl,al
mov [di],bl
jmp get_char
exit:
pop cx
ret
input endp
end_pro:
MOV AH,4CH
INT 21H
CODES ENDS
END START
第三种方法,则是对有符号数进行排序,和第二种方法也是在输入和输出的方面有区别,这种方法将数据以十进制的形式保存,以十进制的形式输出,输入的思想是每次输入的字符加上上一次的结果乘以10作为这一次的结果。输出的思想是每次输出都除以十取余数,直到商为0,其次和前两种方法相比在比较方面使用的语句也有所区别。
DATAS SEGMENT
;此处输入数据段代码
buf dw 10 dup(?)
count equ ($-buf)/2
tmp db 10 dup(?);保存数的每一位,打印的时候要用
max dw ?
min dw ?
buf1 db 'The original array is:',0dh,0ah,'$'
buf2 db 'Please input ten number:',0dh,0ah,'$'
buf3 db 0ah,'The biggest number is:',0dh,0ah,'$'
buf4 db 0ah,'The smallest number is:',0dh,0ah,'$'
buf5 db 0ah,'The sorted array is:',0dh,0ah,'$'
buf6 db 0ah,'The character is out of range, Try again:',0dh,0ah,'$'
DATAS ENDS
STACKS SEGMENT
;此处输入堆栈段代码
dw 50 dup(?)
top label byte
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
mov ax,stacks
mov ss,ax
mov sp,offset top
MOV AX,DATAS
MOV DS,AX
;输入所有数据
lea di,buf
mov cx,count
mov bx,10
mov si,0
mov bp,0
mov dx,offset buf2
mov ah,9h
int 21h
input_loop:
mov dx,0
call input
add si,2
inc di
loop input_loop
mov dx,offset buf1
mov ah,9h
int 21h
;显示内存中所有数据
mov cx,count
mov si,0
LOOP1:
mov ax,buf[si]
call show_ascii
add si,2
loop loop1
;计算最大数
mov cx,count
lea bx,buf
mov ax,[bx]
add bx,02h
dec cx
again:
cmp ax,[bx]
jge next
mov ax,[bx]
next:
add bx,02h
loop again
mov max,ax
;显示部分
mov dx,offset buf3
mov ah,9h
int 21h
mov ax,max
call show_ascii
;计算最小数
mov cx,count
lea bx,buf
mov ax,[bx]
add bx,02h
dec cx
again_min:
cmp ax,[bx]
jl next_min
mov ax,[bx]
next_min:
add bx,02h
loop again_min
mov min,ax
;显示部分
mov dx,offset buf4
mov ah,9h
int 21h
mov ax,min
call show_ascii
;冒泡排序部分
mov cx,count-1;cx为比较轮数,大循环次数
loop3:
mov dx,cx;dx表示大循环次数
mov bx,0;地址指针
loop4:
mov ax,buf[bx]
cmp ax,buf[bx+2]
jle no_change
xchg ax,buf[bx+2]
mov buf[bx],ax
no_change:
add bx,02h
loop loop4
mov cx,dx;一轮比完之后,cx再次赋值比较轮数
loop loop3
;提示语
mov dx,offset buf5
mov ah,9h
int 21h
mov si,0
mov cx,count
LOOP5:
mov ax,buf[si]
CALL show_ascii
add si,02h
loop loop5
jmp end_pro
kong_ge proc near
mov dl,' '
mov ah,02h
int 21h
ret
kong_ge endp
input proc near
push cx
mov cx,00h
get_char:
mov ah,01h
int 21h
cmp al,'-';判断是否为负数
jz nagetive
cmp al,0dh;判断是否为回车
jz process_1
cmp al,' ';判断是否为空格
jz process_1
cmp al,30h
jl mistake
cmp al,39h;大于9
ja judge1
jmp process_2
judge1:
cmp al,41h;表示在39<x<41的数
jb mistake
cmp al,80h;表示>46即超过F的数
ja mistake
jmp process_2
mistake:
mov dx,offset buf6
mov ah,9h
int 21h
jmp get_char
nagetive:
mov bp,1;bp作为符号位
jmp get_char
process_2:
push ax;
mov ax,dx
mul bx;乘以10,以十进制存储
mov dx,ax;数据保存在dx中
pop ax
sub al,30h
mov ah,0
add dx,ax
jmp get_char
process_1:
cmp bp,1
jnz save
neg dx;取负命令0-原数据
save:
mov buf[si],dx;将处理好的数据存入num中去
mov bp,0;bp位清零
mov dl,0dh;回车换行重新输入
mov ah,2
int 21h
mov dl,0ah
int 21h
exit:
pop cx
ret
input endp
show_ascii proc near
test ax,1000h;与命令
jz pre_show;不是负数
push ax
mov dl,'-';是负数的情况,先显示负号
mov ah,02h
int 21h
pop ax
neg ax
pre_show:
mov di,0
mov dx,0
mov bx,10
mid_show:
div bx;十六进制转十进制
add dl,30h;余数部分作为结果
mov tmp[di],dl
inc di
cmp ax,0;判断商是否为0,是则表示转换完成
jz last_show
mov dx,0;余数部分清零
jmp mid_show
last_show:
mov dl,tmp[di-1];dl为待输出字符的ascii码
mov ah,2
int 21h
dec di
jnz last_show
mov dl,' ';数据之间打印空格
mov ah,02h
int 21h
ret
show_ascii endp
end_pro:
MOV AH,4CH
INT 21H
CODES ENDS
END START
这是我自己做微机实验的一些整理,好多代码来自网上和课本我做了一个整理,希望能对你们有所帮助。这个题还可以在输入小数方面做进一步的改进。