微原软件实验:统计正负数、奇偶数的个数

北邮微原软件实验二:分支,循环程序设计。
基于8086汇编。我在64位Win7下用DOSBox进行实验。

实验二 分支,循环程序设计
一.实验目的:
1.开始独立进行汇编语言程序设计;
2.掌握基本分支,循环程序设计;
3.掌握最简单的 DOS 功能调用.
二.实验内容:
1.安排一个数据区,内存有若干个正数,负数和零.每类数的个数都不超过 9.
2.编写一个程序统计数据区中正数,负数和零的个数.
3.将统计结果在屏幕上显示.
三.选作题:
  统计出正奇数,正偶数,负奇数,负偶数以及零的个数.

仙剑95进度汇报

姥姥挂了
姥姥挂了
嗯,情况是这样的。以后灵儿就跟着逍遥哥哥四处闯荡咯。

编程思路

在Deadline的前一天,我开始了这段煎熬的旅程。
对汇编实在没啥感觉,先用C语言写一记。

C语言实现

num_to_compare[N_NUM] = [-4,12,34,0,5,1,4,6,9,-8];
int positive_odd_num=0, positive_even_num=0, zero_num=0, negative_odd_num=0, negative_even_num=0;
 for(int i = 0; i< N_NUM; i++){
	int temp = num_to_compare[N_NUM];
	if(  temp > 0 ){
		if( temp % 2 )  positive_odd_num++;
		else positive_even_num++;
	}else if( temp < 0 ) 
		if( temp % 2 ) negative_odd_num++;
		else negative_even_num++;
	}else{
		zero_num++}
	}
}
print ""
print ""
print ""
print ""

所以,在汇编中,可以分成几个小模块。
主模块负责处理各种判断逻辑,然后还需要一些小模块来负责打印字符串到屏幕的功能。

显示字符串模块

;---------------------------
;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

用法:将DS:DX指向字符串的首地址(字符串以字符'$'结束),然后直接调用print_string就可以将字符串打印到屏幕上。

显示字符模块

;---------------------
; 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

用法:将需要显示的字符存到DL中,程序里调用print_char即可。

显示换行模块

;---------------------------
;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

用法:直接调用,即可打印换行。

显示数字模块

二进制数,是无法直接打印到屏幕上的。可以采取的方法是,将这个二进制的数转换成对应的ASCII码,然后打印。
下面这个Process只能打印一位十进制的数。

;---------------------------
;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

用法:将需要打印的数字存放在AL寄存器中,调用print_num即可将数字打印到屏幕上。

完整代码

;Exercise 2  
;We store a sequence of numbers in data segment, include positive numbers,negative numbers and zeros,the amount of each type will not exceed 9.
;Tasks: Count different type of numbers, and print to screen.
;AUTHOR: feichashao
; 2013-12-8

assume cs:codesg,ds:datasg,ss:stacksg

Stacksg SEGMENT STACK 'STACK'
	DB 100H DUP(0)
Stacksg ENDS

datasg segment
	num_to_compare db -4,12,34,0,5,1,4,6,9,-8,-7,0,0,3 ; Define an array to store the numbers we want to identify.
	N_NUM EQU $-num_to_compare  ; Get the length of the array
	positive_odd_num db 00H ; Variable that keep track of the amount of positive odd numbers.
	positive_even_num db 00H ; Variable that keep track of the amount of positive even numbers.
	zero_num db 00H ; Variable that keep track of the amount of zeros.
	negative_odd_num db 00H ; Variable that keep track of the amount of negative odd numbers.
	negative_even_num db 00H ; Variable that keep track of the amount of negative even numbers.
	positive_odd_string db 'Positive Odd Num: $' ; A string to print
	positive_even_string db 'Positve Even Num: $' 
	zero_string db 'Zeros: $'
	negative_odd_string db 'Negative Odd Num: $'
	negative_even_string db 'Negative Even Num: $'
datasg ends

codesg segment

main proc
		push ds
		xor  ax,ax
		push ax
		mov ax,datasg
		mov ds,ax
		; Point DS to datasg, so we can use the variables.
		push cx
		
		mov cx,N_NUM
		mov si,0H
again:		mov al,num_to_compare[si]
			cmp al,0H
			jz zero
			cmp al,0H
			js negative ; Jump to negative.
			shr al,1
			jnc positve_even ; Jump to positive_even.
			inc positive_odd_num
			jmp continue_loop
			
positve_even: inc positive_even_num
			jmp continue_loop
			
negative:	shr al,1
			jnc negative_even;
			inc negative_odd_num
			jmp	continue_loop
			
negative_even: inc negative_even_num
			jmp continue_loop
zero:		inc zero_num;
			
continue_loop: inc si
			loop again
			
; Print results to screen.

;print positive odd number
	lea dx,positive_odd_string
	call print_string
	mov al,positive_odd_num
	call print_num
	call print_nl
;print positive even number
	lea dx,positive_even_string
	call print_string
	mov al,positive_even_num
	call print_num
	call print_nl
;print zeros
	lea dx,zero_string
	call print_string
	mov al,zero_num
	call print_num
	call print_nl
;print negative odd number
	lea dx,negative_odd_string
	call print_string
	mov al,negative_odd_num
	call print_num
	call print_nl
;print negative even number
	lea dx,negative_even_string
	call print_string
	mov al,negative_even_num
	call print_num
	call print_nl
	
	mov ax,4c00H
	int 21H

main endp

;---------------------------
;input: DL,the ASCII of the char.
;output: a char on screen

print_char proc 
	mov ah,02h
	int 21h
	ret
print_char endp

;---------------------------
;input: Null.
;output: a newline  on screen

print_nl proc 
	mov ah,02h
	mov dl,0dh
	int 21h
	mov dl,0ah
	int 21h
	ret
print_nl endp

;---------------------------
;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

;---------------------------
;input: al = number
;output: a number char on screen.

print_num proc near
	add al,'0'-0h
	mov ah,02h
	mov dl,al
	int 21h
	ret
print_num endp

codesg ends

end main

实验结果

结果图
结果图

故障分析

出现过的逻辑问题:把0误判成正偶数。
解决方法:得到一个数,先判断是否为0,不为0再跳转到其他判断中。