Ensamblador - Ayuda

 
Vista:

Ayuda

Publicado por Andres Rodriguez (2 intervenciones) el 03/04/2009 16:12:30
Por favor necesito el codigo fuente en ensamblador de una calculadora basica que sume, reste, multiplique y divida.
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder

RE:Ayuda

Publicado por Perceval (13 intervenciones) el 13/04/2009 22:43:52
Para que tengas una idea, es un ejemplo que viene con Emu8086.

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

Continua
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Ayuda

Publicado por Perceval (13 intervenciones) el 13/04/2009 22:44:15
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
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar