سلام .
چون اخیرا خیلی سوال شده بود و دوستان زیادی دنبال ماشین حساب بودن من علاوه بر پروژه هایی که دوستان از ترم های قبل گذاشتن اینا رو هم قرار میدم تا انشاالله مورد استفاده قرار بگیره و مفید واقع بشه . (انشاالله بعد از کنکور سورسهای بیشتری از اسمبلی تو بخش کتابخونه انجمن قرار میگیره که دوستان بتونن استفاده کنن . )
چند تا ماشین حساب اینجا معرفی میکنم . یکی گرافیکی هست و دوتای دیگه معمولی .
ابتدا سورس کد کامل این برنامه ها رو میزارم و در انتها هم سورس کدها رو ضمیمه کردم .
شبیه ساز emu8086 4.08 و فایلهای Masm و Link هم ضمیمه شدن که میتونید دنلود کنید . (برای یادگرفتن کار با Masm میتونید اینجا رو بخونید : نحوه کامپایل و ساخت فایل اجرایی از سورس کد های اسمبلی )
برنامه اول ماشین حساب گرافیکی تحت داس : ( تست شده و اجرا شده در emu8086 )
توضیحات این برنامه
دستورات اصلی بدین شرح هستند:
0)عدد موجود در x را چاپ کن
1)عدد اول را دریافت کن(رشته را در buffer قرار بده، و عدد را در x قرار بده)
2)بعد از آن عملگر اول را دریافت کن
3)اگر عملگر "=" بود ، به خط صفر برگرد؛در غبر این صورت ادامه بده :
4)عدد دوم را دریافت کن(رشته را در buffer قرار بده و عدد را درy قرار بده)
5)عملگر دوم را دریافت کن
6)با فراخوانی calculatore نتیجه عبارت x(عملگر اول)y را حساب کن و حاصل را در xقرار بده
7)اگر عملگر دوم "=" بود، به خط 0 برگرد؛در غیر اینصورت ادامه بده:
8)عملگر دوم را در عملگر اول قرار بده و به خط 5 برگرد.
با این دستورات مثلا شما میتوانید عبارت 3*6-4+8= و یا 4+5= ویا -6/5= را وارد کنید.
البته به این دلیل که x,y را word تعریف کردم و از همان ثبات های دوبیتی استفاده کردم فقط میشود اعداد تا پنج رقم را استفاده کرد و اگر حاصل از آن بیشتر شد علامت o بمعنی سرریز در گوشه صفحه چاپ میشود که باید در اینصورت دکمه C را کلیک کرد تا برنامه به خط صفر برگردد.
برنامه فقط تا پنج رفم را دریافت میکند و رقم بعدی را _هرچه باشد_ عملگر "=" حساب میکند.
ضمنا اعداد مثبت و منفی را هم در محاسبات درنظر میگیرد.برای وارد کردن عدد منفی باید بنویسی -8= یا -8*... .
این هم دستورات اصلی برنامست:
call print_screen
begin:
reset
calc1:
putrez buffer,x ;print x
number_in x,operand1,lenth
mov al,operand1
cmp al,'='
je calc1
calc2:
number_in y,operand2,lenth
call calculate ;x = x (operand1) y
mov al,operand2
cmp al,'='
je calc1 ;if(operand2=='='):printx,start again.
mov operand1,al ;else:operand1=operand2,printx,get buffer again.
putrez buffer,x
jmp calc2
cmp of,1 ;print owerflow mark
jne pz1
gotoxy 24,3
putch 'F',12
jmp pz2 ;print xsighn
pz1:
cmp xsighn,1
jne pz2
gotoxy 23,3
putch '-',12
pz2:
pop_all
endm
;---------------------------------------------------
reset macro
mov x,0
mov y,0
mov xsighn,0
mov of,0
clear buffer
mov key,0
mov operand1,0
endm
;---------------------------------------------------
;---------------------------------------------------
;--------- D A T A -------- S E G M E N T-----------
;---------------------------------------------------
;---------------------------------------------------
data segment
; add your data here!
;vars
;---------------------------------------------------
x dw 0
y dw 0
buffer db 5 dup(0),'$'
lenth dw 0
operand1 db 0
operand2 db 0
key db 0
of db 0
ng db 0
xsighn db 0
ysighn db 0
;---------------------------------------------------
;print lines
;---------------------------------------------------
l0 db 218,17 dup(196),191,'$'
l1 db 179,' ',201,205,187,201,10 dup(205),187,' ',179,'$'
l2 db 179,' ',186,' ',186,186,10 dup(' '),186,' ',179,'$'
l3 db 179,' ',200,205,188,200,10 dup(205),188,' ',179,'$'
l4 db 179,' ',218,196,191,' ',218,196,191,' ',218,196,191,' ',218,196,191,' ',179,'$'
l5 db 179,' ',179,' ',179,' ',179,' ',179,' ',179,' ',179,' ',179,' ',179,' ',179,'$'
l6 db 179,' ',192,196,217,' ',192,196,217,' ',192,196,217,' ',192,196,217,' ',179,'$'
l7 db 192,17 dup(196),217,'$'
;---------------------------------------------------
ends
;---------------------------------------------------
;---------------------------------------------------
;--------- S T A C K S E G M E N T --------------
;---------------------------------------------------
;---------------------------------------------------
stack segment
dw 128 dup(0)
ends
code segment
start:
; set segment registers:
mov ax, data
mov ds, ax
mov es, ax
;--------------------------------------------------
;--------------------------------------------------
;--- C A L C U L A T O R E -------- P R O C ------
;--------------------------------------------------
;--------------------------------------------------
call print_screen
begin:
reset
calc1:
putrez buffer,x ;print x
number_in x,operand1,lenth
mov al,operand1
cmp al,'='
je calc1
calc2:
number_in y,operand2,lenth
call calculate ;x = x (operand1) y
mov al,operand2
cmp al,'='
je calc1 ;if(operand2=='='):printx,start again.
mov operand1,al ;else:operand1=operand2,printx,get buffer again.
putrez buffer,x
jmp calc2
;--------------------------------------------------
;--------------------------------------------------
;------------- F U N C T I O N S -----------------
;--------------------------------------------------
;--------------------------------------------------
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; this maro is copied from emu8086.inc ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; this macro prints a char in AL and advances
; the current cursor position:
PUTC MACRO char
PUSH AX
MOV AL, char
MOV AH, 0Eh
INT 10h
POP AX
ENDM
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
org 100h
jmp start
; define variables:
msg0 db "note: calculator works with integer values only.",0Dh,0Ah
db "to learn how to output the result of a float division see float.asm in examples",0Dh,0Ah,'$'
msg1 db 0Dh,0Ah, 0Dh,0Ah, 'enter first number: $'
msg2 db "enter the operator: + - * / : $"
msg3 db "enter second number: $"
msg4 db 0dh,0ah , 'the approximate result of my calculations is : $'
msg5 db 0dh,0ah ,'thank you for using the calculator! press any key... ', 0Dh,0Ah, '$'
err1 db "wrong operator!", 0Dh,0Ah , '$'
smth db " and something.... $"
; operator can be: '+','-','*','/' or 'q' to exit in the middle.
opr db '?'
; first and second number:
num1 dw ?
num2 dw ?
start:
mov dx, offset msg0
mov ah, 9
int 21h
lea dx, msg1
mov ah, 09h ; output string at ds:dx
int 21h
; get the multi-digit signed number
; from the keyboard, and store
; the result in cx register:
call scan_num
; store first number:
mov num1, cx
; new line:
putc 0Dh
putc 0Ah
lea dx, msg2
mov ah, 09h ; output string at ds:dx
int 21h
; get operator:
mov ah, 1 ; single char input to AL.
int 21h
mov opr, al
; new line:
putc 0Dh
putc 0Ah
cmp opr, 'q' ; q - exit in the middle.
je exit
cmp opr, '*'
jb wrong_opr
cmp opr, '/'
ja wrong_opr
; output of a string at ds:dx
lea dx, msg3
mov ah, 09h
int 21h
; get the multi-digit signed number
; from the keyboard, and store
; the result in cx register:
call scan_num
; store second number:
mov num2, cx
lea dx, msg4
mov ah, 09h ; output string at ds:dx
int 21h
; calculate:
cmp opr, '+'
je do_plus
cmp opr, '-'
je do_minus
cmp opr, '*'
je do_mult
cmp opr, '/'
je do_div
; none of the above....
wrong_opr:
lea dx, err1
mov ah, 09h ; output string at ds:dx
int 21h
exit:
; output of a string at ds:dx
lea dx, msg5
mov ah, 09h
int 21h
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; these functions are copied from emu8086.inc ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; gets the multi-digit SIGNED number from the keyboard,
; and stores the result in CX register:
SCAN_NUM PROC NEAR
PUSH DX
PUSH AX
PUSH SI
MOV CX, 0
; reset flag:
MOV CS:make_minus, 0
next_digit:
; get char from keyboard
; into AL:
MOV AH, 00h
INT 16h
; and print it:
MOV AH, 0Eh
INT 10h
; check for MINUS:
CMP AL, '-'
JE set_minus
; check for ENTER key:
CMP AL, 0Dh ; carriage return?
JNE not_cr
JMP stop_input
not_cr:
POP SI
POP AX
POP DX
RET
make_minus DB ? ; used as a flag.
SCAN_NUM ENDP
; this procedure prints number in AX,
; used with PRINT_NUM_UNS to print signed numbers:
PRINT_NUM PROC NEAR
PUSH DX
PUSH AX
CMP AX, 0
JNZ not_zero
PUTC '0'
JMP printed
not_zero:
; the check SIGN of AX,
; make absolute if it's negative:
CMP AX, 0
JNS positive
NEG AX
PUTC '-'
positive:
CALL PRINT_NUM_UNS
printed:
POP AX
POP DX
RET
PRINT_NUM ENDP
; this procedure prints out an unsigned
; number in AX (not just a single digit)
; allowed values are from 0 to 65535 (FFFF)
PRINT_NUM_UNS PROC NEAR
PUSH AX
PUSH BX
PUSH CX
PUSH DX
; flag to prevent printing zeros before number:
MOV CX, 1
; (result of "/ 10000" is always less or equal to 9).
MOV BX, 10000 ; 2710h - divider.
; AX is zero?
CMP AX, 0
JZ print_zero
begin_print:
; check divider (if zero go to end_print):
CMP BX,0
JZ end_print
; avoid printing zeros before number:
CMP CX, 0
JE calc
; if AX<BX then result of DIV will be zero:
CMP AX, BX
JB skip
calc:
MOV CX, 0 ; set flag.
STACK SEGMENT PARA STACK 'STACK'
DB 64 DUP(?)
STACK ENDS
;**************************************14 ;DATA SEGMENT
DATA SEGMENT PARA 'DATA'
ORG 50H
UP DB 0C9H, 16 DUP(0CDH), 0BBH, '$'
L1 DB 0BAH, ' ADDITION ', 0BAH, '$'
L2 DB 0CCH, 16 DUP(0CDH), 0B9H, '$'
L3 DB 0BAH, ' SUBTRACTION ', 0BAH, '$'
L4 DB 0CCH, 16 DUP(0CDH), 0B9H, '$'
L5 DB 0BAH, ' MULTIPLICATION ', 0BAH, '$'
L6 DB 0CCH, 16 DUP(0CDH), 0B9H, '$'
L7 DB 0BAH, ' DIVISION ', 0BAH, '$'
L8 DB 0CCH, 16 DUP(0CDH), 0B9H, '$'
L9 DB 0BAH, ' EXIT ', 0BAH, '$'
DOWN DB 0C8H, 16 DUP(0CDH), 0BCH, '$'
PRO DB ':::::::::: PRODUCT BY BAHMAN AKBARZADEH ::::::::::$'
MSG DB ' TO SELECT AN ITEM, USE <UP / DOWN ARROW> AND PRESS < ENTER >.$'
MSG1 DB 'ENTER NUMBER 1: $'
MSG2 DB 'ENTER NUMBER 2: $'
RADD DB 'RESULT OF ADDITION IS : $'
RSUB DB 'RESULT OF SUBTRACTION IS : $'
RMUL DB 'RESULT OF MULTIPLICATION IS : $'
RDIV DB 'RESULT OF DIVISION IS : $'
STRDATA1 LABEL BYTE
MAX1 DB 5
LEN1 DB ?
DATA1 DB 5 DUP(?)
STRDATA2 LABEL BYTE
MAX2 DB 5
LEN2 DB ?
DATA2 DB 5 DUP(?)
DATA3 DD ?
NUMBER1 DB 2 DUP(?)
NUMBER2 DB 2 DUP(?)
RESULT DW 10 DUP(0)
STRRESULT DB 40 DUP(5)
DATA ENDS
;****************************************50 ;CODE SEGMENT
CODE SEGMENT PARA 'CODE'
ASSUME CS:CODE,DS:DATA,SS:STACK
MAIN PROC FAR
MOV AX,DATA
MOV DS,AX
;****************************************56 ;DISPLAY MENU
MOV CX,0111H
MOV DX,0220H
CALL DISPLAY
;****************************************60 ;PRINT MSG1
MOV AH,09H
LEA DX,MSG1
INT 21H
;****************************************64 ;GIVE DATA1
MOV AH,0AH
LEA DX,STRDATA1
INT 21H
;*****************************************68 ;LOCATION OF MOUSE
MOV DX,0F10H
MOV BH,0H
MOV AH,02H
INT 10H
;****************************************73 ;PRINT MSG2
MOV AH,09H
LEA DX,MSG2
INT 21H
;****************************************77 ;GIVE DATA2
MOV AH,0AH
LEA DX,STRDATA2
INT 21H
;*****************************************81 ;DATA1(ASCII) TO DATA3(HEX)
MOV SI,0H
START: MOV AH,[OFFSET DATA1+SI]
CMP AH,39H
JL X1
SUB AH,7H
X1: AND AH,0FH
MOV [OFFSET DATA3+SI],AH
INC SI
CMP SI,4
JNE START
;*****************************************92 ;4 BYTE OF DATA3 TO 2 BYTE OF NUMBER1
LEA SI,DATA3
MOV AH,[SI]
MOV BH,[SI+1]
MOV CL,4
SHL AH,CL
OR AH,BH
MOV NUMBER1,AH
MOV AH,[SI+2]
MOV BH,[SI+3]
MOV CL,4
SHL AH,CL
OR AH,BH
MOV NUMBER1+1,AH
;*****************************************107 ;DATA2(ASCII) TO DATA3(HEX)
MOV SI,0H
START2: MOV AH,[OFFSET DATA2+SI]
CMP AH,39H
JL X2
SUB AH,7H
X2: AND AH,0FH
MOV [OFFSET DATA3+SI],AH
INC SI
CMP SI,4
JNE START2
;*****************************************118 ;4 BYTE OF DATA3 TO 2 BYTE OF NUMBER2
LEA SI,DATA3
MOV AH,[SI]
MOV BH,[SI+1]
MOV CL,4
SHL AH,CL
OR AH,BH
MOV NUMBER2,AH
MOV AH,[SI+2]
MOV BH,[SI+3]
MOV CL,4
SHL AH,CL
OR AH,BH
MOV NUMBER2+1,AH
;*****************************************133 ;PRIMARY PART
MOV CX,0111H
MOV DX,0220H
BACK: CALL DISPLAY
;*****************************************137 ;LOCATION OF MOUSE
PUSH DX
MOV DX,1008H
MOV BH,0H
MOV AH,02H
INT 10H
;****************************************143 ;PRINT MSG
MOV AH,09H
LEA DX,MSG
INT 21H
POP DX
;****************************************148 PRIMARY PART
CALL INPUT
CMP BH,0EH
JNE BACK
CMP CH,01H
JNE Z1
CALL ADDITION
JMP BACK
Z1: CMP CH,03H
JNE Z2
CALL SUBTRACTION
JMP BACK
Z2: CMP CH,05H
JNE Z3
CALL MULTIPLICATION
JMP BACK
Z3: CMP CH,07H
JNE Z4
CALL DIVISION
JMP BACK
;*****************************************168 ;CLEAR SCREEN
Z4: MOV AH,06H
MOV BH,07H
MOV CX,0H
MOV DX,2579H
MOV AL,0H
INT 10H
;*****************************************175 ;LOCATION OF MOUSE
MOV DX,0C0EH
MOV BH,0H
MOV AH,02H
INT 10H
;*****************************************180 ;END NAMEH
LEA DX,PRO
MOV AH,09H
INT 21H
;*****************************************184 ;GETCH()
MOV AH,01H
INT 21H
;****************************************187 ;END
MOV AH,4CH
INT 21H
MAIN ENDP
;THIS PART GIVE SELECTED ITEM FROM KEYBORD
;TISH PART CHANGE CX AND DX FOR SELECTED ITEM
INPUT PROC NEAR
;*****************************************338 ;PUSH SEGMENTS
PUSH AX
;*****************************************340 ;GIVE KEY
MOV AH,0H
INT 16H
;*****************************************343 ;MOVE
MOV BH,0H
CMP AH,50H
JNE NEXT
CMP CH,09H
JNE R1
MOV CH,01H
MOV DH,02H
JMP END
R1: ADD CH,2H
ADD DH,2H
NEXT: CMP AH,48H
JNE NEXT2
CMP CH,01H
JNE R2
MOV CH,09H
MOV DH,0AH
JMP END
R2: SUB CH,2H
SUB DH,2H
NEXT2: CMP AL,0DH
JNE END
MOV BH,0EH
;*****************************************366 ;POP SEGMENTS
END: POP AX
;*****************************************368
RET
INPUT ENDP
;THIS PART ADDS NUMBER1 AND NUMBER2 THEN PRINT RESULT
ADDITION PROC NEAR
;*****************************************377 ;PUSH SEGMENTS
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH SI
PUSH DI
;*****************************************384 ;ADD NUMBER1 AND NUMBER2
CLC
MOV AH,NUMBER1
MOV AL,NUMBER1+1
MOV BH,NUMBER2
MOV BL,NUMBER2+1
ADD AX,BX
MOV RESULT,AX
MOV BX,0
ADC BX,0
MOV RESULT+2,BX
;*****************************************395 ;ASCII OF RESULT TO STRRESULT
CALL ASCII
;*****************************************397 ;LOCATION OF MOUSE
MOV DX,1210H
MOV BH,0H
MOV AH,02H
INT 10H
;****************************************402 ;PRINT RADD
MOV AH,09H
LEA DX,RADD
INT 21H
;*****************************************406 ;PRINT STRRESULT
MOV AH,02H
MOV SI,5
W5: MOV DL,[OFFSET STRRESULT+SI-1]
INT 21H
DEC SI
CMP SI,0
JNE W5
MOV DL,' '
INT 21H
MOV DL,'H'
INT 21H
;*****************************************418 ;GETCH()
MOV AH,01H
INT 21H
;*****************************************421 ;POP SEGMENTS
POP DI
POP SI
POP DX
POP CX
POP BX
POP AX
;*****************************************428
RET
ADDITION ENDP
;THIS PART SUBTRACT NUMBER1 AND NUMBER2 THEN PRINT RESULT
SUBTRACTION PROC NEAR
;*****************************************438 ;PUSH SEGMENTS
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH SI
PUSH DI
;*****************************************445 ;SUBTRACT NUMBER2 OF NUMBER1
MOV AH,NUMBER1
MOV AL,NUMBER1+1
MOV BH,NUMBER2
MOV BL,NUMBER2+1
SUB AX,BX
MOV RESULT,AX
MOV BH,0
ADC BH,0
CMP BH,1
JNE W7
MOV RESULT+2,0FH
;*****************************************457 ;ASCII OF RESULT TO STRRESULT
W7: CALL ASCII
;*****************************************459 ;LOCATION OF MOUSE
MOV DX,1210H
MOV BH,0H
MOV AH,02H
INT 10H
;****************************************464 ;PRINT RSUB
MOV AH,09H
LEA DX,RSUB
INT 21H
;*****************************************468 ;PRINT STRRESULT
MOV AH,02H
MOV SI,5
W6: MOV DL,[OFFSET STRRESULT+SI-1]
INT 21H
DEC SI
CMP SI,0
JNE W6
MOV DL,' '
INT 21H
MOV DL,'H'
INT 21H
;*****************************************480 ;GETCH()
MOV AH,01H
INT 21H
;*****************************************483 ;POP SEGMENTS
POP DI
POP SI
POP DX
POP CX
POP BX
POP AX
;*****************************************490
RET
SUBTRACTION ENDP
MOV AH,STRRESULT+19
ADD AH,DH
MOV DH,AH
AND AH,0FH
SHR DH,CL
MOV STRRESULT+7,AH
;*****************************************629 ;NUMBERS TO ASCII
MOV SI,0
W11: MOV AH,[OFFSET STRRESULT+SI]
CMP AH,0AH
JL W12
ADD AH,7H
W12: ADD AH,30H
MOV [OFFSET STRRESULT+SI],AH
INC SI
CMP SI,8
JNE W11
;*****************************************640 ;LOCATION OF MOUSE
MOV DX,1210H
MOV BH,0H
MOV AH,02H
INT 10H
;****************************************645 ;PRINT RMUL
MOV AH,09H
LEA DX,RMUL
INT 21H
;*****************************************649 ;PRINT STRRESULT
MOV AH,02H
MOV SI,8
W13: MOV DL,[OFFSET STRRESULT+SI-1]
INT 21H
DEC SI
CMP SI,0
JNE W13
MOV DL,' '
INT 21H
MOV DL,'H'
INT 21H
;****************************************661 ;GETCH()
MOV AH,01H
INT 21H
;*****************************************664 ;POP SEGMENTS
POP DI
POP SI
POP DX
POP CX
POP BX
POP AX
;*****************************************671
RET
MULTIPLICATION ENDP
;THIS PART DIVIDE NUMBER1 AND NUMBER2 THEN PRINT RESULT
DIVISION PROC NEAR
;*****************************************681 ;PUSH SEGMENTS
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH SI
PUSH DI
;*****************************************688 ;DIVIDE NUMBER1 ON NUMBER2
MOV AH,NUMBER1
MOV AL,NUMBER1+1
MOV BH,NUMBER2
MOV BL,NUMBER2+1
DIV BX
MOV RESULT,AX
;*****************************************695 ;ASCII OF RESULT TO STRRESULT
CALL ASCII
;*****************************************697 ;LOCATION OF MOUSE
MOV DX,1210H
MOV BH,0H
MOV AH,02H
INT 10H
;****************************************702 ;PRINT RDIV
MOV AH,09H
LEA DX,RDIV
INT 21H
;*****************************************706 ;PRINT STRRESULT
MOV AH,02H
MOV SI,4
W14: MOV DL,[OFFSET STRRESULT+SI-1]
INT 21H
DEC SI
CMP SI,0
JNE W14
MOV DL,' '
INT 21H
MOV DL,'H'
INT 21H
;*****************************************718 ;GETCH()
MOV AH,01H
INT 21H
;*****************************************721 ;POP SEGMENTS
POP DI
POP SI
POP DX
POP CX
POP BX
POP AX
;*****************************************728
RET
DIVISION ENDP
;THIS PART CONVERT RESULT TO ASCII AND SAVE IT INTO STRRESULT
ASCII PROC NEAR
;*****************************************738 ;PUSH SEGMENTS
PUSH AX
PUSH DX
PUSH SI
PUSH DI
;*****************************************743 ;NUMBERS OF RESULT TO ASSCII OF STRRESULT
MOV DI,0
MOV SI,0
W2: MOV AL,[OFFSET RESULT+DI]
MOV DL,AL
AND AL,0FH
MOV CL,4
SHR DL,CL
OR AL,30H
CMP AL,3AH
JB W3
ADD AL,7
W3: OR DL,30H
CMP DL,3AH
JB W4
ADD DL,7
W4: MOV AH,DL
MOV [OFFSET STRRESULT+SI],AX
INC DI
ADD SI,2
CMP DI,8
JNE W2
;*****************************************765 ;POP SEGMENTS
POP DI
POP SI
POP DX
POP AX
;*****************************************770
RET
ASCII ENDP
علاقه مندی ها (Bookmarks)