8. • Ejecutar el programa hola mundo, y debe cambiar los mensajes de
pantalla al español:
9. Código:
name "hola-mundo"
; this example prints out "hello world!"
; by writing directly to video memory.
; in vga memory: first byte is ascii character, byte that follows is character attribute.
; if you change the second byte, you can change the color of
; the character even after it is printed.
; character attribute is 8 bit value,
; high 4 bits set background color and low 4 bits set foreground color.
; hex bin color
;
; 0 0000 black
; 1 0001 blue
; 2 0010 green
; 3 0011 cyan
; 4 0100 red
; 5 0101 magenta
; 6 0110 brown
; 7 0111 light gray
10. ; 8 1000 dark gray
; 9 1001 light blue
; a 1010 light green
; b 1011 light cyan
; c 1100 light red
; d 1101 light magenta
; e 1110 yellow
; f 1111 white
org 100h
; set video mode
mov ax, 3 ; text mode 80x25, 16 colors, 8 pages (ah=0, al=3)
int 10h ; do it!
; cancel blinking and enable all 16 colors:
mov ax, 1003h
mov bx, 0
int 10h
; set segment register:
mov ax, 0b800h
mov ds, ax
; print "hello world"
; first byte is ascii code, second byte is color code.
mov [02h], 'H'
11. mov [04h], 'o'
mov [06h], 'l'
mov [08h], 'a'
mov [0ah], ','
mov [0ch], 'M'
mov [0eh], 'u'
mov [10h], 'n'
mov [12h], 'd'
mov [14h], 'o'
; color all characters:
mov cx, 12 ; number of characters.
mov di, 03h ; start from byte after 'h'
c: mov [di], 11101100b ; light red(1100) on yellow(1110)
add di, 2 ; skip over next ascii code in vga memory.
loop c
12. ; wait for any key press:
mov ah, 0
int 16h
ret
Compilar un programa en EMU8086 que indique lo siguiente: Nombre
completo del estudiante, Universidad, Fecha y materia:
13. Codigo:
.MODEL SMALL ;modelo pequeño de compilación (64k como máximo)
.STACK 100h ;Segmento de pila: Pila 256 posiciones
CR EQU 13 ;Declaración de constantes
LF EQU 10
.DATA ;Comienzo del segmento de datos
TEXTO DB 'Fabricio Xavier Galarraga Perez PUCESI 26/04/2019 Compiladores',CR,LF ;Reserva
de memoria con retorno de carro e
;Inicio de línea, la variable TEXTO es de tipo
;byte,el símbolo $ es el símbolo de fin de cadena
.CODE ;Comienzo del segmento de código
MOV AX, SEG TEXTO ;Mueve a AX la dirección del primer byte del
;segmento de datos
MOV DS,AX ;Mueve dicha dirección al segmento de datos
LEA DX,TEXTO ;Cargamos en DX la dirección efectiva del texto
;que vamos a imprimir por pantalla
MOV AH,9 ;función "Escribir texto por pantalla"
INT 21h ;Llamada a DOS por medio de la interrupción
;para ejecutar la función
MOV AH,4ch ;función "Retornar a DOS"
INT 21h ;Interrupción que llama a DOS para terminar el
;programa
END ;fin
Compilar un programa que permita comparar 2 números del 0 al 9:
14.
15. Código:
name "flags"
org 100h
; this sample shows how cmp instruction sets the flags.
; usually cmp instruction is followed by any relative
; jump instruction such as: je, ja, jl, jae...
; it is recommended to click "flags" and "analyze"
; for better visual expirience before stepping through this code.
; (signed/unsigned)
; 4 is equal to 4
mov ah, 4
mov al, 4
cmp ah, al
nop
; (signed/unsigned)
; 4 is above and greater then 3
mov ah, 4
mov al, 3
16. cmp ah, al
nop
; -5 = 251 = 0fbh
; (signed)
; 1 is greater then -5
mov ah, 1
mov al, -5
cmp ah, al
nop
; (unsigned)
; 1 is below 251
mov ah, 1
mov al, 251
cmp ah, al
nop
; (signed)
; -3 is less then -2
mov ah, -3
mov al, -2
cmp ah, al
nop
; (signed)
; -2 is greater then -3
mov ah, -2
mov al, -3
cmp ah, al
nop
; (unsigned)
; 255 is above 1
mov ah, 255
mov al, 1
17. cmp ah, al
nop
; now a little game:
game: mov dx, offset msg1
mov ah, 9
int 21h
; read character in al:
mov ah, 1
int 21h
cmp al, '0'
jb stop
cmp al, '9'
ja stop
cmp al, '3'
jb below
ja above
mov dx, offset equal_5
jmp print
below: mov dx, offset below_5
jmp print
above: mov dx, offset above_5
print: mov ah, 9
int 21h
jmp game ; loop.
stop: ret ; stop
msg1 db "enter a number or any other character to exit: $"
equal_5 db " es el tres! (igual)", 0Dh,0Ah, "$"
below_5 db " is menor que tres!" , 0Dh,0Ah, "$"
above_5 db " is mayor que tres!" , 0Dh,0Ah, "$"
19. Codigo:
name "calcular-suma"
org 100h ; directive make tiny com file.
; calculate the sum of elements in vector,
; store result in m and print it in binary code.
; number of elements:
mov cx, 10
; al will store the sum:
mov al, 0
; bx is an index:
mov bx, 0
; sum elements:
next: add al, vector[bx]
; next byte:
inc bx
; loop until cx=0:
loop next
; store result in m:
mov m, al
20. ; print result in binary:
mov bl, m
mov cx, 8
print: mov ah, 2 ; print function.
mov dl, '0'
test bl, 10000000b ; test first bit.
jz zero
mov dl, '1'
zero: int 21h
shl bl, 1
loop print
; print binary suffix:
mov dl, 'b'
int 21h
mov dl, 0ah ; new line.
int 21h
mov dl, 0dh ; carrige return.
int 21h
; print result in decimal:
mov al, m
call print_al
; wait for any key press:
mov ah, 0
int 16h
ret
; variables:
vector db 5, 4, 5, 2, 1, 4, 2, 1, 3, 1
m db 0
print_al proc
cmp al, 0
jne print_al_r
21. push ax
mov al, '0'
mov ah, 0eh
int 10h
pop ax
ret
print_al_r:
pusha
mov ah, 0
cmp ax, 0
je pn_done
mov dl, 10
div dl
call print_al_r
mov al, ah
add al, 30h
mov ah, 0eh
int 10h
jmp pn_done
pn_done:
popa
ret
endp
22. Compilar un programa sugerido por usted, como propuesta adicional:
Codigo:
name "calculadora"
; 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
23. 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, 'ponga el primer numero: $'
msg2 db "ponga un operador: + - * / : $"
msg3 db "ponga el segundo numero: $"
msg4 db 0dh,0ah , 'el resultado aproximado es : $'
msg5 db 0dh,0ah ,'gracias por usar la calculadora! presione
cualquier tecla... ', 0Dh,0Ah, '$'
err1 db "operacion erronea!", 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 ?
24. 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
25. 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
26. 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
27. 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,
28. ; 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
29. 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
30. 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.
31. 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,
32. ; 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).
33. 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
34. 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
35. 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.
36. 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