汇编语言-------从键盘输入 N 个数,排序后输出(用循环写)

微机原理课程上机实验之一

题目:

      从键盘输入 N 个无符号数(整数,小于256),将其转换为二进制数后存放在字节型缓冲区 BUF 中。对这 N 个数进行由大到小排序,排序后仍将其存储在 BUF 中,并将排序后的结果在屏幕上显示出来(请用循环程序设计方法编写汇编程序实现上述功能)。

 

     已经在DOSBOX/Emu8086 下正确运行过了

     详见注释

DATA   SEGMENT       ;定义数据段
    buf db 100 dup(0)
	n db 0
	printInt_div dw 100,10,1
	printInt_res db 0,0,0,"$"
DATA   ENDS
CODE   SEGMENT               ;定义代码段
       ASSUME  CS: CODE,DS:DATA
START: 
		MOV  AX,DATA     
        MOV  DS,AX
		
		call getInt
		mov n,al
		mov bx,0
		mov ch,0
		mov cl,al
	lp:
		push cx
		call getInt
		mov buf[bx],al
		inc bx
		pop cx
		loop lp
		mov bx,0
	lp1:
		mov di,bx
		inc di
		lp2:
			mov al,buf[bx]
			mov cl,buf[di]
			cmp al,cl
				jae els
				mov buf[bx],cl
				mov buf[di],al
			els:
			inc di
			mov ax,di
			mov ah,n
			cmp ah,al
			jae lp2
		inc bx
		cmp bl,n
		jb lp1
		
		mov ch,0
		mov cl,n
		mov bx,0
	lp3:
		mov ah,0
		mov al,buf[bx]
		call putInt
		mov al,' '
		call putchar
		inc bx
		loop lp3
		MOV AH,4CH
        INT 21H    
putchar:
	pushf
	push DX
	mov DX,AX
	mov AH,02H
	int 21h
	pop DX
	popf
	ret

getInt: 
	;普通输入数字返回输入的数字ax(zf=1),,,特殊情况(esc键和tab键zf=0)esc键返回ax=0(zf=0),tab返回ax=1(zf=0)
	;可以用jz判断是否发生了特殊情况。用ax区分发生了esc还是tab

        push BX  ;保护现场
        push DX 
        push CX 
       ;此处不能pushf,因为flags是返回值
        mov AX,0 ;初始化 
        mov BX,0
        mov CX,0
        mov DX,0
getInt_XUNHUAN:
    mov AH ,01H
    int 21H ; 输入一个字符,一定存储在 AL 中
    cmp  AL,0DH ; 判断回车符 
    jz  getInt_RESULT ;    zf=0 判断是回车

    cmp  AL,30H
    jb   getInt_XUNHUAN  ; < 0
    cmp  AL,39H ;<= 9 && > 0
    jbe  getInt_SUM_TO_AX   

    jmp  getInt_XUNHUAN ;继续循环 

getInt_SUM_TO_AX: 
        mov AH,0 ;清除 AX 高位
        push AX  ;保存 AX

        mov AX,CX  ;将原先的值乘以 10 ,实质上乘起来的值放在了 CX 中 
        mov BX,10
        ;如果参数是字节,将把 AL 做乘数, 结果放在 AX
        ;如果参数是字 , 将把 AX 做乘数, 结果放在 DX:AX
        mul BX 
        mov DX,0
        mov CX,AX 
        pop AX
        sub AL,30H
        add CX,AX 
        jmp  getInt_XUNHUAN    
            
;getInt_OTHER_ERROR:  
;        jmp  getInt_XUNHUAN   
getInt_RESULT:
        mov AX,CX
        pop BX  ;恢复现场
        pop DX 
        pop CX
        ret  

putInt:
	pushf
	push ax
	push bx
	push cx
	push dx
	push di
	push si
    	mov     si, offset printInt_div
    	mov     di, offset printInt_res                     
    	mov     cx,3  
    ddiv:
        mov     dx,0            
        div     word ptr [si]   ;除法指令的被除数是隐含操作数,此处为dx:ax,商ax,余数dx
        add     al,30H           ;商加上48即可得到相应数字的ASCII码
        mov     byte ptr [di],al        
        inc     di                                
        add     si,2                           
        mov     ax,dx                        
        loop    ddiv
        mov     cx,4    
        mov     di, offset printInt_res 
    leadzero:
        cmp     byte ptr [di],'0'   ;不输出前面的0字符    
        jne     pprint
        inc     di                           
        loop    leadzero
    pprint:
        mov     dx,di                       
        mov     ah,9
        int     21h   ;调用DOS功能,该功能为显示DS:DX地址处的字符 
        pop si
        pop di
        pop dx
        pop cx
        pop bx
        pop ax
        popf     
    	RET
CODE  ENDS                    ;代码段结束
END  START              ;汇编结束  

运行结果:

第一个输入的数字N指明输入的待排序的数字个数

好的,这是一个比较复杂的问题。这里提供一个简单的实现思路,仅供参考。具体实现需要考虑很多细节,例如输入的字符串长度限制、排序算法、输出格式等等。 首先,需要通过 BIOS 中断 16h 的 00h 功能获取用户输入的字符串。具体实现可以参考以下汇编代码: ``` input_string: mov ah, 0 ; 读取键盘输入 int 16h ; 调用 16h 中断 cmp al, 0Dh ; 如果输入回车键,则结束输入 je end_input mov [si], al ; 将输入的字符存入字符串中 inc si ; 字符串指针加一 jmp input_string end_input: mov [si], 0 ; 字符串结束符 ``` 接下来,需要遍历字符串,找出其中的数字字符,并进行排序。可以通过循环遍历字符串,并使用 ASCII 码进行判断。具体实现可以参考以下汇编代码: ``` sort_numbers: mov cx, 0 ; 数字计数器清零 mov di, str ; 字符串指针指向开头 loop_start: mov al, [di] ; 获取当前字符 cmp al, 0 ; 如果到了字符串结尾,则结束循环 je end_loop cmp al, '0' ; 如果当前字符是数字字符,则将其存入数字数组中 jb continue_loop cmp al, '9' ja continue_loop mov [numbers+cx], al inc cx continue_loop: inc di ; 字符串指针加一 jmp loop_start end_loop: ; 在这里进行数字排序 ``` 最后,需要将排序后的数字字符输出到屏幕上。可以通过循环遍历数字数组,并使用 BIOS 中断 10h 的 0Eh 功能输出字符。具体实现可以参考以下汇编代码: ``` output_numbers: mov cx, 0 ; 数字计数器清零 mov si, numbers ; 数字指针指向开头 output_loop: cmp cx, num_count ; 如果遍历完所有数字,则结束循环 je end_output mov al, [si] ; 获取当前数字 mov ah, 0Eh ; 设置输出字符的功能号 int 10h ; 调用 10h 中断输出字符 inc si ; 数字指针加一 inc cx ; 数字计数器加一 jmp output_loop end_output: ``` 以上代码仅仅是一个简单的实现思路,实际的实现需要考虑很多细节。如果你需要更具体的帮助,可以提出具体的问题,我会尽力帮助。
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值