*/ --------------------------------------------------------------------------------------
*/ 出自: 编程中国 http://www.bc-cn.net
*/ 作者: 永夜的极光
*/ 时间: 2007-11-14 编程论坛首发
*/ 声明: 尊重作者劳动,转载请保留本段文字
*/ --------------------------------------------------------------------------------------
上星期下定决心开始学习8086汇编,断断续续学了一个星期,终于编出来几个小程序,发出来给大家看看
各位高手中手低手,见笑了.最好能给我提提一些改进的建议,程序是在写的太冗长了
目前写一个这种小程序,估计要4,5个小时......
下面是目录
1楼 从键盘输入年份,判断是否为闰年
2楼 接受输入一个字符串,找出重复长度最大的一段
3楼 计算两个长整数相加
4楼 输入升序数据,并使用二分法搜索
5楼 用快速排序法对一维数组进行排序
9楼 利用自定义的库函数,输出任意不大于FFFFFFFF的10进制数
11楼 利用宏汇编和条件汇编,实现子程序的寄存器入栈和出栈
;从键盘输入年份,判断是否为闰年
;作者:永夜的极光
;时间:2007-11-11
;程序运行结果
;Please Input Year: 1996
;This is a leap year!
;Do you want to try again?(Y/N) y
;Please Input Year: 1900
;This is not a leap year!
;Do you want to try again?(Y/N) y
;Please Input Year: 2000
;This is a leap year!
;Do you want to try again?(Y/N) y
;Please Input Year: 2007
;This is not a leap year!
;Do you want to try again?(Y/N) n
;Press any key to exit.
assume cs:code,ds:data
data segment
;初始化各种提示语句,前面的0dh,0ah表示回车
inf db 0dh,0ah,'Please Input Year: $'
inf_ok db 0dh,0ah,'This is a leap year! $'
inf_no db 0dh,0ah,'This is not a leap year! $'
inf_err db 0dh,0ah,'Input Error! $'
inf_ag db 0dh,0ah,'Do you want to try again?(Y/N) $'
inf_end db 0dh,0ah,'Press any key to exit. $'
;将输入的年份字符串转为数字,存在此处
year dw 0
;缓冲区,用于接受输入,第一个字节为缓冲区长度,第二个字节为实际输入长度,后面是缓冲区
buf db 8
db ?
db 8 dup (?)
data endsstack segment
db 80 dup (0)
stack endscode segment
start:
mov ax,data
mov ds,ax
mov ax,stack
mov ss,ax
mov sp,80
;dx保存提示语句的首地址,调用21H中断09功能,显示在屏幕上
lea dx,inf
mov ax,0900H
int 21H
;dx指向缓冲区首字节(表示缓冲区大小的字节),调用21H中断0AH功能,接受输入字符串
lea dx,buf
mov ax,0a00H
int 21H
;cx清零,程序一开始,cx就不是0,这个不知道什么原因
xor cx,cx
mov cl,[buf+1];cl取得实际输入字符数
cmp cl,4 ;如果实际输入字符数>4,则提示输入错误
ja input_error
lea si,[buf+2];si指向实际的缓冲区起始位置
push cx
is_num: ;判断输入的是否都是数字,如果不是,则提示输入错误
cmp byte ptr [si],'0'
jb input_error
cmp byte ptr [si],'9'
ja input_error
inc si ;si后移
loop is_num
pop cx
dec si ;上面循环结束后,si指向输入字符串的最后一个字符的后面,所以减1,使之指向最后一个字符
lea di,year ;di指向保存转换后数字的空间
mov word ptr [di],0 ;该空间清0
call str2int ;调用函数,将输入字符串转换为数字
call isleap ;判断这个数字是否为闰年
jmp short try_again ;询问是否继续输入
input_error:
lea dx,inf_err ;提示输入错误
mov ax,0900H
int 21Htry_again:
lea dx,inf_ag ;询问是否继续
mov ax,0900H
int 21H
mov ax,0100H ;调用中断21H的01功能,接受一个字符输入并回显
int 21H
cmp al,'y' ;判断输入字符是否为y或Y,如果是,则跳回函数开头,重新执行
jz start
cmp al,'Y'
jz startmain_end:
lea dx,inf_end
mov ax,0900H
int 21H
mov ax,0700H
int 21H
mov ax,4c00H ;程序结束
int 21H
;函数功能:将一个数字字符串转换成对应的数字
;输入参数:cx 字符串长度
; si 指向字符串的最后一个字符
; di 指向转换结果保存的位置,大小为word型
str2int proc near
push ax ;寄存器入栈
push bx
push cx
push dx
mov ax,1 ;ax初始为1
l1:
push ax ;每次循环,ax*10,但是后面计算乘法的时候,还需要用到ax,所以先把ax的值入栈
mov bl,[si] ;把si指向的字符存入bl,并减掉字符'0'
sub bl,'0'
mov bh,0 ;bh置0,计算乘法,因为可能要乘1000,只能用16位乘16位的乘法
mul bx
add ds:[di],ax ;乘法结果加到保存计算结果的地方(也就是di指向的地址)
pop ax ;ax出栈,并乘10
mov bx,10
mul bx
dec si ;si递减
loop l1 ;这个循环开头没有写cx,因为cx是作为参数传进来的pop dx
pop cx
pop bx
pop ax
retstr2int endp
;函数功能:判断某个数字是否为闰年
;输入参数:di 指向被判断数字的存储地址,word型
;输出参数:无,直接屏幕显示是否闰年
isleap proc near
push ax ;寄存器入栈
push bx
push cx
push dx
mov cx,ds:[di] ;cx保留输入字符串
mov ax,cx
mov dx,0 ;因为除法结果可能超过8位,所以要做32位除16位的除法,所以dx要清零
mov bx,4 ;除4
div bx
cmp dx,0 ;dx是余数,判断是否为0,不是0则肯定不是闰年
jnz not_leap
mov ax,cx ;ax恢复为待计算数字,这次计算的结果只需要8位就够,所以用16位除8位就行
mov bx,100 ;除100
div bl
cmp ah,0 ;ah是余数,如果为0,那还要继续判断,如果不为0,那就肯定是闰年了
jnz is_leap
mov ax,cx ;x恢复为待计算数字,因为要除以400,超过8位,所以用32位除16位除法
mov dx,0
mov bx,400
div bx
cmp dx,0 ;余数如果为0,说明是闰年
jz is_leap
jmp short not_leap ;不是闰年
is_leap:
lea dx,inf_ok ;是闰年的话,提示是闰年
mov ax,0900H
int 21H
jmp short end_sub
not_leap:
lea dx,inf_no ;不是闰年的话,提示不是闰年
mov ax,0900H
int 21H
end_sub:
pop dx
pop cx
pop bx
pop ax
retisleap endp
code ends
end start
[此贴子已经被作者于2007-11-21 13:48:58编辑过]