8086匯編語言實作簡易計算器
本周看了一個很有意思的知識,
C語言的編譯器最初是怎么來的?
最初應該是由匯編語言實作一個簡化版C語言,然后使用簡化版的C語言進行多次迭代,功能更新,從而出現了如今強大的C語言,
本人找到了一個古老的課程設計,當時學匯編時候的一個小demo分享出來,
1.概述
為了更深入地理解計算機作業原理以及CPU的功能和結構,掌味訓編語言的使用,本文以簡易計算器程式的匯編語言實作為主要任務,進行對程式的一些演算法和匯編語言語法的論述,計算器是最簡單的計算工具,簡單計算器具有加、減、乘、除四項運算功能,想要用匯編語言實作簡單的計算器,就必須通過對資料存盤,暫存器的使用,加減乘除相關指令以及模塊的呼叫等匯編語言知識進行運用,以實作一個基本功能完善,界面友好,操作簡便易行的計算器,用匯編語言實作簡單計算器還涉及到輸入輸出模塊的設計,加減乘除運算的判斷以及退出程式的判斷的設計,通過對各種指令的合理使用,設計各個功能模塊,當實作各個程式模塊后,通程序式的呼叫最終實作一個簡單的計算器,本文以用8086匯編語言實作簡易計算器為目標,對程式的演算法以及結構進行分析和解釋,
匯編語言的陳述句型別有指令陳述句、偽指令陳述句和宏指令陳述句,
在實作簡易計算器的程序中暫不需要宏指令陳述句,故對此陳述句不進行介紹,
計算器的實作需要使用輸入輸出,DOS系統的01H,02H,09H號呼叫可以完成所需功能,
由于簡易計算器對結果沒有很高的范圍要求,故對四則運算只需考慮ADD,SUB,MUL,DIV等指令,在計算器中,輸入的是10進制數字,而在匯編語言中讀入字符只能一位一位的讀取,故需要使用MUL設定一個回圈演算法,將輸入的數字以16進制形式放入暫存器中,而輸出則是使用MOD設定一個回圈演算法,將16進制轉化為10進制后處理為ASCII碼進行輸出,
2.程式演算法結構
簡易計算器程式的任務主要有處理輸入資料,選擇運算方式進行計算,顯示算式結果,程式中為這三個任務做了5個子程式:do_before,do_add,do_sub,do_mul,do_div,show,
簡易計算機結構
在進行簡易計算器程式的制作之前,需要設計程式的結構,從簡易計算器設計的任務要求可知,需要計算機先進行判定需要進行的運算方式,對輸入資料進行計算,最后輸出輸入的算式及計算結果,如:
系統輸出:please input the operator(from + - * /):
用戶輸入運算子選擇運算方式
系統輸出:please input the x and y:
用戶輸入兩個運算元
系統輸出:x+y=z (進行加法運算)
程式流程圖如下:(很簡陋,本科階段畫的)

演算法介紹
主要需要用到的子程式主要有輸入轉化子程式do_before:DOS功能01H號呼叫中的輸入,是將數字一位一位地存盤在AL暫存器中的(如123,讀入暫存器的為1,2,3),而且輸入的數字是以ASCII碼存盤在暫存器中的,需要將其轉化為ASCII碼代表的數字,并將一位一位的數字合并轉化為一個具有數學意義的多位數字,四則運算子程式do_add,do_sub,do_mul,do_div:主要使用add,sub,mul,div指令,下文中只對do_add子程式進行介紹,其余三個子程式類似,輸出結果子程式show:DOS功能02H號呼叫中的輸出,是輸出一位數字,不能輸出整數型,所以需要對運算結果進行處理,將16進制的資料,轉化為10進制,并一位位地進行輸出,
1.輸入轉化子程式
do_before:
mov ah,1h
int 21h ;呼叫DOS功能1H號,讀入一位數字
mov temp,0
sub al,'0' ;將數字轉化為ASCII碼代表的數字
cmp al,0 ;判斷輸入的是否是數字
jl done1 ;不是數字的話結束輸入
cmp al,9 ;判斷輸入的是否是數字
jg done1 ;不是數字的話結束輸入
xor ah,ah ;高位清零
mov temp,ax
mov ax,x
mul ten ;ten 中存盤的是10
add ax,temp
mov x,ax
jmp do_before ; 輸入未結束,回圈呼叫
done1:
ret
該子程式流程圖如下:

2.加法子程式
do_add:
call crlf ;呼叫輸出回車子程式
mov ax,data
mov ds,ax
mov ah,09h
lea dx,message4 ;輸出’please input the x and y:’
int 21h
call do_before1
call do_before2 ;輸入兩個運算元
call crlf
mov ax,temp1
mov x,ax
call show1
mov dl,'+'
mov ah,2h
int 21h
mov ax,temp2
mov x,ax
call show1
mov ax,temp1
mov x,ax
mov dl,'=' ;輸出算式
mov ah,2h
int 21h
mov ax,x
add ax,y ;進行加法
mov x,ax
call show ;輸出結果
ret
由于該子程式是順序結構,不對其流程圖進行描述,
do_add子程式直接對輸入算式進行了輸出,對兩個運算元進行加法后呼叫了show子程式對結果進行了輸出,兩部分合在一起后便湊成了完整的算式,
3.輸出結果子程式
show: ;顯示結果并結束
mov ax,x ;x中此時存盤的是運算結果
mov bx,0ah ;給bx暫存器中賦10,方便結果輸出
mov cx,0 ;cx暫存器作計數器
step1: mov dx,0
div bx ;執行div指令后商在ax暫存器中,余數在dx暫存器中
cmp ax,0ah ;判斷商是否小于10
jl n1
push dx ;將余數壓入堆疊
inc cx ;計數器加1,cx代表堆疊中數字的數量
jmp step1 ;若商不小于10,則一直進行壓堆疊、判斷的回圈
n1: push dx ;將最后一位余數壓入堆疊
inc cx
push ax ;最后一位小于10的商入堆疊
inc cx
jmp step2
step2: pop dx ;將堆疊中數字依次輸出
add dl,'0'
mov ah,2h
int 21h
loop step2
mov ah,4ch ;回傳DOS
int 21h ;系統呼叫
ret
該子程式的流程圖如下:

該子程式演算法是將16進制數除以10,將余數壓入堆疊,若商大于10,將商除以10,余數再次壓入堆疊,回圈這個步驟直到商小于10,將商壓入堆疊,壓入的順序即是10進制數字由后到前的順序,依次出堆疊得到的結果就是10進制的運算結果,
此外,如do_add子程式中出現的show1子程式,是為了顯示兩個運算元,呼叫完之后不回傳DOS,程式中,將第一個運算元存進了x,第二個運算元存進了y,由于程式中不需要考慮負數作為運算元,故暫存器中存盤的都是無符號數,需要考慮減法和除法中,x小于y的情況,在do_sub中,當判斷x小于y后,將x和y內的資料調換,調換程序中需要借用一個暫存器,在源代碼中借用的ax暫存器,調換之后按正常情況計算,在運算結果前添加負號即得到正確結果,在do_div中,判斷x小于y后,可直接在等號后輸出x,
3.實作效果




4.原始碼
data segment
x dw 0 ;第一個數
y dw 0 ;第二個數
z dw 0
temp1 dw 0
temp2 dw 0
temp dw 0
ten dw 0ah
op db 0 ;運算子
message db 'please choose the operator : (from + - * /)',0ah,0dh,'$'
message2 db 'input error',0ah,0dh,'$'
message3 db '......','$'
message4 db 'please input the x and y:',0ah,0dh,'$'
data ends
assume cs:code,ds:data
code segment
start:
mov ax,data
mov ds,ax
mov ah,09h
lea dx,message
int 21h
call input
input:
mov ah,1h
int 21h
cmp al,'+'
jz nx_1
cmp al,'-'
jz nx_2
cmp al,'*'
jz nx_3
cmp al,'/'
jz nx_4
jnz er_1
er_1:
call crlf
call show_error
call done
nx_1:
call do_add
nx_2:
call do_sub
nx_3:
call do_mul
nx_4:
call do_div
show_error:
mov ax,data
mov ds,ax
mov ah,09h
lea dx,message2
int 21h
do_before1:
mov ah,1h
int 21h
mov temp,0
sub al,'0'
cmp al,0
jl done1
cmp al,9
jg done1
xor ah,ah ;高位清零
mov temp,ax
mov ax,x
mul ten
add ax,temp
mov x,ax
mov temp1,ax
jmp do_before1
done1:
;add x,'0'
ret
do_before2:
mov ah,1h
int 21h
mov temp,0
sub al,'0'
cmp al,0
jl done1
cmp al,9
jg done1
xor ah,ah ;高位清零
mov temp,ax
mov ax,y
mul ten
add ax,temp
mov y,ax
mov temp2,ax
jmp do_before2
done:
mov ax,4c00h
int 21h
do_add:
call crlf
mov ax,data
mov ds,ax
mov ah,09h
lea dx,message4
int 21h
call do_before1
call do_before2
call crlf
mov ax,temp1
mov x,ax
call show1
mov dl,'+'
mov ah,2h
int 21h
mov ax,temp2
mov x,ax
call show1
mov ax,temp1
mov x,ax
mov dl,'='
mov ah,2h
int 21h
mov ax,x
add ax,y
mov x,ax
call show
ret
do_sub:
call crlf
mov ax,data
mov ds,ax
mov ah,09h
lea dx,message4
int 21h
call do_before1
call do_before2
call crlf
call show1
mov dl,'-'
mov ah,2h
int 21h
mov ax,temp2
mov x,ax
call show1
mov ax,temp1
mov x,ax
mov dl,'='
mov ah,2h
int 21h
mov ax,x
cmp ax,y
jl exchange
mov ax,x
sub ax,y
mov x,ax
call show
ret
exchange:
;小x減大y
mov dl,'-'
mov ah,2h
int 21h
mov ax,y
mov bx,x
sub ax,bx
mov x,ax
call show
do_mul:
call crlf
mov ax,data
mov ds,ax
mov ah,09h
lea dx,message4
int 21h
call do_before1
call do_before2
call crlf
call show1
mov dl,'*'
mov ah,2h
int 21h
mov ax,temp2
mov x,ax
call show1
mov ax,temp1
mov x,ax
mov dl,'='
mov ah,2h
int 21h
mov ax,x
mov bx,y
mul bx
mov x,ax
call show
do_div:
call crlf
mov ax,data
mov ds,ax
mov ah,09h
lea dx,message4
int 21h
call do_before1
call do_before2
call crlf
mov ax,temp1
mov x,ax
call show1
mov dl,'/'
mov ah,2h
int 21h
mov ax,temp2
mov x,ax
call show1
mov ax,temp1
mov x,ax
mov dl,'='
mov ah,2h
int 21h
mov ax,x
mov bx,y
cmp ax,bx
jl do_div2
mov dx,0
div bx
mov x,ax
mov temp,dx
cmp dx,0
jz div_0
call show1
mov ax,data ;求余
mov ds,ax
lea dx,message3
mov ah,9h
int 21h
mov ax,temp
mov x,ax
call show1
mov ah,4ch
int 21h
ret
div_0:
call show
do_div2: ;x比y小
mov dl,'0'
mov ah,2h
int 21h
mov ax,data ;求余
mov ds,ax
lea dx,message3
mov ah,9h
int 21h
mov ax,x
call show
crlf: ;回車換行
mov ah,2
mov dl,0DH
int 21H
mov dl,0AH
int 21H
ret
show: ;顯示結果并結束
mov ax,x
mov bx,0ah
mov cx,0
step1: mov dx,0
div bx
cmp ax,0ah
jl n1
push dx
inc cx
jmp step1
n1: push dx
inc cx
push ax
inc cx
jmp step2
step2: pop dx
add dl,'0'
mov ah,2h
int 21h
loop step2
mov ah,4ch
int 21h
ret
show1: ;顯示結果不結束
mov ax,x
mov bx,0ah
mov cx,0
step_1: mov dx,0
div bx
cmp ax,0ah
jl n_1
push dx
inc cx
jmp step_1
n_1: push dx
inc cx
push ax
inc cx
jmp step_2
step_2: pop dx
add dl,'0'
mov ah,2h
int 21h
loop step_2
ret
code ends
end start
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/276936.html
標籤:其他
