Beruflich Dokumente
Kultur Dokumente
42.
saludo db "Hola mundo!!!"
43. DATOS ENDS
44.
45. ;----------------------------------------------------------------------------46. ;Definicion del segmento de pila
47. ;----------------------------------------------------------------------------48. PILA SEGMENT STACK "STACK"
49.
DB 40 DUP(0)
50. PILA ENDS
51.
52. ;----------------------------------------------------------------------------53. ;Definicion del segmento extra
54. ;----------------------------------------------------------------------------55. EXTRA SEGMENT
56.
RESULT DW 0,0
57. EXTRA ENDS
58.
59. ;----------------------------------------------------------------------------60. ;Definicion del segmento de codigo
61. ;----------------------------------------------------------------------------62. CODE SEGMENT
63.
assume cs:code,ds:datos,es:extra,ss:pila
64.
65. START PROC
66.
;Inicializamos los registros de segmento
67.
mov ax,datos
68.
mov ds,ax
69.
mov ax,pila
70.
mov ss,ax
71.
mov ax,extra
72.
mov es,ax
73.
;Fin de las inicializaciones
74.
75.
;Limpiamos la pantalla
76.
mov ax,0B800h
;En esta direccion comienza la memoria de
video
77.
mov es,ax
;Lo cargamos en el segmento extra
78.
xor di,di
;Ponemos DI=0. Esto equivale a mov di,0,
pero
79.
;xor di,di consume 3 ciclos de reloj y
con mov 4
80.
mov cx,80*25
;El tamao total es 2000 (80 lineas x 25
columnas)
81.
82. b_clear:
;Bucle que se encargara de recorrer los
2000
83.
;caracteres de la pantalla para limpiarla
84.
mov al,20h
;20h=" "
Rellenar la pantalla con
espacios
85.
mov ah,1bh
;Fondo azul, letras blancas
86.
mov es:[di],ax
87.
inc di
88.
inc di
89.
loop b_clear
90.
91.
mov ax,0B800h
92.
mov es,ax
93.
mov si,offset saludo
94.
mov di,(80*7+17)*2 ;Linea 7, caracter 18
95.
mov cx,13
96.
97. b_saludo:
;Bucle que se encargara de recorrer los
2000
98.
;caracteres de la pantalla para limpiarla
99.
mov al,[si]
100.
mov ah,1bh
;Fondo azul, letras blancas
101.
mov es:[di],ax
102.
inc si
;Pasamos a apuntar a la siguiente letra
del saludo
103.
inc di
104.
inc di
105.
loop b_saludo
106.
107.
108.
mov ax,4C00h
;
109.
int 21h
;Terminar el programa
110.
111. START ENDP
112.
113. CODE ENDS
114.
END START
115.
116.
117.
118. ;----------------------------------------------------------------------------119. ;Definicion del segmento de datos
120. ;----------------------------------------------------------------------------121. DATOS SEGMENT
122.
mensaje
db "Ejercicios disponibles en:
www.victorsanchez2.net"
123.
pregunta_nombre db "Cual es tu nombre?: "
124.
nombre
db 64 DUP(0)
125. DATOS ENDS
126.
127. ;----------------------------------------------------------------------------128. ;Definicion del segmento de pila
129. ;----------------------------------------------------------------------------130. PILA SEGMENT STACK "STACK"
131.
db 40h DUP(0)
132. PILA ENDS
133.
134. ;----------------------------------------------------------------------------135. ;Definicion del segmento extra
183.
inc si
;Pasamos a apuntar a la siguiente letra
del saludo
184.
inc di
185.
inc di
186.
loop b_saludo
187.
188.
;Mensaje al usuario para que introduzca su nombre
189.
mov si,offset pregunta_nombre
190.
mov di,(80*12+10)*2
;Linea 12, columna 10
191.
mov cx,20
192.
193. b_pide_nombre:
;Bucle que se encargara de recorrer los
2000
194.
;caracteres de la pantalla para limpiarla
195.
mov al,[si]
196.
mov ah,1bh
;Fondo azul, letras blancas
197.
mov es:[di],ax
198.
inc si
;Pasamos a apuntar a la siguiente letra
del saludo
199.
inc di
200.
inc di
201.
loop b_pide_nombre
202.
203.
;Almacenamos el nombre
204.
mov ah,0Ah
205.
mov dx,offset nombre
206.
mov nombre[0],64
;Maximo numero de caracteres
207.
int 21h
208.
209.
mov bx,0
210.
211. muestra_nombre:
212.
mov dl,nombre[bx+2]
213.
mov ah,2
214.
int 21h
;Escribir un caracter del nombre
215.
inc bx
216.
cmp bl,nombre[1]
;Compara con el numero de caracteres
217.
jne muestra_nombre
218.
219.
mov ax,4C00h
;
220.
int 21h
;Terminar el programa
221.
222. START ENDP
223.
224. CODE ENDS
225.
END START
226.
227.
228.
229. ;----------------------------------------------------------------------------230. ;Definicion del segmento de datos
231. ;----------------------------------------------------------------------------232. DATOS SEGMENT
233.
mensaje
db "Ejercicios disponibles en:
www.victorsanchez2.net"
234.
pregunta_nombre db "Cual es tu nombre?: "
235.
nombre
db 256 DUP(0)
236. DATOS ENDS
237.
238. ;----------------------------------------------------------------------------239. ;Definicion del segmento de pila
240. ;----------------------------------------------------------------------------241. PILA SEGMENT STACK "STACK"
242.
db 40h DUP(0)
243. PILA ENDS
244.
245. ;----------------------------------------------------------------------------246. ;Definicion del segmento extra
247. ;----------------------------------------------------------------------------248. EXTRA SEGMENT
249.
RESULT DW 0,0
250. EXTRA ENDS
251.
252. ;----------------------------------------------------------------------------253. ;Definicion del segmento de codigo
254. ;----------------------------------------------------------------------------255. CODE SEGMENT
256.
assume CS:code,DS:datos,ES:extra,SS:pila
257.
258. ;----------------------------------------------------------------------------259. ;
Procedimiento inicial
260. ;----------------------------------------------------------------------------261. START PROC
262.
263.
call inicializa_seg
;Inicializa los registros de
segmento
264.
call limpia_pantalla
;Limpiamos la pantalla
265.
call muestra_mensaje
;Mensaje de informacion
266.
call pide_nombre
;Pide el nombre al usuario
267.
call muestra_nombre
;Muestra por pantalla el nombre
del usuario
268.
269.
mov ax,4C00h
;
270.
int 21h
;Terminar el programa
271.
272. START ENDP
273.
274.
275. ;----------------------------------------------------------------------------276. ; inicializa_seg
277. ;
278. ; in:
279. ; out:
Los registros de segmento quedan inicializados
327.
pop cx
;Importante sacarlas en orden contrario
al que las
328.
pop ax
;guardamos
329.
330.
ret
331.
332. limpia_pantalla endp
333.
334. ;----------------------------------------------------------------------------335. ; muestra_mensaje
336. ;
337. ; in:
338. ; out:
339. ; machaca: DI, SI
340. ; make:
Muestra un mensaje por pantalla indicando en que pagina
se pueden
341. ;
encontrar los ejercicios
342. ;
343. ;----------------------------------------------------------------------------344. muestra_mensaje proc near
345.
346.
push ax
347.
push cx
348.
push es
349.
350.
351.
mov si,offset mensaje
352.
mov di,(80*10+10)*2 ;Linea 10, columna 10
353.
mov cx,49
;Tamao del mensaje
354.
355. b_saludo:
;Bucle que se encargara de recorrer los
2000
356.
;caracteres de la pantalla para limpiarla
357.
mov al,[si]
358.
mov ah,1bh
;Fondo azul, letras blancas
359.
mov es:[di],ax
360.
inc si
;Pasamos a apuntar a la siguiente letra
del saludo
361.
inc di
362.
inc di
363.
loop b_saludo
364.
365.
pop es
366.
pop cx
367.
pop ax
368.
369.
ret
370.
371. muestra_mensaje endp
372.
373. ;----------------------------------------------------------------------------374. ; pide_nombre
375. ;
376. ; in:
377. ; out:
378. ; machaca: DI, SI, DX
379. ; make:
Pide el nombre al usuario para que lo introduzca por
pantalla
380. ;
381. ;----------------------------------------------------------------------------382. pide_nombre proc near
383.
384.
push ax
385.
push cx
386.
push es
387.
388.
389.
;Mensaje al usuario para que introduzca su nombre
390.
mov si,offset pregunta_nombre
391.
mov di,(80*12+10)*2
;Linea 12, columna 10
392.
mov cx,20
393.
394. b_pide_nombre:
;Bucle que se encargara de recorrer los
2000
395.
;caracteres de la pantalla para limpiarla
396.
mov al,[si]
397.
mov ah,1bh
;Fondo azul, letras blancas
398.
mov es:[di],ax
399.
inc si
;Pasamos a apuntar a la siguiente letra
del saludo
400.
inc di
401.
inc di
402.
loop b_pide_nombre
403.
404.
;Almacenamos el nombre
405.
mov ah,0Ah
406.
mov dx,offset nombre
407.
mov nombre[0],64
;Maximo numero de caracteres
408.
int 21h
409.
410.
pop es
411.
pop cx
412.
pop ax
413.
414.
ret
415.
416. pide_nombre endp
417.
418. ;----------------------------------------------------------------------------419. ; muestra_nombre
420. ;
421. ; in: nombre contiene el nombre de usuario que se ha introducido
422. ; out:
423. ; machaca: DI, SI
424. ; make:
Muestra el nombre al usuario por pantalla
425. ;
426. ;----------------------------------------------------------------------------427. muestra_nombre proc near
428.
429.
push ax
430.
push cx
431.
push es
432.
433.
mov ax,0B800h
434.
mov es,ax
435.
xor dx,dx
436.
mov si,offset nombre+2
437.
mov di,(80*12+31)*2
438.
439. mostrar_nombre:
440.
mov al,[si]
441.
mov ah,1bh
442.
mov es:[di],ax
443.
inc dx
444.
inc si
445.
inc di
446.
inc di
447.
cmp dl,nombre[1]
caracteres
448.
jne mostrar_nombre
449.
450.
pop es
451.
pop cx
452.
pop ax
453.
454.
ret
455.
456. muestra_nombre endp
457.
458.
459. CODE ENDS
460.
END START
461.
462.
463.
464. ;----------------------------------------------------------------------------465. ;Definicion del segmento de datos
466. ;----------------------------------------------------------------------------467. DATOS SEGMENT
468.
469.
dato
db 3 ;Numero del que calcularemos su factorial
470.
471. DATOS ENDS
472.
473. ;----------------------------------------------------------------------------474. ;Definicion del segmento de pila
475. ;----------------------------------------------------------------------------476. PILA SEGMENT STACK "STACK"
477.
db 40h dup(0)
478. PILA ENDS
479.
529.
ret
530.
531. inicializar endp
532.
533. ;----------------------------------------------------------------------------534. ; calcula_factorial
535. ;
536. ; in:
CL contiene el dato
537. ; out:
Devuelve en AX el resultado de calcular el factorial
538. ; machaca: AX, CX
539. ; make:
Inicializa los registros de segmento y el puntero de
pila
540. ;
541. ;----------------------------------------------------------------------------542. calcula_factorial proc near
543.
544.
mov ax,1
545.
xor ch,ch
546.
cmp cx,0
;Si el numero es 0
547.
je
fin
;terminamos
548.
549. factor:
550.
mul cx
551.
dec cx
552.
jne factor
553.
554. fin:
555.
ret
556.
557. calcula_factorial endp
558.
559. ;----------------------------------------------------------------------------560. ; muestra_nombre
561. ;
562. ; in: nombre contiene el nombre de usuario que se ha introducido
563. ; out:
564. ; machaca: DI, SI
565. ; make:
Muestra el valor del factorial por pantalla
566. ;
567. ;----------------------------------------------------------------------------568. muestra_factorial proc near
569.
570.
push ax
571.
push cx
572.
push es
573.
574.
mov ax,0B800h
575.
mov es,ax
;Apuntar a la memoria de video
576.
mov dl,factorial
577.
mov di,(80*12+31)*2
;Linea 12, columna 31
578.
add dl,30h
;Obtener el valor en ASCII ('0'=30h)
579.
mov dh,1bh
580.
mov es:[di],dx
581.
582.
pop es
583.
pop cx
584.
pop ax
585.
586.
ret
587.
588. muestra_factorial endp
589.
590. CODE ENDS
591.
END START
592.
2
1. Escribir un programa que escriba el mismo carcter en las 2000 posiciones de
la pantalla:
2.
3. pantalla EQU 0B800h
;Direccion fsica de comienzo de la
pantalla
4.
5. ;----------------------------------------------------------------------------6. ;Definicin del segmento de codigo
7. ;----------------------------------------------------------------------------8. CODE SEGMENT
9.
assume cs:code
10.
11. START PROC
12.
mov ax,pantalla
;Cargar la direccin de la
coordenada 0,0 de la
13.
mov ds,ax
;pantalla
14.
xor bx,bx
;Ponemos bx a 0
15.
16. pinta_caracter:
17.
mov ds:[bx],byte ptr "V"
;Escribir el carcter en
su coordenada
18.
inc bx
;En lugar de sumar 2, se
incrementa 2 veces porque
19.
;consume menos ciclos de
reloj del procesador
20.
inc bx
;Cada posicion de la
pantalla son 2 bytes,
21.
cmp bx,2000*2
;por eso bx va a llegar
hasta 4000
22.
jl
pinta_caracter
;Si bx<4000 volvemos a
pintar otro carcter
23.
24.
mov ax,4C00h
;
25.
int 21h
;Terminar el programa
26.
31. Hacer un programa que coja el carcter que se encuentre en la coordenada 0,0
de la pantalla en ese momento y lo copie por toda la pantalla. En los ltimos 4
caracteres mostrar la palabra ETSI:
32.
33. pantalla EQU 0B800h
34.
35. ;----------------------------------------------------------------------------36. ;Definicin del segmento de codigo
37. ;----------------------------------------------------------------------------38. CODE SEGMENT
39.
assume cs:code
40.
41. START PROC
42.
mov ax,pantalla
;Cargar la direccin de la
coordenada 0,0 de la
43.
mov ds,ax
;pantalla
44.
xor bx,bx
45.
mov dx,ds:[bx]
;Obtener el carcter de la
coordenada 0,0
46.
47. pinta_caracter:
48.
inc bx
49.
inc bx
50.
mov ds:[bx],dx
;Copiar el carcter
obtenido por toda la pantalla
51.
cmp bx,1995*2
;Dejamos los ultimos 4
caracteres sin rellenar
52.
jl
pinta_caracter
53.
54.
mov ds:[1996*2],byte ptr "E"
;En los ultimos 4
caracteres escribimos
55.
mov ds:[1997*2],byte ptr "T"
;nuestro mensaje
56.
mov ds:[1998*2],byte ptr "S"
;
57.
mov ds:[1999*2],byte ptr "I"
;
58.
59.
mov ax,4C00h
;
60.
int 21h
;Terminar el programa
61.
62. START ENDP
63.
64. CODE ENDS
65.
END START
principio puede parecernos un poco raro y no saber muy bien a que equivale,
pero poco a poco iremos aprendiendo a pensar en hexadecimal y binario :D.
Antes de nada les voy a mostrar los archivos .bat que he venido utilizando
durante mi aprendizaje del ensamblador: - Para debuggear un programa puede
utilizarse nicamente el programa deb.bat:
67.
68. :---------------------------------------------------------------------69. :
70. : Fichero: deb.bat
71. :
72. : Descripcion:
73. :
Ensamblar modulo fuente principal de un programa, crear modulo
74. :
objeto y debuggearlo.
75. :
76. :---------------------------------------------------------------------77. :
78. echo off
79.
if z%1 == z goto error
80.
goto check
81. :error
82.
echo *** error: falta nombre del modulo fuente ***
83.
goto fin
84. :check
85.
if exist %1.asm goto ensam
86.
echo *** error: fichero %1.asm no existe ***
87.
goto fin
88. :ensam
89.
tasm /zi %1;
90.
if exist %1.obj goto mensa
91.
echo *** error en programa fuente ***
92.
goto fin
93. :mensa
94.
tlink /v %1
95.
echo ... creado fichero %1.obj
96.
97.
td %1
98.
99. :fin
;----------------------------------------------------------------------------CODE SEGMENT
assume CS:code
START:
xor
mov
ax,ax
cx,1
;
;Inicializar
add
inc
cmp
jne
ax,cx
cx
cx,11
suma
;
;
;
;Sumar 1+...+10=37h
mov
int
ax,4C00h
21h
;
;Terminar el programa
suma:
CODE ENDS
END START
Si quisiesemos poner los atributos de otra forma slo hay que cambiar una lnea.
Podramos ponerla de la siguiente manera, por ejemplo:
mov ax,1100001000000000b mov ax,0C200h
29. mostrar_ascii:
30.
mov [bx],al
pantalla
31.
inc bx
32.
inc bx
33.
inc al
34.
loop mostrar_ascii
35.
36.
mov ax,4C00h
37.
int 21h
38.
39. CODE ENDS
40.
END START
;Escribirlo en la coordenada de la
;
;Pasar a la siguiente coordenada
;Pasar al siguiente caracter
;
;Terminar el programa
77.
78.
79.
80.
81.
82.
add
mov
inc
loop
bx,ax
word ptr [bx],7056h
dh
BucleColumnas
pop
cx
lineas
83.
inc dl
84.
loop BucleLineas
85.
86.
mov ax,4C00h
87.
int 21h
88.
89. CODE ENDS
90.
END START
124.
jmp continuar
CONTINUAR
125.
126. INICIO:
127.
lea dx,continuando
128.
mov ah,9
129.
int 21h
programa
130.
jmp continuar
desea continuar
131.
132. ERROR:
133.
lea dx,LetraErronea
134.
mov ah,9
introducida
135.
int 21h
136.
137. CONTINUAR:
138.
lea dx,DeseaContinuar
139.
mov ah,9
140.
int 21h
desea continuar
141.
142.
mov ah,1
143.
int 21h
144.
145.
cmp al, 'S'
146.
je
inicio
147.
cmp al, 's'
148.
je
inicio
149.
150.
cmp al, 'N'
151.
je
salir
152.
cmp al, 'n'
153.
je
salir
154.
155.
jmp error
'N' ni 'n'
156.
error. Saltamos
157.
158.
159. salir:
160.
mov ax, 4C00h
161.
int 21h
162.
163. CODE ENDS
164.
END START
;Saltamos a la etiqueta
;
;
;Mensaje de que seguimos en el
;Salto para preguntar si se
;
;Mensaje de que la letra
;no es correcta
;
;
;Mostrar pregunta para ver si
;Esperar a que se pulse una tecla
;y mostrarla por pantalla
;
;
;
;Desea continuar
;
;
;
;No desea continuar, terminamos
;La tecla pulsada no es 'S', 's',
;Se va a mostrar un mensaje de
;a la etiqueta ERROR
165.
Realizar un programa que cambie todas las letras de la pantalla a
minusculas:
166.
167. PANTALLA equ 0B800h
168.
169. ;----------------------------------------------------------------------------170. ;Definicion del segmento de pila
Vamos a ver diferentes ejemplos de instrucciones para entenderlas un poco mejor. Ser
bueno tener un libro al lado para saber qu hace cada instruccin.
1. Ejemplo de las instrucciones: CBW y CWD
2.
3. ;----------------------------------------------------------------------------4. ;Definicion del segmento de pila
5. ;----------------------------------------------------------------------------6. PILA SEGMENT STACK "STACK"
7.
db
40h dup(0)
8. PILA ENDS
9.
10. ;----------------------------------------------------------------------------11. ;Definicion del segmento de codigo
12. ;----------------------------------------------------------------------------13. CODE SEGMENT
14.
assume CS:code, SS:pila
15.
16. START:
17.
mov ah,3
;No sirve para nada, solo para ver que al
convertir
18.
;en palabra o doble palabra se machacan
los registros
19.
mov al,5
20.
cbw
;Convertir un byte en palabra
21.
cwd
;Convertir una palabra en doble palabra
22.
23.
neg al
;al pasa a ser un numero negativo
(complemento a 2)
24.
mov ah,4
;basura, igual que en caso anterior
25.
cbw
;Convertir un byte en palabra
26.
cwd
;Convertir una palabra en doble palabra
27.
28.
mov ax,4C00h
29.
int 21h
30.
31. CODE ENDS
32.
END START
91.
aaa
92.
mov ax,11110001b
93.
add al,1
94.
aaa
95.
mov ax,8
96.
add al,7
97.
aaa
98.
add al,4
99.
aaa
100.
add al,9
101.
aaa
102.
103.
104.
mov ax,4C00h
105.
int 21h
106.
107. START ENDP
108.
109. CODE ENDS
110.
END START
;AX=0100h
;
;
;AX=0002h
;
;
;AX=0105h
;
;AX=0109h
;
;AX=0208h
;
;Terminar el programa
111.
Ejemplo de la instruccion: AAA (ajuste ASCII en suma). Del examen de
ETCII del ao 2001:
112.
113. ;----------------------------------------------------------------------------114. ; Programa que prueba la instruccion: AAA
115. ;
116. ; ah <- cociente (al/0Ah)
117. ; al <- resto
(al/0Ah)
118. ;
119. ;----------------------------------------------------------------------------120. ; Ejercicio: examen ETCII - 7/11/01
121.
122. ;----------------------------------------------------------------------------123. ;Definicion del segmento de codigo
124. ;----------------------------------------------------------------------------125.
126. CODE SEGMENT
127.
assume CS:code
128.
129. start:
130.
131.
mov ax,16h
132.
mov bx,191h
133.
add ax,bx
134.
aaa
;AX=0107h
135.
add ax,7h
136.
aaa
;AX=0204h
137.
138.
mov ax,4c00h
139.
int 21h
140.
141. CODE ENDS
142.
143.
END START
144.
145. ;----------------------------------------------------------------------------146. ; Programa que prueba las instrucciones: AAA y DAA
147. ;----------------------------------------------------------------------------148. ;----------------------------------------------------------------------------149. ;Definicion del segmento de pila
150. ;----------------------------------------------------------------------------151. PILA SEGMENT STACK "STACK"
152.
db
40h dup(0)
153. PILA ENDS
154.
155. ;----------------------------------------------------------------------------156. ;Definicion del segmento de codigo
157. ;----------------------------------------------------------------------------158. CODE SEGMENT
159.
assume CS:code, SS:pila
160.
161. START:
162.
mov al,5
163.
add al,7
164.
aaa
;Ajuste BCD no empaquetado
165.
166.
xor ax,ax
167.
168.
mov al,5
169.
add al,7
170.
daa
;Ajuste BCD empaquetado
171.
172.
mov ax,4C00h
173.
int 21h
174.
175. CODE ENDS
176.
END START
177.
178.
179. ;----------------------------------------------------------------------------180. ;Definicion del segmento de pila
181. ;----------------------------------------------------------------------------182. PILA SEGMENT STACK "STACK"
183.
db
40h dup(0)
184. PILA ENDS
185.
186. ;----------------------------------------------------------------------------187. ;Definicion del segmento de codigo
202.
Otra forma de convertir a complemento a 2 mediante las instrucciones
NOT e INC:
203.
204. ;----------------------------------------------------------------------------205. ;Definicion del segmento de pila
206. ;----------------------------------------------------------------------------207. PILA SEGMENT STACK "STACK"
208.
db
40h dup(0)
209. PILA ENDS
210.
211. ;----------------------------------------------------------------------------212. ;Definicion del segmento de codigo
213. ;----------------------------------------------------------------------------214. CODE SEGMENT
215.
assume CS:code, SS:pila
216.
217. START:
218.
219.
mov al,8
220.
not al
;
221.
inc al
;Convertir a su complemento a 2
222.
223.
mov ax,4C00h
224.
int 21h
225.
226. CODE ENDS
227.
END START
42.
43.
44.
45.
46.
47.
48.
49.
mov
ds,ax
xor
mov
mov
lea
si,si
ax,datos
es,ax
di,pantalla_bak
;Apuntar a la variable
mov
cx,80*25*2
copiar
50.
cld
;Direccion para incrementar DI y SI
51.
52. backup:
53.
movsb
;Mover el contenido de la direccion de
memoria apuntada
54.
;por SI a la apuntada por DI, en este
caso la variable
55.
;pantalla_bak
56.
loop backup
57.
58.
mov cx,80*25
;
59.
xor bx,bx
;
60.
mov al,'*'
;
61.
mov ah,70h
;Llenar la pantalla de '*'
62.
63. llena:
64.
mov [bx],ax
65.
inc bx
66.
inc bx
67.
loop llena
68.
69.
push ds
;
70.
push es
;
71.
pop ds
;
72.
pop es
;Intercambiar DS y ES
73.
74.
xor di,di
75.
lea si,pantalla_bak
76.
77.
xor ah,ah
;
78.
int 16h
;Esperar a que se pulse una tecla
79.
80.
mov cx,4000
;Los 4000 bytes de la pantalla
81.
82. restaura:
;
83.
movsb
;
84.
loop restaura
;Volver a dejar la pantalla como al
principio
85.
86.
mov ax,4C00h
87.
int 21h
88.
89. CODE ENDS
90.
END START
138.
mov ax,0B800h
;En esta direccion comienza la memoria de
video
139.
mov es,ax
;Lo cargamos en el segmento extra
140.
xor di,di
;Ponemos DI=0
141.
mov cx,80*25
;80 lineas x 25 columnas
142.
xor al,al
;0=" "
Rellenar la pantalla con blancos
143.
mov ah,0Fh
;Fondo negro, letras blancas
144.
rep stosw
145.
146.
lea si,mensaje
;Cargar el mensaje donde buscaremos
147.
mov al,CARACTER
;Cargar el caracter a buscar
148.
mov cx,22
;Longitud maxima para buscar (longitud de
'mensaje')
149.
150.
call busca_fin
;Buscar la posicion en que se encuentra
el CARACTER
151.
152.
mov ax,0B800h
;
153.
mov es,ax
;Colocarnos al inicio de la memoria de
video
154.
add cl,30h
;Preparar CL para mostrar el caracter por
pantalla
155.
push cx
;Guardarlo para recuperarlo despues
156.
157.
mov di,(80*2)*2
;Colocarnos en la segunda fila
158.
lea si,mensaje
;Colocar el offset de mensaje en si
159.
mov cx,22
;Total de caracteres de mensaje
160.
call pinta
;Mostrarlo por pantalla
161.
162.
mov di,(80*4)*2
;Nos colocamos en la cuarta fila
163.
lea si,msg_caracter ;Cargar el offset
164.
mov cx,13
;Total de caracteres de mensaje
165.
call pinta
;Mostrarlo por pantalla
166.
167.
mov di,(80*4+13)*2
;Colocarnos al final del
msg_caracter
168.
mov byte ptr es:[di],CARACTER
;Mostrar el CARACTER por
pantalla
169.
170.
mov di,(80*5)*2
;Ponernos en la quinta fila
171.
lea si,msg_posicion
;Cargar el offset
172.
mov cx,29
;Total de caracteres de mensaje
173.
call pinta
;Mostrarlo por pantalla
174.
175.
mov di,(80*5+29)*2 ;Colocarnos al final del msg_posicion
176.
pop cx
;Recuperar la posicion en que se
encontraba CARACTER
177.
mov es:[di],cl
178.
179.
mov ax,4C00h
;
180.
int 21h
;Terminar el programa
181.
182. START ENDP
183.
184. ;----------------------------------------------------------------------------185. ; busca_fin
186. ;
187. ; in: AL contiene el caracter que debemos buscar
188. ;
SI contiene la cadena que debemos buscar
189. ; out: En CX se guarda la posicion donde se ha encontrado el
caracter
190. ; machaca: CX
191. ; make: Devuelve en CX la primera posicion donde se ha encontrado
el caracter
192. ;
dado en AL
193. ;----------------------------------------------------------------------------194.
195. busca_fin proc near
196.
197.
push di
198.
push dx
199.
push es
200.
push si
201.
push ax
202.
203.
mov ax,ds
;
204.
mov es,ax
;
205.
mov di,si
;Copiar DS:SI en ES:DI
206.
207.
mov dx,cx
;Copiar el limite en otro registro
208.
cld
;Direccion incremental
209.
pop ax
;Recuperar el caracter que nos han pedido
210.
push ax
;Guardarlo en la pila para no perderlo
211. repnz
scasb
;Buscar el caracter pedido
212.
sub dx,cx
;Calcular la longitud
213.
mov cx,dx
;Guardar la longitud en CX
214.
215.
pop ax
216.
pop si
217.
pop es
218.
pop dx
219.
pop di
220.
ret
221.
222. busca_fin endp
223.
224. ;----------------------------------------------------------------------------225. ; pinta
226. ;
227. ; in: SI contiene el offset del mensaje a mostrar
228. ;
DI contiene la direccion donde se ira mostrando el mensaje
229. ;
CX contiene el numero de iteraciones a realizar
230. ; out:
231. ; machaca: CX
232. ; make: Muestra por pantalla el mensaje dado
233. ;----------------------------------------------------------------------------234. pinta proc near
235.
236.
push ax
237.
push si
238.
push di
239.
240.
mov ah,0Fh
241.
242. pintar:
243.
mov al,[si]
244.
mov es:[di],ax
245.
inc si
246.
inc di
247.
inc di
248.
loop pintar
249.
250.
pop di
251.
pop si
252.
pop ax
253.
ret
254.
255. pinta endp
256.
257. CODE ENDS
258.
END START
259.
Hacer un programa que muestre la sucesin de cdigos ASCII en la
esquina superior derecha de la pantalla, intercambiando los caracteres cada
medio segundo. Este programa ya es algo ms complejo que los anteriores ya
que empezamos a trabajar con programas residentes y el RTC. Os recomiendo
que aprendais bien las caractersticas de los programas residentes y
programacin del RTC antes de intentar comprender este ejercicio por
completo. Este tipo de ejercicios van un nivel ms all, y si de verdad no
comprendeis bien este tipo de ejercicios es mejor que os cojais libros, apuntes o
lo que sea y lo domineis con soltura.
Un comando que os puede servir de ayuda es:
MEM /C
Con este podemos saber los programas que hay residentes en nuestra memoria.
Al escribir esto veremos como aparece el programa de nombre ASCII, que
ocupa 0,4K.
Para ensamblar y ejecutar este programa, al ser .COM, hay que hacerlo con
unas banderas distintas:
C:\>tasm archivo
C:\>tlink /t archivo
C:\>archivo
;----------------------------------------------------------------------------;Programa que muestra la sucesion de codigos ASCII en la esquina
superior
;derecha de la pantalla, intercambiando los caracteres cada medio
segundo
;----------------------------------------------------------------------------PANTALLA
equ 0b800h
;----------------------------------------------------------------------------;Definicion del segmento de codigo
;----------------------------------------------------------------------------CODE SEGMENT
assume CS:code
org 100h
;Dejar las 100h primeras posiciones para
el PSP
START:
jmp instalar
;
;
;Guardamos los registros en la pila
mov
out
in
al,0Ch
70h,al
al,71h
;
;
;Leer el RTC
mov
mov
mov
mov
inc
mov
ax,PANTALLA
es,ax
di,79*2
ax,es:[di]
al
es:[di],ax
cli
mov
out
out
sti
al,20h
20h,al
0A0h,al
pop
pop
pop
di
es
ax
iret
letras endp
instalar proc far
cli
;Inhabilitar las interrupciones
xor ax,ax
;
mov es,ax
;Poner a 0 ES
mov es:[70h*4],offset letras
;Guardar el offset
mov es:[70h*4+2],cs
;y el segmento de la rutina
in
and
al,0A1h
al,11111110b
out
0A1h,al
;Activamos IR0
in
and
out
al,21h
al,11111011b
21h,al
al,0Ah
70h,al
al,2Fh
71h,al
al,0Bh
70h,al
al,71h
al,01000000b
71h,al
mov
out
mov
segundo
out
mov
out
in
or
out
sti
;
;Activamos las interrupciones periodicas
;Habilitar las interrupciones
lea dx,instalar
int 27h
instalar endp
CODE ENDS
END START
260.
Algo muy importante es el programa que sirve para desinstalar y
restaurar todo lo que hizo el programa anterior. Si no lo hacemos seguir
mostrndose la sucesin de los caracteres ASCII mientras mantengamos
encendido el ordenador. Despus de ensamblar y ejecutar el programa con:
C:\>tasm /zi archivo
C:\>tlink /v archivo
C:\>archivo
Este programa no es .COM, por lo tanto usamos las banderas habituales.
Despus de ejecutarlo, si volvemos a escribir "MEM /C" veremos que nuestro
programa ha desaparecido, ya no se encuentra residente en memoria.
;----------------------------------------------------------------------------;Desactiva las interrupciones periodicas del RTC y elimina el
programa anterior
;de la memoria.
;----------------------------------------------------------------------------;----------------------------------------------------------------------------;Definicion del segmento de pila
ax,4C00h
21h
;
;Terminar el programa
START ENDP
;----------------------------------------------------------------------------; desinstalar
;
; in:
; out:
; machaca:
; make: Desinstala las interrupciones periodicas (PIE), desconecta
la
;
interrupcion del RTC al PIC esclavo, restaura los vectores
de
;
interrupcion y desinstala el programa residente
;
;----------------------------------------------------------------------------desinstalar PROC
push ax
push es
push ds
cli
mov al,0Bh
out 70h,al
and al,10111111b
out 71h,al
periodicas (PIE)
in
al,0A1h
OR
al,00000001B
out 0A1h,al
PIC esclavo
xor
mov
mov
mov
xor
mov
mov
mov
mov
mov
int
mov
mov
mov
int
FIN:
pop
pop
ds
es
ax
ret
desinstalar ENDP
CODE ENDS
END START
6 Estos ejercicios van a ser algo ms complejos y son del nivel que se va a exigir a
aquellos que estn cursando la asignatura de ETCII en la Universidad Autnoma de
Madrid.
1. Hallar cual es el valor de AX tras la segunda instruccin AAA:
2.
3. ; Ejercicio: examen ETCII - 7/11/01
4.
104.
105.
7 Las soluciones y archivos fuente de todos los ejercicios podis obtenerlos escribindome
un e-mail para pedrmelos.
1. Hallar el valor de AX tras la instruccin "mov ax,[bp+1]":
2.
3. ;----------------------------------------------------------------------------4. ;Definicion del segmento de pila
5. ;----------------------------------------------------------------------------6. PILA SEGMENT STACK "STACK"
7.
db 40h DUP(0)
8. PILA ENDS
9.
10. ;----------------------------------------------------------------------------11. ;Definicion del segmento de codigo
12. ;----------------------------------------------------------------------------13. CODE SEGMENT
14.
assume cs:code,ss:pila
15.
16. START PROC
17.
;Inicializamos los registros de segmento
18.
mov ax,pila
19.
mov ss,ax
20.
21.
mov cx,37FFh
22.
xor bx,bx
23.
push cx
24.
push bx
25.
mov bp,sp
26.
mov ax,[bp+1]
27.
28.
mov ax,4C00h
;
29.
int 21h
;Terminar el programa
30.
31. START ENDP
32.
33. CODE ENDS
34.
END START
115.
116.
117. ;----------------------------------------------------------------------------118. ;Definicion del segmento de datos
119. ;----------------------------------------------------------------------------120. DATOS SEGMENT
121.
texto
db "Cadena_de_texto"
122. DATOS ENDS
123.
124. ;----------------------------------------------------------------------------125. ;Definicion del segmento de pila
126. ;----------------------------------------------------------------------------127. PILA SEGMENT STACK "STACK"
128.
db 40h DUP(0)
129. PILA ENDS
130.
131. ;----------------------------------------------------------------------------132. ;Definicion del segmento de codigo
133. ;----------------------------------------------------------------------------134. CODE SEGMENT
135.
assume cs:code,ds:datos,ss:pila
136.
137. START PROC
138.
;Inicializamos los registros de segmento
139.
mov ax,datos
140.
mov ds,ax
141.
mov ax,pila
142.
mov ss,ax
143.
144.
mov si,offset texto
145.
cld
146.
mov cx,5
147.
rep lodsw
148.
149.
mov ax,4C00h
;
150.
int 21h
;Terminar el programa
151.
152. START ENDP
153.
154. CODE ENDS
155.
END START
156.
157.
158. ;----------------------------------------------------------------------------159. ;Definicion del segmento de datos
160. ;----------------------------------------------------------------------------161. DATOS SEGMENT
162.
texto
db "Esto_es_una_cadena_de_texto",0
198.
Y otro ms. Las instrucciones de cadena son bastante potentes y como
podreis ver es mejor saber manejarlas con soltura:
199.
200. ;----------------------------------------------------------------------------201. ;Definicion del segmento de datos
202. ;----------------------------------------------------------------------------203. DATOS SEGMENT
204.
texto
db "Cadena_de_texto"
205. DATOS ENDS
206.
207. ;----------------------------------------------------------------------------208. ;Definicion del segmento de pila
209. ;-----------------------------------------------------------------------------
240.
241.
242. ;----------------------------------------------------------------------------243. ;Definicion del segmento de pila
244. ;----------------------------------------------------------------------------245. PILA SEGMENT STACK "STACK"
246.
db 40h DUP(0)
247. PILA ENDS
248.
249. ;----------------------------------------------------------------------------250. ;Definicion del segmento de codigo
251. ;----------------------------------------------------------------------------252. CODE SEGMENT
253.
assume cs:code,ss:pila
254.
255. START PROC
256.
;Inicializamos los registros de segmento
257.
mov ax,pila
258.
mov ss,ax
259.
260.
mov bx,10h
261.
xor ax,ax
262.
mov cx,0FFFFh
263. L1:
264.
add ax,bx
265.
loop L1
266.
267.
mov ax,4C00h
268.
int 21h
269.
270. START ENDP
271.
272. CODE ENDS
273.
END START
;
;Terminar el programa
8
1. El siguiente programa le pide al usuario la confirmacin de si desea continuar
y dependiendo de la respuesta se har una cosa u otra:
2.
3. ;----------------------------------------------------------------------------4. ;Programa que le pregunta al usuario si desea continuar o no hasta
que se pulse
5. ;la tecla 'N' o 'n'
6. ;----------------------------------------------------------------------------7.
8. cr equ 13
;retorno de carro
9. lf equ 10
;alimentacion de linea
10.
11. ;----------------------------------------------------------------------------12. ;Definicion del segmento de datos
13. ;----------------------------------------------------------------------------14. DATOS SEGMENT
15.
DeseaContinuar db cr,lf,'Desea continuar? S/N: '
16.
db'$'
17.
continuando db '
Continuando...',cr,lf
18.
db'$'
19.
LetraErronea db '
La tecla pulsada es incorrecta.',cr,lf
20.
db'$'
21. DATOS ENDS
22.
23. ;----------------------------------------------------------------------------24. ;Definicion del segmento de pila
25. ;----------------------------------------------------------------------------26. PILA SEGMENT STACK "STACK"
27.
db 40h dup(?)
28. PILA ENDS
29.
119.
Otro programa .COM (no os olvideis de compilar con las banderas
antes mencionadas). En este caso se trata de mostrar las letras V y S con un
intervalo de medio segundo, siendo una letra roja y la otra azul:
120.
121.
122.
123.
124.
125.
PANTALLA
ROJO
LETRA_ROJA
LETRA_AZUL
AZUL
equ
equ
equ
equ
equ
0b800h
4
'V'
'S'
1
126.
127. ;----------------------------------------------------------------------------128. ;Definicion del segmento de codigo
129. ;----------------------------------------------------------------------------130. CODE SEGMENT
131.
assume CS:code
132.
org 100h
;Dejar las 100h primeras posiciones para
el PSP
133.
134. START:
135.
jmp instalar
;Bifurcar a la rutina de instalacion
136.
137.
138. ;----------------------------------------------------------------------------139. ; letras
140. ;
141. ; in:
142. ; out:
143. ; machaca:
144. ; make: Hace que se intercambien las letras V y S cada medio
segundo en
145. ;
colores diferentes.
146. ;
147. ;----------------------------------------------------------------------------148. letras proc far
149.
150.
push ax
;
151.
push es
;
152.
push di
;Guardamos los registros en la pila
153.
154.
cli
;Inhabilitar las interrupciones
155.
156.
mov al,0Ch
;
157.
out 70h,al
;
158.
in
al,71h
;Leer el RTC
159.
160.
mov ax,pantalla
161.
mov es,ax
162.
mov di,79*2
;Esquina superior derecha
163.
mov ax,es:[di]
;Guardamos en AX lo que hay en la esquina
164.
165.
cmp ah,AZUL
;Si era azul ahora debemos mostrar
166.
je
muestra_v_rojo ;la 'V' de color rojo
167.
168.
mov ah,AZUL
169.
mov al,LETRA_AZUL
170.
mov es:[di],ax
;Guardar en ES:[DI] que hemos puesto la
letra
171.
;de color azul
172.
jmp fin
;Terminar el procedimiento
173.
174. muestra_v_rojo:
175.
mov ah,ROJO
176.
mov al,LETRA_ROJA
177.
mov es:[di],ax
;Guardar en ES:[DI] que hemos puesto la
letra
178.
;de color rojo
179.
180. fin:
181.
mov al,20h
;
182.
out 20h,al
;
183.
out 0A0h,al
;EOI al maestro y al esclavo
184.
185.
sti
;Habilitar las interrupciones
186.
187.
pop di
;
188.
pop es
;
189.
pop ax
;Recuperar los registros
190.
191.
iret
192. letras endp
193.
194.
195. ;----------------------------------------------------------------------------196. ; instalar
197. ;
198. ; in:
199. ; out:
200. ; machaca: ax, dx, es
201. ; make: Instala el programa dejandolo residente
202. ;
203. ;----------------------------------------------------------------------------204. instalar proc
205.
206.
cli
;Inhabilitar las interrupciones
207.
208.
xor ax,ax
;
209.
mov es,ax
;Poner a 0 ES
210.
mov es:[70h*4],offset letras
;Guardar el offset
211.
mov es:[70h*4+2],cs
;y el segmento de la rutina
212.
213.
in
al,0A1h
;Leer el PIC esclavo
214.
and al,11111110b
;
215.
out 0A1h,al
;Activamos IR0
216.
217.
in
al,21h
;Leer el PIC maestro
218.
and al,11111011b
;
219.
out 21h,al
;Activado
220.
221.
mov al,0Ah
;Vamos a escribir en el registro A del
RTC
222.
out 70h,al
;
223.
mov al,2Fh
;Los simbolos se intercambian cada medio
segundo
224.
out 71h,al
;Lo indicamos en el registro A del RTC
225.
226.
mov al,0Bh
;Vamos a escribir en el registro B del
RTC
227.
out 70h,al
228.
in
al,71h
229.
or
al,01000000b
230.
out 71h,al
231.
232.
sti
233.
234.
lea dx,instalar
235.
int 27h
236.
237. instalar endp
238.
239. CODE ENDS
240.
END START
;
;
;
;Activamos las interrupciones periodicas
;Habilitar las interrupciones
;
;Dejar residente
241.
El siguiente ejercicio de examen nos pide conocer la instruccin scasb.
Hallar cul es el valor de AX tras la instruccin NOP:
242.
243. ;----------------------------------------------------------------------------244. ;Definicion del segmento de datos
245. ;----------------------------------------------------------------------------246. DATOS SEGMENT
247.
Cadena1
db 50 dup(0)
248.
Cadena2
db 50 dup(?)
249. DATOS ENDS
250.
251. ;----------------------------------------------------------------------------252. ;Definicion del segmento de pila
253. ;----------------------------------------------------------------------------254. PILA SEGMENT STACK "STACK"
255.
db 40h DUP(0)
256. PILA ENDS
257.
258. ;----------------------------------------------------------------------------259. ;Definicion del segmento de codigo
260. ;----------------------------------------------------------------------------261. CODE SEGMENT
262.
assume cs:code,ds:datos,ss:pila
263.
264. START PROC
265.
;Inicializamos los registros de segmento
266.
mov ax,datos
267.
mov ds,ax
268.
mov ax,pila
269.
mov ss,ax
270.
271.
xor ax,ax
272.
mov cx,10h
273.
lea si,Cadena1
274.
lea di,Cadena2
275. otro:
276.
push ds
277.
inc ax
278.
pop es
279.
scasb
280.
loop otro
281.
nop
282.
283.
mov ax,4C00h
284.
int 21h
285.
286. START ENDP
287.
288. CODE ENDS
289.
END START
290.
Otro ejercicio como el anterior, pero usando la instruccin repne.
Recordar que la instruccin LOOP primero decrementa y despues compara
CX con 0, as que cuidado con este ejercicio:
291.
292. ;----------------------------------------------------------------------------293. ;Definicion del segmento de datos
294. ;----------------------------------------------------------------------------295. DATOS SEGMENT
296.
Cadena1
db 50 dup(0)
297.
Cadena2
db 50 dup(?)
298. DATOS ENDS
299.
300. ;----------------------------------------------------------------------------301. ;Definicion del segmento de pila
302. ;----------------------------------------------------------------------------303. PILA SEGMENT STACK "STACK"
304.
db 40h DUP(0)
305. PILA ENDS
306.
307. ;----------------------------------------------------------------------------308. ;Definicion del segmento de codigo
309. ;----------------------------------------------------------------------------310. CODE SEGMENT
311.
assume cs:code,ds:datos,ss:pila
312.
313. START PROC
314.
;Inicializamos los registros de segmento
315.
mov ax,datos
316.
mov ds,ax
317.
mov ax,pila
318.
mov ss,ax
319.
320.
xor ax,ax
321.
mov cx,10h
322.
lea si,Cadena1
323.
lea di,Cadena2
324. otro:
325.
push ds
326.
inc ax
327.
pop es
328.
repne scasb
329.
loop otro
330.
nop
331.
332.
mov ax,4C00h
333.
int 21h
334.
335. START ENDP
336.
337. CODE ENDS
338.
END START
;
;Terminar el programa
339.
Hallar cual es el contenido de las posiciones de memoria: 1000, 1001,
1002 y 1003 tras la ejecucion del bucle:
340.
341. ;----------------------------------------------------------------------------342. ; Ejercicio 1: examen ETCII - 12/02/96
343. ;----------------------------------------------------------------------------344.
345. ;----------------------------------------------------------------------------346. ;Definicion del segmento de codigo
347. ;----------------------------------------------------------------------------348. CODE SEGMENT
349.
assume CS:code
350.
351. START:
352.
353.
;Inicializar
354.
mov byte ptr ds:[1000h],0
355.
mov byte ptr ds:[1001h],0
356.
mov byte ptr ds:[1002h],0
357.
mov byte ptr ds:[1003h],0
358.
359.
mov si,1000h
360.
mov cx,4
361. l1:
362.
add [si],si
363.
inc si
364.
loop l1
365.
366.
mov ax,4C00h
367.
int 21h
368.
369. CODE ENDS
370.
END START
371.
372.
373. ;-----------------------------------------------------------------------------
9
1. Otro problema de examen. Hallar el valor de AX tras la instruccin mov
ax,word ptr ds:[3]
2.
3. ;----------------------------------------------------------------------------4. ;Definicion del segmento de datos
5. ;----------------------------------------------------------------------------6. DATOS SEGMENT
7.
dw
3Ah,7Bh,9Ch
8.
db
34h,76h,65h
9.
org 1
10.
db
67h,31h,56h,"SE ACABO"
11. DATOS ENDS
12.
13. ;----------------------------------------------------------------------------14. ;Definicion del segmento de pila
15. ;----------------------------------------------------------------------------16. PILA SEGMENT STACK "STACK"
17.
db 40h DUP(0)
116.
dec sp
117.
pop ax
118.
pop ax
119.
nop
120.
121.
mov ax,4C00h
122.
int 21h
123.
124. START ENDP
125.
126. CODE ENDS
127.
END START
;
;Terminar el programa
128.
Muy importantes tambin son los ejercicios de pila. Hallar el valor de
AX tras la instruccin NOP:
129.
130. ;----------------------------------------------------------------------------131. ;Definicion del segmento de pila
132. ;----------------------------------------------------------------------------133. PILA SEGMENT STACK "STACK"
134.
db 40h DUP(0)
135. PILA ENDS
136.
137. ;----------------------------------------------------------------------------138. ;Definicion del segmento de codigo
139. ;----------------------------------------------------------------------------140. CODE SEGMENT
141.
assume cs:code,ss:pila
142.
143. START PROC
144.
;Inicializamos los registros de segmento
145.
mov ax,pila
146.
mov ss,ax
147.
148.
mov al,5
149.
mov bx,0FA45h
150.
push bx
151.
push ax
152.
mov bp,sp
153.
mov al,[bp+3]
154.
nop
155.
156.
mov ax,4C00h
;
157.
int 21h
;Terminar el programa
158.
159. START ENDP
160.
161. CODE ENDS
162.
END START
163.
Estos ejercicios de pilas suelen tener truco la mayora de las veces ;)
Hallar el valor de AX tras el ltimo POP:
164.
10
1. Hallar el valor de AX tras la instruccin div bl:
2.
3. ;----------------------------------------------------------------------------4. ;Definicion del segmento de codigo
5. ;----------------------------------------------------------------------------6. CODE SEGMENT
7.
assume cs:code
8.
9. START PROC
10.
11.
mov ah,1
12.
mov al,0D7h
13.
xor bx,bx
14.
stc
15.
rcr bx,1
16.
rcr bx,1
17.
div bl
18.
19.
mov ax,4C00h
20.
int 21h
21.
22. START ENDP
23.
24. CODE ENDS
25.
END START
;
;Terminar el programa
26. De nuevo un ejercicio sencillito para dejar a un lado los exmenes (por el
momento) y relajarnos un poco y ver otra forma de inicializar variables. Este
programa muestra dos lneas, una llena de '5' y otra de '@':
27.
28. ;----------------------------------------------------------------------------29. ;Definicion del segmento de datos
30. ;----------------------------------------------------------------------------31. DATOS SEGMENT
32.
Cadena1
db 80 dup("5"),"$"
33.
Cadena2
db 80 dup("@"),"$"
34. DATOS ENDS
35.
36. ;----------------------------------------------------------------------------37. ;Definicion del segmento de pila
38. ;----------------------------------------------------------------------------39. PILA SEGMENT STACK "STACK"
40.
db 40h DUP(0)
41. PILA ENDS
42.
43. ;----------------------------------------------------------------------------44. ;Definicion del segmento de codigo
45. ;----------------------------------------------------------------------------46. CODE SEGMENT
47.
assume cs:code,ds:datos,ss:pila
48.
49. START PROC
50.
;Inicializamos los registros de segmento
51.
mov ax,datos
52.
mov ds,ax
53.
mov ax,pila
54.
mov ss,ax
55.
56.
mov dx,offset Cadena1
57.
mov ah,9
58.
int 21h
59.
60.
mov dx,offset Cadena2
61.
mov ah,9
62.
int 21h
63.
64.
mov ax,4C00h
65.
int 21h
66.
67. START ENDP
68.
69. CODE ENDS
70.
END START
;
;Terminar el programa
112.
113. CODE ENDS
114.
END START
115.
Que es lo que encuentra el programa? "to" de la palabra "Esto" "ot"
de la palabra "otra"
116.
117. ;----------------------------------------------------------------------------;Definicion del segmento de datos
;----------------------------------------------------------------------------DATOS SEGMENT
cadena
db
"Esto es otra cadena"
DATOS ENDS
;----------------------------------------------------------------------------;Definicion del segmento de pila
;----------------------------------------------------------------------------PILA SEGMENT STACK "STACK"
db 40h DUP(0)
PILA ENDS
;----------------------------------------------------------------------------;Definicion del segmento de codigo
;----------------------------------------------------------------------------CODE SEGMENT
assume cs:code,ds:datos,ss:pila
START PROC
;Inicializamos los registros de segmento
mov ax,datos
mov ds,ax
cld
mov ax,datos
mov es,ax
mov cx,100h
mov ax,"ot"
lea di,cadena
repnz scasw
mov
int
ax,4C00h
21h
;
;Terminar el programa
START ENDP
CODE ENDS
END START
si,si
ax,[si]
ax,[si]
al,byte ptr tabla[si]
mov
int
ax,4C00h
21h
;
;Terminar el programa
START ENDP
CODE ENDS
END START
Instruccin JMP
Propsito: Salto incondicional
Sintaxis:
JMP destino
Esta instruccin se utiliza para desviar el flujo de un programa sin tomar en
cuenta las condiciones actuales de las banderas ni de los datos.
Instruccin JA (JNBE)
Propsito: Brinco condicional
Sintaxis:
JA Etiqueta
Despus de una comparacin este comando salta si est arriba o salta si no est
abajo o si no es igual.
Esto significa que el salto se realiza solo si la bandera CF esta desactivada o si la
bandera ZF esta desactivada (que alguna de las dos sea igual a cero).
Instruccin JAE (JNB)
Propsito: salto condicional
Sintaxis:
JAE etiqueta
Salta si est arriba o si es igual o salta si no est abajo.
El salto se efectua si CF esta desactivada.
Instruccin JB (JNAE)
Propsito: salto condicional
Sintaxis:
JB etiqueta
Salta si est abajo o salta si no est arriba o si no es igual.
Sintaxis:
JG etiqueta
Salta si es ms grande o salta si no es menor o igual.
El salto ocurre si ZF = 0 u OF = SF.
Instruccin JGE (JNL)
Propsito: salto condicional, se toma en cuenta el signo.
Sintaxis:
JGE etiqueta
Salta si es ms grande o igual o salta si no es menor que.
El salto se realiza si SF = OF
Instruccin JL (JNGE)
Propsito: salto condicional, se toma en cuenta el signo.
Sintaxis:
JL etiqueta
Salta si es menor que o salta si no es mayor o igual.
El salto se efecta si SF es diferente a OF.
Instruccin JLE (JNG)
Propsito: salto condicional, se toma en cuenta el signo.
Sintaxis:
JLE etiqueta
Salta si es menor o igual o salta si no es ms grande.
El salto se realiza si ZF = 1 o si SF es diferente a OF
Instruccin JC
Propsito: salto condicional, se toman en cuenta las banderas.
Sintaxis:
JC etiqueta
Salta si hay acarreo.
El salto se realiza si CF = 1
Instruccin JNC
Propsito: salto condicional, se toma en cuenta el estado de las banderas.
Sintaxis:
JNC etiqueta
Salta si no hay acarreo.
El salto se efecta si CF = 0.
Instruccin JNO
Propsito: salto condicional, se toma en cuenta el estado de las banderas.
Sintaxis:
JNO etiqueta
Salta si no hay desbordamiento.
El salto se efectua si OF = 0.
Instruccin JNP (JPO)
Propsito: salto condicional, toma en cuenta el estado de las banderas.
Sintaxis:
JNP etiqueta
Sintaxis:
JS etiqueta
Salta si el signo est prendido.
El salto se efecta si SF = 1.
Instruccin LOOP
Propsito: Generar un ciclo en el programa.
Sintaxis:
LOOP etiqueta
La instruccin loop decrementa CX en 1, y transfiere el flujo del programa a la
etiqueta dada como operando si CX es diferente a 1.
Instruccin LOOPE
Propsito: Generar un ciclo en el programa considerando el estado de ZF
Sintaxis:
LOOPE etiqueta
Esta instruccin decrementa CX en 1. Si CX es diferente a cero y ZF es igual a 1,
entonces el flujo del programa se transfiere a la etiqueta indicada como operando.
Instruccin LOOPNE
Propsito: Generar un ciclo en el programa, considerando el estado de ZF
Sintaxis:
LOOPNE etiqueta
Esta instruccin decrementa en uno a CX y transfiere el flujo del programa solo
si ZF es diferente a 0.
Instruccin DEC
CMC
Esta instruccin complementa el estado de la bandera CF, si CF = 0 la
instruccin la iguala a 1, y si es 1 la instruccin la iguala a 0.
Podemos decir que unicamente "invierte" el valor de la bandera.
Instruccin STC
Propsito: Activar la bandera de acarreo.
Sintaxis:
STC
Esta instruccin pone la bandera CF en 1.
Instruccin STD
Propsito: Activar la bandera de direccin.
Sintaxis:
STD
La instruccin STD pone la bandera DF en 1.
Instruccin STI
Propsito: Acticar la bandera de interrupcin.
Sintaxis:
STI
La instruccin activa la bandera IF, esto habilita las interrupciones externas
enmascarables (las que funcionan unicamente cuando IF = 1 ).
seguir:
inc si ;para seguir recorriendo la palabra
loop comienzo ;bucle principal para recorrer palabra
resultado:
mov dx, offset msg3 ;copiar msg3 a dx
mov ah, 9 ;preparar ah con 9 para la interrupcion 21h
int 21h ;mostrar contenido en dx
final:
ret
msg db "Hola Mundo$"
msg2 db "ola$"
msg3 db "Si es subcadena$"
Ejercicio 3: Escribir un cdigo que verifique que todas los caracteres de una cadena se
encuentran en otra.
Por ejemplo: todas las letras de la cadena casa se encuentran en escaso. Pero no todas
las letras de cerro se en cuentran en recanate
org 100h
mov si, 0 ;ponemos si en 0
comienzo:
cmp msg[si],"$" ;si es el fin de la cadena mandar a final
jz resultado
mov di, 0 ;poner en 0 di
comprobar:
mov al, msg2[di] ;copiar msg2 con su posicion a al
cmp msg[si], al ;comparar msg con su posicion con al
jz seguir ;si se encuentra entonces continua
inc di ;incrementar di para seguir recorriendo cadena
cmp msg2[di], "$" ;si es que llega al final y no encontro coincidencia,
entonces ya termina el programa
jz final
loop comprobar ;bucle para recorrer
seguir:
inc si ;para seguir recorriendo la palabra
loop comienzo ;bucle principal para recorrer palabra
resultado:
mov dx, offset msg3 ;copiar msg3 a dx
mov ah, 9 ;preparar ah con 9 para la interrupcion 21h
int 21h ;mostrar contenido en dx
final:
ret
msg db "cerro$"
msg2 db "recanate$"
msg3 db "Si se encuentran todos los caracteres$"
Ejercicio 4: Escribir una programa que reciba una cadena ingresada por teclado, terminada
en ENTER. Luego que elimine todos los caracteres que no son dgitos, sin utilizar una
variable auxiliar.
ORG 100H
mov si, 0
lectura:
mov ah,1
int 21h
cmp al,13
jz resultado:
cmp al, 57 ;si tecla es mayor a 57 entonces ir a fin3 (tecla > 57)
ja fin3
cmp al,47 ;si tecla no es mayor a 47 ir a fin3 (tecla <= 47)
jng fin3
mov bx[si], al ;si es un digito entonces guardo en bx
inc si ;incrementa si
fin3:
jmp lectura
resultado:
mov ah,00h ;limpia la pantalla
mov al,03h
int 10h
mov bx[si], "$"
mov dx, offset bx
mov ah, 9 ;preparar ah con 9 para la interrupcion 21h
int 21h ;mostrar contenido en dx
ret
Ejercicio 5: Escribir un programa que tome una cadena que representa un nmero decimal
y escriba su equivalente octal
org 100h ; inicio de programa
mov si, 0
mov al, 0
cadAnum:
cmp cad[si], "$"
jz seguir
mov bl, 10
mul bl
sub cad[si], '0'
add al, cad[si]
inc si
loop cadAnum
seguir:
mov cx, si
mov si, 0
mov bl, 8
pasar:
div bl ;dividir al con bl
mov oct[si], ah ;copiar a la cadena oct el resultado sobrante de la
division
inc si ;incrementar si
loop pasar
fina:
cmp ah, 0
jnz final
mov oct[si], al
final:
;mov dx, offset res
;mov ah, 9 ;preparar ah con 9 para la interrupcion 21h
;int 21h ;mostrar contenido en dx
ret
cad db "64$"
oct db 0
mul bl
sub cad3[si], '0'
add al, cad3[si]
inc si
loop cadAnum2
seguir2:
mov bl, al
mov al, aux1
;realizar operaciones normalmente teniendo ya los dos numeros decimales
cmp cad2, "-"
jz resta
cmp cad2, "+"
jz suma
cmp cad2, "*"
jz multi
cmp cad2, "/"
jz divi
resta:
sub al, bl
jmp fin
suma:
add al, bl
jmp fin
multi:
mul bl
jmp fin
divi:
div bl
jmp fin
fin:
mov bx, ax
mov ah,09
lea dx,msg
int 21h
mov ax, bx
call PRINT_NUM
ret
cad1 db "10$"
cad2 db "-"
cad3 db "2$"
aux1 db ?
aux2 dw ?
msg dw "El resultado es: $"
;============================
; eternal loop to get
; and print keys:
wait_for_key:
; check for keystroke in
; keyboard buffer:
mov dh, pos
mov dl, pos
mov bh, 0
mov ah, 2
int 10h ;Movemos el cursor
mov al,'X'
mov bh,0
mov bl,1
mov cx,1
mov ah,09h
inc pos ;Imprimimos una x
int 10h
mov ah, 1
int 16h
jz wait_for_key
; get keystroke from keyboard:
; (remove from the buffer)
mov ah, 0
int 16h
; print the key:
mov ah, 0eh
int 10h
; press 'esc' to exit:
cmp al, 1bh
jz exit
jmp wait_for_key
;============================
exit:
ret
msg db "Type anything...", 0Dh,0Ah
db "[Enter] - carriage return.", 0Dh,0Ah
db "[Ctrl]+[Enter] - line feed.", 0Dh,0Ah
db "You may hear a beep", 0Dh,0Ah
db " when buffer is overflown.", 0Dh,0Ah
db "Press Esc to exit.", 0Dh,0Ah, "$"
pos db 1
end
mov si, cx
mov ah, v[si-1]
cmp ah,v[bx-1]
jnge seguir ;Si
mov dh, v[bx-1]
mov dl, v[si-1]
mov v[bx-1], dl
mov v[si-1], dh
seguir:
loop bucle2
mov cx, c
loop bucle1
ret
v db 2,32,64,32,98,12,5,21,91
c dw 0
cx
color ;AL = pixel color
0ch ;Change color for a single pixel
;set pixel
Ejercicio 11: Escribir un programa que lea un archivo y cuente cuantas palabras terminan
con la letra a.
name "archivo3"
org 100h
mov al, 0 ;modo de acceso para abrir arhivo, modo lectura/escritura
mov dx, offset archivo ;offset lugar de memoria donde esta la variable
mov ah, 3dh ;se intenta abrir el archivo
int 21h ;llamada a la interrupcion DOS
jc error ; si se prendio la bandera c ir a error
mov handle, ax ;si no paso mover a lo que le dio el SO
jmp leer
error:
; ....
;leer archivo
leer:
mov bx, handle
mov cx, 1
mov dx, offset leido
mov ah, 3fh
int 21h