汇编语言(斐波拉契数列)
汇编语言(斐波拉契数列)
;=======================================================================================
; @date : 2017.5.1
; @author : Small_Pond
; @说明:
; 1.斐波拉契数列最大只能输出25个 ,不然会溢出
; 2. 获得用户输入后,在进行数据转换时,还无法进行错误输入检测------>(2017.5.1已解决)
; 3.产生新问题: 在进行字符串正确性的判断中有反逻辑
; -> 0表示正确 1表示错误
;======================================================================================
assume cs:codesg ,ds:datasg,ss:stack
stack segment
db 128 dup(?)
stack ends
datasg segment
canHandleData dw 10 dup(0)
charStackData db 128 dup(0)
fibonacciData dw 50 dup(?)
conversionTable dw 1,10,100,1000,10000
printDataSource db 128 dup(0)
info db 'please input:',0
againInfo db 'please input again :',0
myInfo db 'id: name: Ding Biao ',0
errorInformation db 'over error input',0
address dw FibonacciData,printDataSource,charStackData,info,againInfo,myInfo,myInfo1,errorInformation
datasg ends
codesg segment
start:
mov ax,stack
mov ss,ax
mov sp,128
mov ax,datasg
mov ds,ax
mov ax,datasg
mov es,ax
;==============获取用户输入===================
mov dh,2 ; 2行
mov dl,0 ; 0列
mov cl,2 ; 字符属性
mov si,address[6] ; 字符串起始地址
call showStr
jmp firstGetStr
inputAgain:
mov dh,2 ; 2行
mov dl,0 ; 0列
mov cl,4 ; 字符属性
mov si,address[8] ; 字符串起始地址
call showStr
firstGetStr:
mov si,address[4]
mov dh,2
mov dl,30
call getstr
;==============获取用户输入===================
;==============对输入数据进行处理=============
mov ax,0 ;默认输入为正确
mov si,0
mov bx,0
call inputDataConverion
cmp ax,1
je inputAgain
;==============对输入数据进行处理=============
;==============判断输入数据范围=============
mov ax,canHandleData[0]
cmp ax,24
jnl errorInput
;==============判断输入数据范围=============
;===============斐波拉契数列产生======================
mov ax,canHandleData[0]
mov cx,ax
call recursionGenerateFibonacci ;调用斐波拉契数列产生子程序
;===============斐波拉契数列产生======================
mov cx,canHandleData[0]
mov bx,address[0]
mov di,address[2]
call dToString
mov dh,8 ; 8行
mov dl,0 ; 3列
mov cl,3 ; 字符属性 2->黑底绿色无高亮无闪烁
mov si,address[2] ; 字符串起始地址
call showStr
;=========显示我的信息==========
mov dh,10
mov dl,0
mov cl,5
mov si,address[10] ;si 显示字符起始地址
call showStr
mov dh,11
mov dl,0
mov cl,6
mov si,address[12] ;si 显示字符起始地址
call showStr
;=========显示我的信息==========
mov ax,4c00h
int 21h
errorInput:
mov dh,10
mov dl,0
mov cl,5
mov si,address[14] ;si 显示字符起始地址
call showStr
mov ax,4c00h
int 21h
;=======================================================================================
;@name : inputDataConverion
;@fuction : 对用户键盘输入的数据进行转换
; 转换为可处理的数据
; 说明:现在默认用户能正确输入数据!2017.4.30
; 2017.5.1 改进 可判断用户输入数据是否满足全为数字,错误则提示用户重新输入
; 使用AX作为返回值。输入格式正确返回0, 否则返回1
;@eg:
; mov ax,0 ;默认输入为正确(2017.5.1可进行用户错误输入判断)
; mov si,0
; mov bx,0
; call inputDataConverion
; cmp ax,1
; je inputAgain
;=======================================================================================
inputDataConverion:
push bx
push cx
push dx
push si
push di
mov di,0 ;初始化数据
startPush:
mov ah,0
mov al,charStackData[bx]
mov ch,0
mov cl,al ;用来检测字符串的结束
jcxz inputDataConverionRet ;最后为0则表示结束
cmp ax,30h ;字符‘0’
jl isSpace
cmp ax,39h ; '9'
ja isError
push ax ;将数据压如栈中,后面进行处理
inc bx ;读入下一个Ascll码
JMP startPush
isSpace:
cmp ax,20h
jne isError ;在小于字符‘0’的情况下不为空格则判断为用户输入错误
;空格表示一个数据输入完成
mov cx,bx
mov si,0
mov bx,0
startPop:
pop ax
sub ax,30h
mov dx,conversionTable[si]
mul dx
add bx,ax
add si,2
loop startPop
mov word ptr canHandleData[di],bx
add di,2
jmp startPush
isError:
mov ax,1 ;返回错误信息
inputDataConverionRet:
pop di
pop si
pop dx
pop cx
pop bx
ret
;==============================================
;@name : generateFibonacci
;@fuction : Generate Fibonacci sequence
;@parameter instructions: cx -> 数列数量 (控制在255以内)
;two way: 1.迭代
; 2.递归
;@说明:
;=============================================
;**************迭代********************************
generateFibonacci:
push ax
push di
push cx
mov FibonacciData[0],1
mov FibonacciData[2],1 ;迭代初始化
mov di,2
sub cx,2
; mov ax,2
; mul bx
; mov di,ax
; sub di,2
FibonacciStart:
jcxz fibonacciRet
mov ax,FibonacciData[di-2]
add ax,FibonacciData[di]
mov FibonacciData[di+2],ax
add di,2
loop FibonacciStart
fibonacciRet:
pop cx
pop di
pop ax
ret
;****************迭代*********************************
;================递归=================================
recursionGenerateFibonacci:
mov FibonacciData[0],1
mov FibonacciData[2],1 ;初始化
mov bx,cx
mov di,4
recursionStart:
cmp bx,2
jng recursionGenerateFibonacciRet ;底层递归结束
sub bx,1
call recursionStart
recursionGenerateFibonacciRet:
mov ax,FibonacciData[di-4]
add ax,FibonacciData[di-2]
mov FibonacciData[di],ax
add di,2
ret
;================递归=============================
;================================================
; name : dtos -> data to string
; fuction : 将数据段的多个数据转化为字符串
; 调用此函数前须将di置为0 ,用于缓存字符串长度
; 将es段中的数据转化为字符放入ds段中
; es:bx 指向源 ds:di指向目的地址
; cx -> 需转换的数字个数
; 待解决负数问题!!(已解决)
; 在此应用中 斐波拉契数列没有正负数
;
;================================================
dToString:
mov ax,es:[bx]
add bx,2
; cmp ax,0
; jnl postiveNum
; mov byte ptr ds:[di],45 ;当为负数时 ,在前添加‘-’
; inc di
; sub ax,1 ;处理负数
; not ax
;postiveNum:
call dtoc
loop dtostring
dtoc:
push bx
push dx
push ds
push si
push cx
jcxz changEnd ;之前在后面进行判断, 会发生输出最后会加0的错误。 所以将其提前,修改bug
mov bx,10
mov si,0
;ax 存储商 dx存储余数
dtocing:
mov dx,0
div bx
add dx,30h
push dx
inc si
mov cx,ax
jcxz dtocRet
jmp dtocing
dtocRet:
mov cx,si
poping:
pop ds:[di]
inc di
loop poping
mov byte ptr ds:[di],32 ;移入空格
inc di
pop cx
pop si
pop ds
pop dx
pop bx
ret
changEnd:
mov byte ptr ds:[di],0 ;移入0,标记字符串的结束
pop cx
pop si
pop ds
pop dx
pop bx
ret
; *******************************************************
;name :showStr
;fuction : 在指定的位置,用指定的颜色,显示一个用0结束的字符串
;参数 :(dh)=行号(取值范围0-24),(dl)=列号(取值范围0-79), (cl) = 颜色,ds:si指向字符串的首地址
;eg:->init
;
; mov dh,8 8行
; mov dl,3 3列
; mov cl,2 字符属性 2->黑底绿色无高亮无闪烁
; mov ax,data
; mov ds,ax 字符串段地址
; mov si,0 字符串起始地址
; *******************************************************
showStr:
push dx
push cx
push es
push bx
push si
push di
call showStrInit
mov dh,cl ;由dx = dh + dl ; dh = 颜色 dl = 字符
showStringMain:
mov cx,0
mov cl,ds:[si]
jcxz showStrRet
mov dl,cl
mov es:[di],dx
add di,2
inc si
jmp showStringMain
showStrInit:
mov al,160
mov bl,dh
mul bl
mov di,ax ;得到行数 , 最终用es:di指向显示区域
mov al,2
mov bl,dl
mul bl
add di,ax
mov ax,0b800h
mov es,ax
ret
showStrRet:
pop di
pop si
pop bx
pop es
pop cx
pop dx
ret
; *******************************************************
;=====================================================
;name: getstr
;parameter instructions: 显示位置 dh->行 dl->列
; si->输入数据栈位置, 需要自行在数据段内定义
;;==============获取用户输入===================
; mov si,charStackData
; mov dh,2
; mov dl,40
; call getstr
;==============获取用户输入===================
getstr:
push ax
getstrs:
mov ah,0
int 16h ;调用16号中断的0号功能,al ->返回的字符
cmp al,20h
jb nochar
mov ah,0
call charstack ;字符入栈
mov ah,2
call charstack ;显示字符串
jmp getstrs ;接收下一个字符
nochar:
cmp ah,0eh ;退格键
je backKey
cmp ah,1ch ;Enter键
je enterKey
jmp getstrs
backKey:
mov ah,1
call charstack
mov ah,2
call charstack
jmp getstrs
enterKey:
mov al,20h
mov ah,0
call charstack ;将空格入栈,表示结束
mov al,0
mov ah,0
call charstack ;将0入栈,表示结束
mov ah,2
call charstack
pop ax
ret
;=====================================================
;======================================================
;字符串入栈出栈
;参数说明
;ah = 功能号 0->字符入栈 1->字符出栈 2->显示字符串
;ds:si 指向字符栈空间
;0号功能:(al) = 需要入栈字符
;1号功能:(al) = 返回的字符
;2号功能:(dh),(dl)=字符串在屏幕上显示行列的位置
;========================================================
;初始化
charstack:
jmp short charstart
table dw charpush,charpop,charshow
top dw 0
charstart:
push bx
push dx
push di
push es
cmp ah,2
ja charstackRet ;输入功能超出限制
mov bl,ah
mov bh,0
add bx,bx ;eg: 2号功能函数地址存储在table[4]中
jmp word ptr table[bx] ;跳转到指定功能函数
charpush:
mov bx,top
mov [si][bx],al
inc top
jmp charstackRet
charpop:
cmp top,0
je charstackRet
dec top
mov bx,top
mov al,[si][bx]
jmp charstackRet
charshow:
mov bx,0b800H
mov es,bx
mov al,160
mov ah,0
mul dh
mov di,ax
add dl,dl ;显示位置: dh *160 + di*2
mov dh,0
add di,dx ;由es:di指向显示位置
mov bx,0 ;bx用于计数,当bx等于top时则显示字符完成
charshows:
cmp bx,top
jne toshow
mov byte ptr es:[di],' ' ;如果退格时 清除退格的字符
jmp charstackRet
toshow:
mov al,[si][bx] ;使用BX遍历堆栈 ,实现队列输出
mov es:[di],al
mov byte ptr es:[di+2], ' ' ;清除之前的显示
inc bx
add di,2
jmp charshows
;===============================
charstackRet:
pop es
pop di
pop dx
pop bx
ret
codesg ends
end start
实验结果
实验结果