北邮微原软件实验二:分支,循环程序设计。
基于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再跳转到其他判断中。