微原软件实验:用户输入任意个两位十进制数,程序要找出最小的数并输出

北邮微原软件实验三:代码转换程序设计

一.实验目的:
1.掌握几种最基本的代码转换方法;
2.运用子程序进行程序设计.

二.实验内容:
1.从键盘上输入若干两位十进制数,寻找其中的最小值,然后在屏幕上显示出来.
2.两个十进制数之间的分隔符,输入结束标志自定,但要在报告中说明.
3.对输入要有检错措施,以防止非法字符输入,并有适当的提示.
4.将整个程序分解为若干模块,分别用子程序实现.在报告中要给出模块层次图.

今天北京的空气可以炫耀

难得空气好~
难得空气好~


难得空气好,at海淀区
难得空气好,at海淀区

海淀区~~
海淀区~~

西土城路
西土城路

这种好日子能持续多久?

编程思路

实验三编程思路
实验三编程思路

用分模块的方法,分别把输入输出纠错都独立开来,主程序只顾大体流程,记录最小值。

完整代码

  ;----------------------------------
  ;Exercise 3. 
  ;Get arbitrary amount of 2-digit-decimal numbers, find out the smallest number, and print it to screen.
  ; Global variables: smallest_num[2], end_flag, current_num[2].
  ;
  
  ; 1. Get input number.
  ; 2. Check if end_flag=1, if yes,jump to output.
  ; 3. Compare the current_num with the smallest_num, if current_num < smallest_num, set smallest_num=current_num
  ; 4. Repeat 1.
  ; 5. Output the smallest number, exit program.
  ;
  
  
  assume cs:codesg,ds:datasg,ss:stacksg
  
  Stacksg SEGMENT STACK 'STACK'
  	DB 100H DUP(0)
  Stacksg ENDS
  
  datasg segment
  	smallest_num db 9,9
  	end_flag db 0
  	current_num db 0,0
  	illegal_num_msg db 'ooooops,something wrong with your input. $'
  	output_msg db 'The smallest number you input is: $'
  datasg ends
  
  
  
  codesg segment
  
  main proc
  initialize:
  	sub ax,ax
  	mov ax,datasg
  	mov ds,ax
  	
  get_input_num:
  	call get_2digits_input
  	cmp end_flag,1
  	jz output
  compare_10:
  	mov al,current_num[0]
  	cmp al,smallest_num[0]
  	jb swap
  	cmp al,smallest_num[0]
  	jz compare_1
  	jmp get_input_num
  compare_1:
  	mov al,current_num[1]
  	cmp al,smallest_num[1]
  	jb swap
  	jmp get_input_num
  swap:
  	mov al,current_num[0]
  	mov smallest_num[0],al
  	mov al,current_num[1]
  	mov smallest_num[1],al
  	jmp get_input_num
  output:
  	call print_nl
  	lea dx,output_msg
  	call print_string
  	mov al,smallest_num[0]
  	call print_num
  	mov al,smallest_num[1]
  	call print_num
  	call print_nl
  
  exit:
  	mov ax,4c00H
  	int 21H
  	
  main endp
  
  
  
  ;--------------------------------------------
  ; Process: get_2digits_input
  ; This process would get a 2-digit-decimal number input from DOS.
  ; This process requires 2 global variables:  end_flag, current_num[2].
  ; Input: null
  ; Output: a number(range 0-99 decimal) in current_num[2](global variable). If encounter a end_symbol, set end_flag to 1.
  
  ; 1. Initialize variables, set end_flag and current_num to 0.
  ; 2. Push registers into stack. 
  ; 3. Get a char input. (input10)
  ; 4. Check if it is separate_symbol or end_symbol. If it is, end this process. (check_s,check_e)
  ; 5. Check if the input is legal(range '0' to '9'),and transform to number from ASCII. (check_legal)
  ; 6. Get another char input.(input1)
  ; 7. Check if it is separate_symbol or end_symbol. If it is, end this process. ,and check if the input is legal.(range '0' to '9')
  ; 8. If input legal,add to current_num directly. (add one)
  ; 9. Pop registers,return. (return)
  
  end_symbol EQU 'e'
  separate_symbol EQU ' '
  
  get_2digits_input proc 
  	mov end_flag,0
  	mov current_num[0],0
  	mov current_num[1],0
  	push ax
  	push bx
  	push cx
  	push dx
  
  input10:	
  	mov ah,01
  	int 21h
  check_s:
  	cmp al,separate_symbol
  	jnz check_e
  	jmp return
  check_e:
  	cmp al,end_symbol
  	jnz check_legal
  	mov end_flag,1
  	jmp return
  check_legal:
  	call check_num
  add_tens:
  	mov current_num[0],al
  	
  	
  input1:
  	mov ah,01
  	int 21h
  check_s1:
  	cmp al,separate_symbol
  	jnz check_e1
  	jmp return
  check_e1:
  	cmp al,end_symbol
  	jnz check_legal1
  	mov end_flag,1
  	jmp return
  check_legal1:
  	call check_num
  add_ones:
  	mov current_num[1],al
  	jmp input10
  	
  return:
  	pop dx
  	pop cx
  	pop bx
  	pop ax
  	;-----Debug------
  	;call print_nl
  	;mov al,current_num[0]
  	;call print_num
  	;mov al,current_num[1]
  	;call print_num
  	;----------------
  	ret
  	
  get_2digits_input endp
  
  
  
  ;--------------------------------------------
  ; Process: check_num
  ; This is a sub-process of get_2digits_input
  ; input: al (ASCII)
  ; output: al (unsigned integer)
  
  check_num proc
  	cmp al,'0'-1H
  	jna illegal_num
  	cmp al,'9'+1H
  	jnb illegal_num
  	sub al,'0'-0H
  	ret
  illegal_num:
  	push dx
  	call print_nl
  	lea dx,illegal_num_msg
  	call print_string
  	call print_nl
  	mov al,0
  	pop dx
  	ret
  check_num endp
  
  ;---------------------------
  ;Process: print_num
  ;input: al = number
  ;output: a number char on screen.
  
  print_num proc 
  	push dx
  	add al,'0'-0h
  	mov ah,02h
  	mov dl,al
  	int 21h
  	pop dx
  	ret
  print_num endp
  
  ;---------------------------
  ;Process:  print_string
  ;input: DS:DX, set DS:DX to string address,and call this process. The string should end with '$'
  ;output: Screen.
  
  print_string proc 
  	mov ah,09h
  	int 21h
  	ret
  print_string endp
  
  ;---------------------------
  ;Process: Print_nl
  ;input: Null.
  ;output: a newline on screen
  
  print_nl proc 
  	push dx
  	mov ah,02h
  	mov dl,0dh
  	int 21h
  	mov dl,0ah
  	int 21h
  	pop dx
  	ret
  print_nl endp
  
  ;---------------------
  ; Process: print_char
  ;input: DL,the ASCII of the char.
  ;output: a char on screen
  
  print_char proc 
  	mov ah,02h
  	int 21h
  	ret
  print_char endp

  
  codesg ends
  end main

实验结果

成功找到输入数列中的最小值;可以进行输入检错。
成功找到输入数列中的最小值;可以进行输入检错。

更优的方法

上面的代码里,是将输入的两位十进制数转换成8bits的二进制数进行存储和比较的,这样在转换和输出的时候,会遇到很多麻烦。
其实这种麻烦是可以避免的。因为数字的ASCII码也是从30H-39H从小到大排序的,我们可以直接记录输入的两位ASCII码,然后十进制按位比较,得出最小值,最后输出。整个过程无需进行十进制到二进制的转换。