necesito calculadora basica en lenguaje ensamblador

jonathan
30 de Noviembre del 2005
necesito una calculadora basica en lenguaje ensamblador urgente.
gracias por la ayuda chao gracias

robert
30 de Noviembre del 2005
yo tambien, ya la cvonsiguio

d
30 de Noviembre del 2005
nosotros tambien necesitamos una, se la acepto lo mas tarde el viernes

CarlosNuel
30 de Noviembre del 2005
y porqué no intentan hacerla y en lo que se equivoquen piden asesoria.
PD. el programa no es muy dificil

Einstein
30 de Noviembre del 2005
Tal vez te sirva este...


name "calc2"

; command prompt based simple calculator (+,-,*,/) for 8086.
; example of calculation:
; input 1 <- number: 10
; input 2 <- operator: -
; input 3 <- number: 5
; -------------------
; 10 - 5 = 5
; output -> number: 5





;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; 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


; wait for any key...
mov ah, 0
int 16h


ret ; return back to os.











do_plus:


mov ax, num1
add ax, num2
call print_num ; print ax value.

jmp exit



do_minus:

mov ax, num1
sub ax, num2
call print_num ; print ax value.

jmp exit




do_mult:

mov ax, num1
imul num2 ; (dx ax) = ax * num2.
call print_num ; print ax value.
; dx is ignored (calc works with tiny numbers only).

jmp exit




do_div:
; dx is ignored (calc works with tiny integer numbers only).
mov dx, 0
mov ax, num1
idiv num2 ; ax = (dx ax) / num2.
cmp dx, 0
jnz approx
call print_num ; print ax value.
jmp exit
approx:
call print_num ; print ax value.
lea dx, smth
mov ah, 09h ; output string at ds:dx
int 21h
jmp exit









;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; 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:


CMP AL, 8 ; \'BACKSPACE\' pressed?
JNE backspace_checked
MOV DX, 0 ; remove last digit by
MOV AX, CX ; division:
DIV CS:ten ; AX = DX:AX / 10 (DX-rem).
MOV CX, AX
PUTC \' \' ; clear position.
PUTC 8 ; backspace again.
JMP next_digit
backspace_checked:


; allow only digits:
CMP AL, \'0\'
JAE ok_AE_0
JMP remove_not_digit
ok_AE_0:
CMP AL, \'9\'
JBE ok_digit
remove_not_digit:
PUTC 8 ; backspace.
PUTC \' \' ; clear last entered not digit.
PUTC 8 ; backspace again.
JMP next_digit ; wait for next input.
ok_digit:


; multiply CX by 10 (first time the result is zero)
PUSH AX
MOV AX, CX
MUL CS:ten ; DX:AX = AX*10
MOV CX, AX
POP AX

; check if the number is too big
; (result should be 16 bits)
CMP DX, 0
JNE too_big

; convert from ASCII code:
SUB AL, 30h

; add AL to CX:
MOV AH, 0
MOV DX, CX ; backup, in case the result will be too big.
ADD CX, AX
JC too_big2 ; jump if the number is too big.

JMP next_digit

set_minus:
MOV CS:make_minus, 1
JMP next_digit

too_big2:
MOV CX, DX ; restore the backuped value before add.
MOV DX, 0 ; DX was zero before backup!
too_big:
MOV AX, CX
DIV CS:ten ; reverse last DX:AX = AX*10, make AX = DX:AX / 10
MOV CX, AX
PUTC 8 ; backspace.
PUTC \' \' ; clear last entered digit.
PUTC 8 ; backspace again.
JMP next_digit ; wait for Enter/Backspace.


stop_input:
; check flag:
CMP CS:make_minus, 0
JE not_minus
NEG CX
not_minus:

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.

MOV DX, 0
DIV BX ; AX = DX:AX / BX (DX=remainder).

; print last digit
; AH is always ZERO, so it\'s ignored
ADD AL, 30h ; convert to ASCII code.
PUTC AL


MOV AX, DX ; get remainder from last div.

skip:
; calculate BX=BX/10
PUSH AX
MOV DX, 0
MOV AX, BX
DIV CS:ten ; AX = DX:AX / 10 (DX=remainder).
MOV BX, AX
POP AX

JMP begin_print

print_zero:
PUTC \'0\'

end_print:

POP DX
POP CX
POP BX
POP AX
RET
PRINT_NUM_UNS ENDP



ten DW 10 ; used as multiplier/divider by SCAN_NUM & PRINT_NUM_UNS.







GET_STRING PROC NEAR
PUSH AX
PUSH CX
PUSH DI
PUSH DX

MOV CX, 0 ; char counter.

CMP DX, 1 ; buffer too small?
JBE empty_buffer ;

DEC DX ; reserve space for last zero.


;============================
; Eternal loop to get
; and processes key presses:

wait_for_key:

MOV AH, 0 ; get pressed key.
INT 16h

CMP AL, 0Dh ; \'RETURN\' pressed?
JZ exit_GET_STRING


CMP AL, 8 ; \'BACKSPACE\' pressed?
JNE add_to_buffer
JCXZ wait_for_key ; nothing to remove!
DEC CX
DEC DI
PUTC 8 ; backspace.
PUTC \' \' ; clear position.
PUTC 8 ; backspace again.
JMP wait_for_key

add_to_buffer:

CMP CX, DX ; buffer is full?
JAE wait_for_key ; if so wait for \'BACKSPACE\' or \'RETURN\'...

MOV [DI], AL
INC DI
INC CX

; print the key:
MOV AH, 0Eh
INT 10h

JMP wait_for_key
;============================

exit_GET_STRING:

; terminate by null:
MOV [DI], 0

empty_buffer:

POP DX
POP DI
POP CX
POP AX
RET
GET_STRING ENDP