Está en la página 1de 80

1

1. Escribir un programa en ensamblador que muestre un mensaje por pantalla


mediante interrupciones:
2.
3. ;------------------------------------------------------------------
------------
4. ;Definicion del segmento de datos
5. ;------------------------------------------------------------------
------------
6. DATOS SEGMENT
7.
8. saludo db "Hola mundo!!!","$"
9.
10. DATOS ENDS
11.
12. ;-----------------------------------------------------------------
-------------
13. ;Definicion del segmento de codigo
14. ;-----------------------------------------------------------------
-------------
15. CODE SEGMENT
16. assume cs:code,ds:datos
17.
18. START PROC
19. mov ax,datos ;
20. mov ds,ax ;Inicializar
21.
22. mov dx,offset saludo ;Cargar la direccion del saludo
23. mov ah,9 ;Opcion que va a servir a la
interrupcion 21h para
24. ;indicar que debe mostrar por
pantalla el offset
25. ;que hay en DX hasta que encuentre
el caracter '$'
26. int 21h ;Interrupcion que lo mostrara por
pantalla
27.
28. mov ax,4C00h ;
29. int 21h ;Terminar el programa
30.
31. START ENDP
32.
33. CODE ENDS
34. END START
35.
36. Escribir un programa en ensamblador que muestre un mensaje por pantalla
accediendo a la memoria de video (0B800h):
37.
38. ;-----------------------------------------------------------------
-------------
39. ;Definicion del segmento de datos
40. ;-----------------------------------------------------------------
-------------
41. DATOS SEGMENT
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 tamaño 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. Este programa pide el nombre al usuario y lo muestra por pantalla:
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
136. ;-----------------------------------------------------------------
-------------
137. EXTRA SEGMENT
138. RESULT DW 0,0
139. EXTRA ENDS
140.
141. ;-----------------------------------------------------------------
-------------
142. ;Definicion del segmento de codigo
143. ;-----------------------------------------------------------------
-------------
144. CODE SEGMENT
145. assume cs:code,ds:datos,es:extra,ss:pila
146.
147. START PROC
148. ;Inicializamos los registros de segmento
149. mov ax,datos
150. mov ds,ax
151. mov ax,pila
152. mov ss,ax
153. mov ax,extra
154. mov es,ax
155. ;Fin de las inicializaciones
156.
157. ;Limpiamos la pantalla
158. mov ax,0B800h ;En esta direccion comienza la memoria de
video
159. mov es,ax ;Lo cargamos en el segmento extra
160. xor di,di ;Ponemos DI=0. Esto equivale a mov di,0,
pero
161. ;xor di,di consume 3 ciclos de reloj y
con mov 4
162. mov cx,80*25 ;El tamaño total es 2000 (80 lineas x 25
columnas)
163.
164. b_clear: ;Bucle que se encargara de recorrer los
2000
165. ;caracteres de la pantalla para limpiarla
166. mov al,20h ;20h=" " Rellenar la pantalla con
espacios
167. mov ah,1bh ;Fondo azul, letras blancas
168. mov es:[di],ax
169. inc di
170. inc di
171. loop b_clear
172.
173. ;Mostramos un mensaje
174. mov si,offset mensaje
175. mov di,(80*10+10)*2 ;Linea 10, columna 10
176. mov cx,49 ;Tamaño del mensaje
177.
178. b_saludo: ;Bucle que se encargara de recorrer los
2000
179. ;caracteres de la pantalla para limpiarla
180. mov al,[si]
181. mov ah,1bh ;Fondo azul, letras blancas
182. mov es:[di],ax
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. El mismo programa que antes, pero ahora con llamadas a funciones:
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
280. ; machaca: AX, DS, SS, ES
281. ; make: Inicializa los registros de segmento
282. ;
283. ;-----------------------------------------------------------------
-------------
284. inicializa_seg proc near
285.
286. mov ax,datos
287. mov ds,ax
288. mov ax,pila
289. mov ss,ax
290. mov ax,extra
291. mov es,ax
292.
293. ret
294.
295. inicializa_seg endp
296.
297.
298. ;-----------------------------------------------------------------
-------------
299. ; limpia_pantalla
300. ;
301. ; in:
302. ; out:
303. ; machaca: DI, ES
304. ; make: Limpia la pantalla escribiendo espacios en las 80x25
posiciones de
305. ; la pantalla, accediendo a la memoria de video
306. ;
307. ;-----------------------------------------------------------------
-------------
308. limpia_pantalla proc near
309.
310. push ax ;Guardar en la pila las variables que
queremos
311. push cx ;conservar para cuando salgamos de la
funcion
312.
313. mov ax,0B800h ;En esta direccion comienza la memoria de
video
314. mov es,ax ;Lo cargamos en el segmento extra
315. xor di,di ;Inicializar DI a 0
316. mov cx,80*25 ;El tamaño total es 2000 (80 lineas x 25
columnas)
317.
318. b_clear: ;Bucle que se encargara de recorrer los
2000
319. ;caracteres de la pantalla para limpiarla
320. mov al,20h ;20h=" " Rellenar la pantalla con
espacios
321. mov ah,1bh ;Fondo azul, letras blancas
322. mov es:[di],ax
323. inc di
324. inc di
325. loop b_clear
326.
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 ;Tamaño 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 ;Linea 12, columna 31
438.
439. mostrar_nombre:
440. mov al,[si]
441. mov ah,1bh ;Fondo azul, letras blancas
442. mov es:[di],ax
443. inc dx ;Cuenta el numero de caracteres
444. inc si
445. inc di
446. inc di
447. cmp dl,nombre[1] ;Comparar con el numero de
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. Programa que calcula el factorial de 3 y lo muestra por pantalla:
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.
480. ;-----------------------------------------------------------------
-------------
481. ;Definicion del segmento extra
482. ;-----------------------------------------------------------------
-------------
483. EXTRA SEGMENT
484. result dw 0,0 ;2 palabras (4 bytes)
485. EXTRA ENDS
486.
487. ;-----------------------------------------------------------------
-------------
488. ;Definicion del segmento de codigo
489. ;-----------------------------------------------------------------
-------------
490. CODE SEGMENT
491. assume CS:code,DS:datos,ES:extra,SS:pila
492.
493. factorial db 0 ;Variable para guardar el factorial
494.
495. START PROC
496.
497. call inicializar ;Inicializa los registros de
segmento
498. mov sp,64 ;Carga el puntero de pila con el
valor mas alto
499.
500. mov cl,dato
501. call calcula_factorial ;Calcula el faltorial de dato
502. mov factorial,al ;Almacenar el resultado en factorial
503. call muestra_factorial ;Muestra el valor del factorial
504.
505. mov ax,4C00h ;
506. int 21h ;Terminar el programa
507.
508.
509. START ENDP
510.
511. ;-----------------------------------------------------------------
-------------
512. ; inicializar
513. ;
514. ; in:
515. ; out: Los registros de segmento quedan inicializados
516. ; machaca: AX, DS, SS, ES
517. ; make: Inicializa los registros de segmento
518. ;
519. ;-----------------------------------------------------------------
-------------
520. inicializar proc near
521.
522. mov ax,datos
523. mov ds,ax
524. mov ax,pila
525. mov ss,ax
526. mov ax,extra
527. mov es,ax
528.
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 carácter en las 2000 posiciones de
la pantalla:
2.
3. pantalla EQU 0B800h ;Direccion física de comienzo de la
pantalla
4.
5. ;------------------------------------------------------------------
------------
6. ;Definición del segmento de codigo
7. ;------------------------------------------------------------------
------------
8. CODE SEGMENT
9. assume cs:code
10.
11. START PROC
12. mov ax,pantalla ;Cargar la dirección 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 carácter 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 carácter
23.
24. mov ax,4C00h ;
25. int 21h ;Terminar el programa
26.
27. START ENDP
28.
29. CODE ENDS
30. END START
31. Hacer un programa que coja el carácter 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. ;Definición del segmento de codigo
37. ;-----------------------------------------------------------------
-------------
38. CODE SEGMENT
39. assume cs:code
40.
41. START PROC
42. mov ax,pantalla ;Cargar la dirección de la
coordenada 0,0 de la
43. mov ds,ax ;pantalla
44. xor bx,bx
45. mov dx,ds:[bx] ;Obtener el carácter de la
coordenada 0,0
46.
47. pinta_caracter:
48. inc bx
49. inc bx
50. mov ds:[bx],dx ;Copiar el carácter
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
66. Nos vemos en la necesidad ya de empezar a manejar el Turbo Debugger. No
todos los programas que hagamos tienen por qué mostrar algo por la pantalla.
Veremos ahora un programa que realiza la suma de los números
1+2+3+4+5+6+7+8+9+10=55=37h. La salida de esta suma se irá guardando en
el acumulador (AX). Con el TD podremos ir viendo como el registro AX va
aumentando hasta llegar a 37 en hexadecimal, que va a ser el equivalente a 55
en decimal. Todo lo que veremos en el TD va a estar en hexadecimal. Al
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

Este archivo de procesamiento por lotes lo que hace es ensamblar el archivo,


linkarlo y por ultimo lanzar el Turbo Debugger para nuestro archivo. Claro está que
todo esto puede hacerse paso por paso, pero bueno, cada uno verá lo que prefiere.
Mi fichero t.bat no se diferencia en casi nada de deb.bat, la única diferencia es que
en lugar de td %1 debemos poner un %1 para que lo ejecute. De esta manera t.bat lo
que hace es ensamblar, linkar y ejecutar el programa. Con estos programas ya
estamos preparados para hacer frente al siguiente ejemplo, para el cual veremos su
resultado en el TD.

;------------------------------------------------------------------
------------
;Definición del segmento de codigo
;------------------------------------------------------------------
------------
CODE SEGMENT
assume CS:code

START:

xor ax,ax ;
mov cx,1 ;Inicializar

suma:
add ax,cx ;
inc cx ;
cmp cx,11 ;
jne suma ;Sumar 1+...+10=37h

mov ax,4C00h ;
int 21h ;Terminar el programa

CODE ENDS
END START

El siguiente programa es algo más sofisticado y potente. La teoría la


explicaremos después de ver el ejemplo.

100. Realizar un programa que limpie la pantalla dejando el fondo azul y los
caracteres rojos:
101.
102. pantalla EQU 0B800h
103.
104. ;-----------------------------------------------------------------
-------------
105. ;Definición del segmento de pila
106. ;-----------------------------------------------------------------
-------------
107. PILA SEGMENT STACK "STACK"
108. db 40h dup(0)
109. PILA ENDS
110.
111. ;-----------------------------------------------------------------
-------------
112. ;Definición del segmento extra
113. ;-----------------------------------------------------------------
-------------
114. EXTRA SEGMENT
115. result dw 0,0
116. EXTRA ENDS
117.
118. ;-----------------------------------------------------------------
-------------
119. ;Definición del segmento de codigo
120. ;-----------------------------------------------------------------
-------------
121. CODE SEGMENT
122. assume cs:code,es:extra,ss:pila
123.
124. START PROC
125.
126. cld ;DF=0 (incrementar DI)
127. mov ax,pantalla
128. mov es,ax
129. xor di,di
130. mov ax,1C00h ;Fondo azul, caracteres rojos con
intensidad
131. ;Equivalente a: mov
ax,0001110000000000b
132. mov cx,2000
133. rep stosw ;Repetirlo las 2000 veces
134.
135. mov ax,4C00h ;
136. int 21h ;Terminar el programa
137.
138. START ENDP
139.
140. CODE ENDS
141. END START

Si quisiesemos poner los atributos de otra forma sólo hay que cambiar una línea.
Podríamos ponerla de la siguiente manera, por ejemplo:

mov ax,1100001000000000b ó mov ax,0C200h

si quisiesemos poner el fondo rojo con letras verdes.

Teoría para entender el ejercicio:

STOSW: Se transfiere el registro AX a la palabra ES:[DI]. DI se actualiza en dos


unidades.
Si la bandera de dirección es cero (DF=0), DI se incrementa, si DF=1, se
decrementa.
Esto lo logramos con las instrucciones CLD o STD.
En CX hemos especificado el número de elementos de la cadena. En este caso las
2000 posiciones, son las 80x25 posiciones de la pantalla.

Para indicar en la memoria de pantalla como queremos el fondo y los caracteres


podemos hacerlo en sus 8 bits. Para indicar el carácter tenemos otros 8 bits. Cada
número o letra hexadecimal equivale a un nibble (4 bits):

código atributo (1 byte). Los bits son los siguientes:


7 - Utilizado para indicar si el carácter parpadea o no.
6 - Componente rojo del fondo
5 - Componente verde del fondo
4 - Componente azul del fondo
3 - Intensidad en los caracteres
2 - Componente rojo del carácter
1 - Componente verde del carácter
0 - Componente azul del carácter

Como vemos en nuestro ejemplo (0001 1100 0000 0000), hemos activado el
componente azul del fondo, la intensidad y el componente rojo de los caracteres.

código carácter (1 byte): Podemos elegir de la tabla ASCII aquel carácter que
prefiramos. Como carácter elegimos el 00h, que en la tabla ASCII va a equivaler a
dejar el fondo sin ningún carácter. Si quiesiesemos que apareciese el carácter 'V' en
el fondo pues cogeríamos el 56h. Cuando ejecutemos el programa, si queremos
volver a tener nuestra pantalla como antes, basta con un un simple:

C:\>cls

Volveremos a tener la pantalla con letras blancas sobre fondo negro.

1. Realizar un programa que muestre la tabla de caracteres ASCII por pantalla:


2.
3. ;------------------------------------------------------------------
------------
4. ; Programa que muestra la tabla de caracteres ASCII por pantalla
5. ;------------------------------------------------------------------
------------
6. PANTALLA equ 0B800h
7.
8. ;------------------------------------------------------------------
------------
9. ;Definicion del segmento de pila
10. ;-----------------------------------------------------------------
-------------
11. PILA SEGMENT STACK "STACK"
12. db 40h dup(0)
13. PILA ENDS
14.
15. ;-----------------------------------------------------------------
-------------
16. ;Definicion del segmento de codigo
17. ;-----------------------------------------------------------------
-------------
18. CODE SEGMENT
19. assume CS:code, SS:pila
20.
21. START:
22. mov ax,PANTALLA
23. mov ds,ax
24.
25. xor bx,bx
26. xor al,al
27. mov cx,256 ;Numero de caracteres que contiene
la tabla ASCII
28.
29. mostrar_ascii:
30. mov [bx],al ;Escribirlo en la coordenada de la
pantalla
31. inc bx ;
32. inc bx ;Pasar a la siguiente coordenada
33. inc al ;Pasar al siguiente caracter
34. loop mostrar_ascii
35.
36. mov ax,4C00h ;
37. int 21h ;Terminar el programa
38.
39. CODE ENDS
40. END START
41. Este programa se encarga de dibujar un cuadrado en la pantalla, ponerlo con
fondo blanco y rellenarlo con caracteres 'V':
42.
43. PANTALLA equ 0B800h
44.
45. ;-----------------------------------------------------------------
-------------
46. ;Definicion del segmento de pila
47. ;-----------------------------------------------------------------
-------------
48. PILA SEGMENT STACK "STACK"
49. db 40h dup(0)
50. PILA ENDS
51.
52. ;-----------------------------------------------------------------
-------------
53. ;Definicion del segmento de codigo
54. ;-----------------------------------------------------------------
-------------
55. CODE SEGMENT
56. assume CS:code, SS:pila
57.
58. START:
59. mov ax,PANTALLA
60. mov ds,ax
61.
62. mov dl,0 ;Primera linea en la que
empezaremos a pintar
63. mov cx,10 ;Numero de lineas que vamos a
tener
64.
65. BucleLineas:
66. push cx
67.
68. mov dh,0 ;Primera columna
69. mov cx,20 ;Numero de columnas
70.
71. BucleColumnas:
72. mov al,80*2 ;Bytes por linea
73. mul dl ;Por el numero de linea
74. mov bx,ax
75. mov al,2 ;2 bytes por columna
76. mul dh ;Por el numero de columna
77. add bx,ax
78. mov word ptr [bx],7056h ;Fondo blanco y letra 'V'
79. inc dh ;Siguiente columna
80. loop BucleColumnas
81.
82. pop cx ;Recuperamos el contador de las
lineas
83. inc dl ;Pasar a la siguiente linea
84. loop BucleLineas
85.
86. mov ax,4C00h
87. int 21h
88.
89. CODE ENDS
90. END START
91. Este programa le pregunta al usuario si desea continuar o no hasta que se
pulse la tecla 'N' o 'n':
92.
93. cr equ 13 ;retorno de carro
94. lf equ 10 ;alimentacion de linea
95.
96. ;-----------------------------------------------------------------
-------------
97. ;Definicion del segmento de datos
98. ;-----------------------------------------------------------------
-------------
99. DATOS SEGMENT
100. DeseaContinuar db cr,lf,'Desea continuar? S/N: '
101. db'$'
102. continuando db ' Continuando...',cr,lf
103. db'$'
104. LetraErronea db ' La tecla pulsada es incorrecta.',cr,lf
105. db'$'
106. DATOS ENDS
107.
108. ;-----------------------------------------------------------------
-------------
109. ;Definicion del segmento de pila
110. ;-----------------------------------------------------------------
-------------
111. PILA SEGMENT STACK "STACK"
112. db 40h dup(?)
113. PILA ENDS
114.
115. ;-----------------------------------------------------------------
-------------
116. ;Definicion del segmento de codigo
117. ;-----------------------------------------------------------------
-------------
118. CODE SEGMENT
119. assume CS:code, DS:datos, SS:pila
120.
121. START:
122. mov ax,datos
123. mov ds,ax
124. jmp continuar ;Saltamos a la etiqueta
CONTINUAR
125.
126. INICIO:
127. lea dx,continuando ;
128. mov ah,9 ;
129. int 21h ;Mensaje de que seguimos en el
programa
130. jmp continuar ;Salto para preguntar si se
desea continuar
131.
132. ERROR:
133. lea dx,LetraErronea ;
134. mov ah,9 ;Mensaje de que la letra
introducida
135. int 21h ;no es correcta
136.
137. CONTINUAR:
138. lea dx,DeseaContinuar ;
139. mov ah,9 ;
140. int 21h ;Mostrar pregunta para ver si
desea continuar
141.
142. mov ah,1 ;Esperar a que se pulse una tecla
143. int 21h ;y mostrarla por pantalla
144.
145. cmp al, 'S' ;
146. je inicio ;
147. cmp al, 's' ;
148. je inicio ;Desea continuar
149.
150. cmp al, 'N' ;
151. je salir ;
152. cmp al, 'n' ;
153. je salir ;No desea continuar, terminamos
154.
155. jmp error ;La tecla pulsada no es 'S', 's',
'N' ni 'n'
156. ;Se va a mostrar un mensaje de
error. Saltamos
157. ;a la etiqueta ERROR
158.
159. salir:
160. mov ax, 4C00h
161. int 21h
162.
163. CODE ENDS
164. END START
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
171. ;-----------------------------------------------------------------
-------------
172. PILA SEGMENT STACK "STACK"
173. db 40h dup(0)
174. PILA ENDS
175.
176. ;-----------------------------------------------------------------
-------------
177. ;Definicion del segmento de codigo
178. ;-----------------------------------------------------------------
-------------
179. CODE SEGMENT
180. assume CS:code, SS:pila
181.
182. START:
183. mov ax,pantalla ;
184. mov ds,ax ;DS apunta a la direccion de la
pantalla
185.
186. xor bx,bx
187. mov cx,2000 ;80 filas x 25 columnas
188.
189. cambia_minus:
190. mov al,ds:[bx] ;Obtenemos el caracter que hay en la
pantalla
191. ;en la coordenada indicada
192. cmp al,byte ptr 'A' ;Comprobar que este entre la letra
'A'
193. jb siguiente ;
194. cmp al,byte ptr 'Z' ;y la letra 'Z'
195. ja siguiente ;Si no es asi pasamos al siguiente
caracter
196. add al,32 ;Para pasar de mayusculas a
minusculas
197. ;hay que sumar 32 para movernos en
la
198. ;tabla ASCII de las mayusculas a las
minusculas
199. mov ds:[bx],al ;Escribimos en la pantalla el
caracter cambiado
200. ;a minusculas
201. siguiente:
202. inc bx ;
203. inc bx ;Pasamos a la siguiente coordenada
204. loop cambia_minus
205.
206. mov ax,4C00h ;
207. int 21h ;Terminamos el programa
208.
209. CODE ENDS
210. END START

4
Vamos a ver diferentes ejemplos de instrucciones para entenderlas un poco mejor. Será
bueno tener un libro al lado para saber qué hace cada instrucción.

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
33. Ejemplo de la instruccion: AAM (ajuste ASCII en multiplicación)
34.
35. ;-----------------------------------------------------------------
-------------
36. ; Programa que prueba la instruccion: AAM
37. ;
38. ; ah <- cociente (al/10)
39. ; al <- resto (al/10)
40. ;
41. ;-----------------------------------------------------------------
-------------
42.
43. ;-----------------------------------------------------------------
-------------
44. ;Definicion del segmento de codigo
45. ;-----------------------------------------------------------------
-------------
46. CODE SEGMENT
47. assume CS:code
48.
49. START:
50.
51. mov al,9
52. mov cl,5
53. mul cl ;Resultado: ax=002D
54. aam ;En el cociente hay un 4 y en el resto un 5
55. ;Resultado es ax=0405
56.
57. mov ax,4c00h
58. int 21h
59.
60. CODE ENDS
61. END START
62. Ejemplo de la instruccion: AAA (ajuste ASCII en suma)
63.
64. ;-----------------------------------------------------------------
-------------
65. ; Programa que muestra el uso de la instruccion AAA. Esta
instruccion convierte
66. ; el contenido de AL en un numero decimal ASCII (desempaquetado)
tras una
67. ; instruccion de suma. Se utiliza para ajustar el resultado
despues de una suma
68. ; de dos numeros decimales en formato ASCII
69. ;-----------------------------------------------------------------
-------------
70.
71. ;-----------------------------------------------------------------
-------------
72. ;Definicion del segmento de pila
73. ;-----------------------------------------------------------------
-------------
74. PILA SEGMENT STACK "STACK"
75. db 40h dup(0)
76. PILA ENDS
77.
78. ;-----------------------------------------------------------------
-------------
79. ;Definicion del segmento de codigo
80. ;-----------------------------------------------------------------
-------------
81. CODE SEGMENT
82. assume CS:code,SS:pila
83.
84. START PROC
85.
86. mov ax,8 ;
87. add al,1 ;
88. aaa ;AX=0009h
89. mov ax,8 ;
90. add al,2 ;
91. aaa ;AX=0100h
92. mov ax,11110001b ;
93. add al,1 ;
94. aaa ;AX=0002h
95. mov ax,8 ;
96. add al,7 ;
97. aaa ;AX=0105h
98. add al,4 ;
99. aaa ;AX=0109h
100. add al,9 ;
101. aaa ;AX=0208h
102.
103.
104. mov ax,4C00h ;
105. int 21h ;Terminar el programa
106.
107. START ENDP
108.
109. CODE ENDS
110. END START
111. Ejemplo de la instruccion: AAA (ajuste ASCII en suma). Del examen de
ETCII del año 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. END START
143. Ejemplo que muestra la diferencia entre las instrucciones: AAA y DAA
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. Ejemplo de la instrucción NEG (convertir a complemento a 2):
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
188. ;-----------------------------------------------------------------
-------------
189. CODE SEGMENT
190. assume CS:code, SS:pila
191.
192. START:
193.
194. mov al,8
195. neg al ;Convertir a su complemento a 2
196.
197. mov ax,4C00h
198. int 21h
199.
200. CODE ENDS
201. END START
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

5
1. Realizar un programa que guarde el estado de la pantalla con todos sus
caracteres, después rellene toda la pantalla con '*' y por último vuelva a dejar
la pantalla como estaba:
2.
3. ;------------------------------------------------------------------
------------
4. ;Programa que guarda el estado de la pantalla con todos sus
caracteres, despues
5. ;rellena toda la pantalla con '*' y por ultimo vuelve a dejar la
pantalla como
6. ;estaba
7. ;------------------------------------------------------------------
------------
8.
9. PANTALLA equ 0B800h
10.
11. ;-----------------------------------------------------------------
-------------
12. ;Definicion del segmento de datos
13. ;-----------------------------------------------------------------
-------------
14. DATOS SEGMENT
15.
16. pantalla_bak db 80*25*2 DUP(?) ;Reservar una variable para
guardar toda la
17. ;informacion de la pantalla
18. DATOS ENDS
19.
20. ;-----------------------------------------------------------------
-------------
21. ;Definicion del segmento de pila
22. ;-----------------------------------------------------------------
-------------
23. PILA SEGMENT STACK "STACK"
24. db 40h dup(0)
25. PILA ENDS
26.
27. ;-----------------------------------------------------------------
-------------
28. ;Definicion del segmento extra
29. ;-----------------------------------------------------------------
-------------
30. EXTRA SEGMENT
31. RESULT DW 0,0
32. EXTRA ENDS
33.
34. ;-----------------------------------------------------------------
-------------
35. ;Definicion del segmento de codigo
36. ;-----------------------------------------------------------------
-------------
37. CODE SEGMENT
38. assume DS:datos, CS:code, SS:pila
39.
40. START:
41. mov ax,PANTALLA
42. mov ds,ax
43.
44. xor si,si
45. mov ax,datos
46. mov es,ax
47. lea di,pantalla_bak ;Apuntar a la variable
48.
49. mov cx,80*25*2 ;Numero de bytes que tenemos que
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
91. Realizar un programa que devuelva la primera posición en que se ha
encontrado un carácter dado:
92.
93. ;-----------------------------------------------------------------
-------------
94. ;Devuelve la primera posicion en que se ha encontrado el caracter
a buscar
95. ;-----------------------------------------------------------------
-------------
96.
97. CARACTER equ 'v'
98.
99. ;-----------------------------------------------------------------
-------------
100. ;Definicion del segmento de datos
101. ;-----------------------------------------------------------------
-------------
102. DATOS SEGMENT
103. mensaje db "www.victorsanchez2.net"
104. msg_caracter db "El caracter: "
105. msg_posicion db "Se encuentra en la posicion: "
106. DATOS ENDS
107.
108. ;-----------------------------------------------------------------
-------------
109. ;Definicion del segmento de pila
110. ;-----------------------------------------------------------------
-------------
111. PILA SEGMENT STACK "STACK"
112. db 40h DUP(0)
113. PILA ENDS
114.
115. ;-----------------------------------------------------------------
-------------
116. ;Definicion del segmento extra
117. ;-----------------------------------------------------------------
-------------
118. EXTRA SEGMENT
119. RESULT DW 0,0
120. EXTRA ENDS
121.
122. ;-----------------------------------------------------------------
-------------
123. ;Definicion del segmento de codigo
124. ;-----------------------------------------------------------------
-------------
125. CODE SEGMENT
126. assume cs:code,ds:datos,es:extra,ss:pila
127.
128. START PROC
129. ;Inicializamos los registros de segmento
130. mov ax,datos
131. mov ds,ax
132. mov ax,pila
133. mov ss,ax
134. mov ax,extra
135. mov es,ax
136.
137. ;Limpiamos la pantalla
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 ;Fondo negro y letras blancas
241.
242. pintar: ;
243. mov al,[si] ;
244. mov es:[di],ax ;
245. inc si ;
246. inc di ;
247. inc di ;
248. loop pintar ;Mostrarlo por pantalla
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 sucesión de códigos ASCII en la
esquina superior derecha de la pantalla, intercambiando los caracteres cada
medio segundo. Este programa ya es algo más complejo que los anteriores ya
que empezamos a trabajar con programas residentes y el RTC. Os recomiendo
que aprendais bien las características de los programas residentes y
programación del RTC antes de intentar comprender este ejercicio por
completo. Este tipo de ejercicios van un nivel más 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 ;Bifurcar a la rutina de instalacion

letras proc far

push ax ;
push es ;
push di ;Guardamos los registros en la pila

mov al,0Ch ;
out 70h,al ;
in al,71h ;Leer el RTC

mov ax,PANTALLA
mov es,ax
mov di,79*2
mov ax,es:[di] ;Guardamos en AX lo que hay en la esquina
inc al ;Pasamos al siguiente caracter
mov es:[di],ax ;Lo mostramos por pantalla

cli ;Inhabilitar las interrupciones


mov al,20h
out 20h,al
out 0A0h,al
sti ;Habilitar las interrupciones

pop di ;
pop es ;
pop ax ;Recuperar los registros

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 al,0A1h ;Leer el PIC esclavo


and al,11111110b ;
out 0A1h,al ;Activamos IR0

in al,21h ;Leer el PIC maestro


and al,11111011b ;
out 21h,al ;Activado

mov al,0Ah ;Vamos a escribir en el registro A del RTC


out 70h,al ;
mov al,2Fh ;Los simbolos se intercambian cada medio
segundo
out 71h,al ;Lo indicamos en el registro A del RTC

mov al,0Bh ;Vamos a escribir en el registro B del RTC


out 70h,al
in al,71h
or al,01000000b ;
out 71h,al ;Activamos las interrupciones periodicas

sti ;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á
mostrándose la sucesión de los caracteres ASCII mientras mantengamos
encendido el ordenador. Después 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.


Después 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
;------------------------------------------------------------------
------------
PILA SEGMENT STACK "STACK"
DB 40h dup(0)
PILA ENDS

;------------------------------------------------------------------
------------
;Definicion del segmento extra
;------------------------------------------------------------------
------------
EXTRA SEGMENT
RESULT DW 0,0
EXTRA ENDS

;------------------------------------------------------------------
------------
;Definicion del segmento de codigo
;------------------------------------------------------------------
------------
CODE SEGMENT
ASSUME CS:CODE,SS:pila

START PROC FAR


call desinstalar

mov ax,4C00h ;
int 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 ;Inhabilitar las interrupciones

;Antes de proceder a desinstalarlo comprobamos si existe


cmp word ptr es:[70h*4],0
je FIN
mov al,0Bh ;Registro B del PIC
out 70h,al ;
and al,10111111b ;
out 71h,al ;Deshabilitamos las interrupciones
periodicas (PIE)

in al,0A1h ;Leer el PIC esclavo


OR al,00000001B ;
out 0A1h,al ;desconectamos la interrupcion del RTC al
PIC esclavo

;Restaurar los vectores de interrupcion


xor ax,ax
mov es,ax
mov ax,es:[70h*4+2] ;Copia en DS el segmento de codigo del
mov ds,ax ;programa a desinstalar
xor ax,ax
mov es:[70h*4],ax ;Poner el offset a 0
mov es:[70h*4+2],ax ;Poner CS a 0

;Desinstalar el programa residente


mov ax,ds:[2Ch] ;
mov es,ax ;
mov ah,49h ;
int 21h ;Desinstalar el PSP
mov ax,ds ;
mov es,ax ;
mov ah,49h ;
int 21h ;Desinstalar CS

sti ;Habilitar las interrupciones

FIN: pop ds
pop es
pop ax
ret

desinstalar ENDP

CODE ENDS
END START

6 Estos ejercicios van a ser algo más complejos y son del nivel que se va a exigir a
aquellos que estén cursando la asignatura de ETCII en la Universidad Autónoma de
Madrid.

1. Hallar cual es el valor de AX tras la segunda instrucción AAA:


2.
3. ; Ejercicio: examen ETCII - 7/11/01
4.
5. ;------------------------------------------------------------------
------------
6. ;Definicion del segmento de codigo
7. ;------------------------------------------------------------------
------------
8.
9. CODE SEGMENT
10. assume CS:code
11.
12. start:
13.
14. mov ax,16h
15. mov bx,191h
16. add ax,bx
17. aaa
18. add ax,7h
19. aaa
20.
21. mov ax,4c00h
22. int 21h
23.
24. CODE ENDS
25. END START
26. Hallar cual es el valor de AX tras la segunda instrucción AAA:
27.
28. ; Ejercicio: examen ETCII - Febrero 2000
29.
30. ;-----------------------------------------------------------------
-------------
31. ;Definicion del segmento de codigo
32. ;-----------------------------------------------------------------
-------------
33.
34. CODE SEGMENT
35. assume CS:code
36.
37. start:
38.
39. mov ax,123h
40. mov bx,77h
41. add ax,bx
42. aaa
43. add ax,5h
44. aaa
45.
46. mov ax,4c00h
47. int 21h
48.
49. CODE ENDS
50. END START
51. Hallar el valor de AX tras la instrucción "div bl":
52.
53. ;-----------------------------------------------------------------
-------------
54. ;Definicion del segmento de pila
55. ;-----------------------------------------------------------------
-------------
56. PILA SEGMENT STACK "STACK"
57. db 40h DUP(0)
58. PILA ENDS
59.
60. ;-----------------------------------------------------------------
-------------
61. ;Definicion del segmento de codigo
62. ;-----------------------------------------------------------------
-------------
63. CODE SEGMENT
64. assume cs:code,ss:pila
65.
66. START PROC
67. ;Inicializamos los registros de segmento
68. mov ax,pila
69. mov ss,ax
70.
71. mov ax,905h
72. mov bx,2h
73. aad
74. mov ah,10h
75. div bl
76.
77. mov ax,4C00h ;
78. int 21h ;Terminar el programa
79.
80. START ENDP
81.
82. CODE ENDS
83. END START
84. Hallar el valor de AX tras la instrucción "aam":
85.
86. ;-----------------------------------------------------------------
-------------
87. ;Definicion del segmento de codigo
88. ;-----------------------------------------------------------------
-------------
89. CODE SEGMENT
90. assume CS:code
91.
92. START:
93.
94. mov al,9
95. mov cl,5
96. mul cl
97. aam
98.
99. mov ax,4c00h
100. int 21h
101.
102. CODE ENDS
103. END START
104. Hallar el valor de AX tras la instrucción "daa":
105.
106. ;-----------------------------------------------------------------
-------------
107. ;Definicion del segmento de pila
108. ;-----------------------------------------------------------------
-------------
109. PILA SEGMENT STACK "STACK"
110. db 40h DUP(0)
111. PILA ENDS
112.
113. ;-----------------------------------------------------------------
-------------
114. ;Definicion del segmento de codigo
115. ;-----------------------------------------------------------------
-------------
116. CODE SEGMENT
117. assume cs:code,ss:pila
118.
119. START PROC
120.
121. mov ax,23h
122. mov bx,77h
123. add ax,bx
124. xor ah,ah
125. daa
126.
127. mov ax,4C00h ;
128. int 21h ;Terminar el programa
129.
130. START ENDP
131.
132. CODE ENDS
133. END START

7 Las soluciones y archivos fuente de todos los ejercicios podéis obtenerlos escribiéndome
un e-mail para pedírmelos.

1. Hallar el valor de AX tras la instrucción "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
35. Hallar el valor de AX tras la instrucción "mov ax,[bp+1]":
36.
37. ;-----------------------------------------------------------------
-------------
38. ;Definicion del segmento de pila
39. ;-----------------------------------------------------------------
-------------
40. PILA SEGMENT STACK "STACK"
41. db 40h DUP(0)
42. PILA ENDS
43.
44. ;-----------------------------------------------------------------
-------------
45. ;Definicion del segmento de codigo
46. ;-----------------------------------------------------------------
-------------
47. CODE SEGMENT
48. assume cs:code,ss:pila
49.
50. START PROC
51. ;Inicializamos los registros de segmento
52. mov ax,pila
53. mov ss,ax
54.
55. mov ax,3759h
56. xor bx,bx
57. push ax
58. push bx
59. mov bp,sp
60. mov ax,[bp+1]
61.
62. mov ax,4C00h ;
63. int 21h ;Terminar el programa
64.
65. START ENDP
66.
67. CODE ENDS
68. END START
69. Hallar el valor de AX tras la instrucción "stosb":
70.
71. ;-----------------------------------------------------------------
-------------
72. ;Definicion del segmento de pila
73. ;-----------------------------------------------------------------
-------------
74. PILA SEGMENT STACK "STACK"
75. db 40h DUP(0)
76. PILA ENDS
77.
78. ;-----------------------------------------------------------------
-------------
79. ;Definicion del segmento extra
80. ;-----------------------------------------------------------------
-------------
81. EXTRA SEGMENT
82. RESULT DW 0,0
83. EXTRA ENDS
84.
85. ;-----------------------------------------------------------------
-------------
86. ;Definicion del segmento de codigo
87. ;-----------------------------------------------------------------
-------------
88. CODE SEGMENT
89. assume CS:code,ES:extra,SS:pila
90.
91. ;-----------------------------------------------------------------
-------------
92. ; Procedimiento inicial
93. ;-----------------------------------------------------------------
-------------
94. START PROC
95.
96. mov si,40h
97. cld
98. mov byte ptr ds:[si],0Fh
99. xor cx,cx
100. mov al,0F0h
101. rep scasb
102. std
103. mov di,si
104. mov bx,ds
105. mov es,bx
106. stosb
107.
108. mov ax,4C00h ;
109. int 21h ;Terminar el programa
110.
111. START ENDP
112.
113. CODE ENDS
114. END START
115. Hallar el valor de AX tras la instrucción "rep lodsw":
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. Otro ejercicio como el anterior:
157.
158. ;-----------------------------------------------------------------
-------------
159. ;Definicion del segmento de datos
160. ;-----------------------------------------------------------------
-------------
161. DATOS SEGMENT
162. texto db "Esto_es_una_cadena_de_texto",0
163. DATOS ENDS
164.
165. ;-----------------------------------------------------------------
-------------
166. ;Definicion del segmento de pila
167. ;-----------------------------------------------------------------
-------------
168. PILA SEGMENT STACK "STACK"
169. db 40h DUP(0)
170. PILA ENDS
171.
172. ;-----------------------------------------------------------------
-------------
173. ;Definicion del segmento de codigo
174. ;-----------------------------------------------------------------
-------------
175. CODE SEGMENT
176. assume cs:code,ds:datos,ss:pila
177.
178. START PROC
179. ;Inicializamos los registros de segmento
180. mov ax,datos
181. mov ds,ax
182. mov ax,pila
183. mov ss,ax
184.
185. mov si,offset texto
186. add si,19h
187. std
188. mov cx,5
189. rep lodsw
190.
191. mov ax,4C00h ;
192. int 21h ;Terminar el programa
193.
194. START ENDP
195.
196. CODE ENDS
197. END START
198. Y otro más. 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. ;-----------------------------------------------------------------
-------------
210. PILA SEGMENT STACK "STACK"
211. db 40h DUP(0)
212. PILA ENDS
213.
214. ;-----------------------------------------------------------------
-------------
215. ;Definicion del segmento de codigo
216. ;-----------------------------------------------------------------
-------------
217. CODE SEGMENT
218. assume cs:code,ds:datos,ss:pila
219.
220. START PROC
221. ;Inicializamos los registros de segmento
222. mov ax,datos
223. mov ds,ax
224. mov ax,pila
225. mov ss,ax
226.
227. mov si,offset texto
228. add si,0Dh
229. std
230. mov cx,5
231. rep lodsw
232.
233. mov ax,4C00h ;
234. int 21h ;Terminar el programa
235.
236. START ENDP
237.
238. CODE ENDS
239. END START
240. Hallar el valor de AX tras salir del bucle:
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 ;Terminar el programa
269.
270. START ENDP
271.
272. CODE ENDS
273. END START

8
1. El siguiente programa le pide al usuario la confirmación 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.
30. ;-----------------------------------------------------------------
-------------
31. ;Definicion del segmento de codigo
32. ;-----------------------------------------------------------------
-------------
33. CODE SEGMENT
34. assume CS:code, DS:datos, SS:pila
35.
36. START:
37. mov ax,datos
38. mov ds,ax
39. jmp continuar ;Saltamos a la etiqueta
CONTINUAR
40.
41. INICIO:
42. lea dx,continuando ;
43. mov ah,9 ;
44. int 21h ;Mensaje de que seguimos en el
programa
45. jmp continuar ;Salto para preguntar si se
desea continuar
46.
47. ERROR:
48. lea dx,LetraErronea ;
49. mov ah,9 ;Mensaje de que la letra
introducida
50. int 21h ;no es correcta
51.
52. CONTINUAR:
53. lea dx,DeseaContinuar ;
54. mov ah,9 ;
55. int 21h ;Mostrar pregunta para ver si
desea continuar
56.
57. mov ah,1 ;Esperar a que se pulse una tecla
58. int 21h ;y mostrarla por pantalla
59.
60. cmp al, 'S' ;
61. je inicio ;
62. cmp al, 's' ;
63. je inicio ;Desea continuar
64.
65. cmp al, 'N' ;
66. je salir ;
67. cmp al, 'n' ;
68. je salir ;No desea continuar, terminamos
69.
70. jmp error ;La tecla pulsada no es 'S', 's',
'N' ni 'n'
71. ;Se va a mostrar un mensaje de
error. Saltamos
72. ;a la etiqueta ERROR
73.
74. salir:
75. mov ax, 4C00h
76. int 21h
77.
78. CODE ENDS
79. END START
80. Este programa cambia el color de fondo de una posición determinada de
pantalla. Si se ejecuta varias veces seguidas veremos como cambia de blanco a
negro y viceversa:
81.
82. PANTALLA equ 0B800h
83.
84. ;-----------------------------------------------------------------
-------------
85. ;Definicion del segmento de pila
86. ;-----------------------------------------------------------------
-------------
87. PILA SEGMENT STACK "STACK"
88. db 40h dup(0)
89. PILA ENDS
90.
91. ;-----------------------------------------------------------------
-------------
92. ;Definicion del segmento de codigo
93. ;-----------------------------------------------------------------
-------------
94. CODE SEGMENT
95. assume CS:code, SS:pila
96.
97. START:
98. mov ax,PANTALLA
99. mov ds,ax
100. mov bx,(80*24+5)*2+1 ;Ultima linea, caracter 5
101. ;Utilizamos el '+1' para acceder
102. ;directamente al fondo
103.
104. cmp byte ptr [bx],07h ;Vemos si el fondo es negro
105. jz CambiaFondo
106.
107. mov byte ptr [bx],07h ;Si no es negro lo ponemos
108. jmp fin
109.
110. CambiaFondo:
111. mov byte ptr [bx],70h ;Ponemos el fondo blanco
112.
113. fin:
114. mov ax,4C00h
115. int 21h
116.
117. CODE ENDS
118. END START
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. PANTALLA equ 0b800h
122. ROJO equ 4
123. LETRA_ROJA equ 'V'
124. LETRA_AZUL equ 'S'
125. AZUL equ 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 ;Activamos las interrupciones periodicas
231.
232. sti ;Habilitar las interrupciones
233.
234. lea dx,instalar ;
235. int 27h ;Dejar residente
236.
237. instalar endp
238.
239. CODE ENDS
240. END START
241. El siguiente ejercicio de examen nos pide conocer la instrucción scasb.
Hallar cuál es el valor de AX tras la instrucción 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 ;AX=10h, SI=0, DI=42h
282.
283. mov ax,4C00h ;
284. int 21h ;Terminar el programa
285.
286. START ENDP
287.
288. CODE ENDS
289. END START
290. Otro ejercicio como el anterior, pero usando la instrucción repne.
Recordar que la instrucción 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 ;Terminar el programa
334.
335. START ENDP
336.
337. CODE ENDS
338. END START
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. Hallar el contenido de SI tras la ejecución de los bucles:
372.
373. ;-----------------------------------------------------------------
-------------
374. ; Ejercicio: examen ETCII - 12/02/96
375. ;-----------------------------------------------------------------
-------------
376.
377. ;-----------------------------------------------------------------
-------------
378. ;Definicion del segmento de codigo
379. ;-----------------------------------------------------------------
-------------
380. CODE SEGMENT
381. assume CS:code
382.
383. START:
384.
385. mov si,0
386. mov cx,4
387. L2: push cx
388. mov cx,100h
389. L1: dec cx
390. inc si
391. loop l1
392. pop cx
393. loop l2
394.
395. mov ax,4C00h
396. int 21h
397.
398. CODE ENDS
399. END START

9
1. Otro problema de examen. Hallar el valor de AX tras la instrucción 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)
18. PILA ENDS
19.
20. ;-----------------------------------------------------------------
-------------
21. ;Definicion del segmento de codigo
22. ;-----------------------------------------------------------------
-------------
23. CODE SEGMENT
24. assume cs:code,ds:datos,ss:pila
25.
26. START PROC
27. ;Inicializamos los registros de segmento
28. mov ax,datos
29. mov ds,ax
30. mov ax,pila
31. mov ss,ax
32.
33. mov ax,word ptr ds:[3]
34.
35. mov ax,4C00h ;
36. int 21h ;Terminar el programa
37.
38. START ENDP
39.
40. CODE ENDS
41. END START
42. Muy similar al anterior:
43.
44. ;-----------------------------------------------------------------
-------------
45. ;Definicion del segmento de datos
46. ;-----------------------------------------------------------------
-------------
47. DATOS SEGMENT
48. dw 3Ah,7Bh,9Ch
49. db 34h,76h,65h
50. org 2
51. db 67h,31h,56h,"SE ACABO"
52. DATOS ENDS
53.
54. ;-----------------------------------------------------------------
-------------
55. ;Definicion del segmento de pila
56. ;-----------------------------------------------------------------
-------------
57. PILA SEGMENT STACK "STACK"
58. db 40h DUP(0)
59. PILA ENDS
60.
61. ;-----------------------------------------------------------------
-------------
62. ;Definicion del segmento de codigo
63. ;-----------------------------------------------------------------
-------------
64. CODE SEGMENT
65. assume cs:code,ds:datos,ss:pila
66.
67. START PROC
68. ;Inicializamos los registros de segmento
69. mov ax,datos
70. mov ds,ax
71. mov ax,pila
72. mov ss,ax
73.
74. mov ax,word ptr ds:[3]
75.
76. mov ax,4C00h ;
77. int 21h ;Terminar el programa
78.
79. START ENDP
80.
81. CODE ENDS
82. END START
83. ¿Cuál es el valor de AX tras la instrucción NOP?:
84.
85. ; Ejercicio: examen ETCII - febrero 2002
86.
87. ;-----------------------------------------------------------------
-------------
88. ;Definicion del segmento de pila
89. ;-----------------------------------------------------------------
-------------
90. PILA SEGMENT STACK "STACK"
91. db 40h DUP(0)
92. PILA ENDS
93.
94. ;-----------------------------------------------------------------
-------------
95. ;Definicion del segmento extra
96. ;-----------------------------------------------------------------
-------------
97. EXTRA SEGMENT
98. RESULT DW 0,0
99. EXTRA ENDS
100.
101. ;-----------------------------------------------------------------
-------------
102. ;Definicion del segmento de codigo
103. ;-----------------------------------------------------------------
-------------
104. CODE SEGMENT
105. assume CS:code,ES:extra,SS:pila
106.
107. ;-----------------------------------------------------------------
-------------
108. ; Procedimiento inicial
109. ;-----------------------------------------------------------------
-------------
110. START PROC
111.
112. mov ax,1Fh
113. push ax
114. inc sp
115. push ax
116. dec sp
117. pop ax
118. pop ax
119. nop
120.
121. mov ax,4C00h ;
122. int 21h ;Terminar el programa
123.
124. START ENDP
125.
126. CODE ENDS
127. END START
128. Muy importantes también son los ejercicios de pila. Hallar el valor de
AX tras la instrucción 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 mayoría de las veces ;)
Hallar el valor de AX tras el último POP:
164.
165. ;-----------------------------------------------------------------
-------------
166. ;Definicion del segmento de pila
167. ;-----------------------------------------------------------------
-------------
168. PILA SEGMENT STACK "STACK"
169. db 40h DUP(0)
170. PILA ENDS
171.
172. ;-----------------------------------------------------------------
-------------
173. ;Definicion del segmento de codigo
174. ;-----------------------------------------------------------------
-------------
175. CODE SEGMENT
176. assume cs:code,ss:pila
177.
178. START PROC
179. ;Inicializamos los registros de segmento
180. mov ax,pila
181. mov ss,ax
182.
183. push 0F34h
184. push 63h
185. pop ax
186. inc sp
187. pop ax
188.
189. mov ax,4C00h ;
190. int 21h ;Terminar el programa
191.
192. START ENDP
193.
194. CODE ENDS
195. END START

10
1. Hallar el valor de AX tras la instrucción 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 ;Terminar el programa
21.
22. START ENDP
23.
24. CODE ENDS
25. END START
26. De nuevo un ejercicio sencillito para dejar a un lado los exámenes (por el
momento) y relajarnos un poco y ver otra forma de inicializar variables. Este
programa muestra dos líneas, 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 ;Terminar el programa
66.
67. START ENDP
68.
69. CODE ENDS
70. END START
71. Volvemos con más instrucciones de cadena y otro ejercicio de examen. Hallar
el valor de CX tras la instrucción repnz scasb:
72.
73. ;-----------------------------------------------------------------
-------------
74. ;Definicion del segmento de datos
75. ;-----------------------------------------------------------------
-------------
76. DATOS SEGMENT
77. texto db "Esto es un texto",0,"Y este otro",0
78. DATOS ENDS
79.
80. ;-----------------------------------------------------------------
-------------
81. ;Definicion del segmento de pila
82. ;-----------------------------------------------------------------
-------------
83. PILA SEGMENT STACK "STACK"
84. db 40h DUP(0)
85. PILA ENDS
86.
87. ;-----------------------------------------------------------------
-------------
88. ;Definicion del segmento de codigo
89. ;-----------------------------------------------------------------
-------------
90. CODE SEGMENT
91. assume cs:code,ds:datos,ss:pila
92.
93. START PROC
94. ;Inicializamos los registros de segmento
95. mov ax,datos
96. mov ds,ax
97. mov ax,pila
98. mov ss,ax
99.
100. push ds
101. pop es
102. cld
103. mov ax,4C00h
104. lea di,texto
105. mov cx,14h
106. repnz scasb
107.
108. mov ax,4C00h ;
109. int 21h ;Terminar el programa
110.
111. START ENDP
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 ax,4C00h ;
int 21h ;Terminar el programa

START ENDP

CODE ENDS
END START

Hallar el valor de AX tras la instrucción mov al,byte ptr tabla[si]:


;---------------------------------------------------------------------
---------
;Definicion del segmento de datos
;---------------------------------------------------------------------
---------
DATOS SEGMENT
db 10,'A',32,45h,10001101b,16
tabla dw 15,'Dk','27',4F5h
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
mov ax,pila
mov ss,ax

xor si,si
mov ax,[si]
sub ax,[si]
mov al,byte ptr tabla[si]

mov ax,4C00h ;
int 21h ;Terminar el programa

START ENDP

CODE ENDS
END START

Instrucción JMP

Propósito: Salto incondicional


Sintaxis:

JMP destino

Esta instrucción se utiliza para desviar el flujo de un programa sin tomar en


cuenta las condiciones actuales de las banderas ni de los datos.

Instrucción JA (JNBE)

Propósito: Brinco condicional

Sintaxis:

JA Etiqueta

Después de una comparación 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).

Instrucción JAE (JNB)

Propósito: 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.

Instrucción JB (JNAE)

Propósito: salto condicional

Sintaxis:

JB etiqueta

Salta si está abajo o salta si no está arriba o si no es igual.


Se efectúa el salto si CF esta activada.

Instrucción JBE (JNA)

Propósito: salto condicional

Sintaxis:

JBE etiqueta

Salta si está abajo o si es igual o salta si no está arriba.

El salto se efectúa si CF está activado o si ZF está activado (que cualquiera sea


igual a 1).

Instrucción JE (JZ)

Propósito: salto condicional

Sintaxis:

JE etiqueta

Salta si es igual o salta si es cero.

El salto se realiza si ZF está activada.

Instrucción JNE (JNZ)

Propósito: salto condicional

Sintaxis:

JNE etiqueta

Salta si no es igual o salta si no es cero.

El salto se efectua si ZF está desactivada.

Instrucción JG (JNLE)

Propósito: salto condicional, se toma en cuenta el signo.


Sintaxis:

JG etiqueta

Salta si es más grande o salta si no es menor o igual.

El salto ocurre si ZF = 0 u OF = SF.

Instrucción JGE (JNL)

Propósito: salto condicional, se toma en cuenta el signo.

Sintaxis:

JGE etiqueta

Salta si es más grande o igual o salta si no es menor que.

El salto se realiza si SF = OF

Instrucción JL (JNGE)

Propósito: 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 efectúa si SF es diferente a OF.

Instrucción JLE (JNG)

Propósito: salto condicional, se toma en cuenta el signo.

Sintaxis:

JLE etiqueta

Salta si es menor o igual o salta si no es más grande.

El salto se realiza si ZF = 1 o si SF es diferente a OF


Instrucción JC

Propósito: salto condicional, se toman en cuenta las banderas.

Sintaxis:

JC etiqueta

Salta si hay acarreo.

El salto se realiza si CF = 1

Instrucción JNC

Propósito: salto condicional, se toma en cuenta el estado de las banderas.

Sintaxis:

JNC etiqueta

Salta si no hay acarreo.

El salto se efectúa si CF = 0.

Instrucción JNO

Propósito: 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.

Instrucción JNP (JPO)

Propósito: salto condicional, toma en cuenta el estado de las banderas.

Sintaxis:

JNP etiqueta
Salta si no hay paridad o salta si la paridad es non.

El salto ocurre si PF = 0.

Instrucción JNS

Propósito: salto condicional, toma en cuenta el estado de las banderas.

Sintaxis:

JNP etiqueta

Salta si el signo esta desactivado.

El salto se efectúa si SF = 0.

Instrucción JO

Propósito: salto condicional, toma en cuenta el estado de las banderas.

Sintaxis:

JO etiqueta

Salta si hay desbordamiento (overflow).

El salto se realiza si OF = 1.

Instrucción JP (JPE)

Propósito: salto condicional, toma en cuenta el estado de las banderas.

Sintaxis:

JP etiqueta

Salta si hay paridad o salta si la paridad es par.

El salto se efectúa si PF = 1.

Instrucción JS

Propósito: salto condicional, toma en cuenta el estado de las banderas.


Sintaxis:

JS etiqueta

Salta si el signo está prendido.

El salto se efectúa si SF = 1.

Instrucción LOOP

Propósito: Generar un ciclo en el programa.

Sintaxis:

LOOP etiqueta

La instrucción loop decrementa CX en 1, y transfiere el flujo del programa a la


etiqueta dada como operando si CX es diferente a 1.

Instrucción LOOPE

Propósito: Generar un ciclo en el programa considerando el estado de ZF

Sintaxis:

LOOPE etiqueta

Esta instrucción 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.

Instrucción LOOPNE

Propósito: Generar un ciclo en el programa, considerando el estado de ZF

Sintaxis:

LOOPNE etiqueta

Esta instrucción decrementa en uno a CX y transfiere el flujo del programa solo


si ZF es diferente a 0.

Instrucción DEC
Propósito: Decrementar el operando

Sintaxis:

DEC destino

Esta operación resta 1 al operando destino y almacena el nuevo valor en el


mismo oeprando.

Instrucción INC

Propósito: Incrementar el operando.

Sintaxis:

INC destino

La instrucción suma 1 al operando destino y guarda el resultado en el mismo


operando destino.

Instrucción CMP

Propósito: Comparar los operandos.

Sintaxis:

CMP destino, fuente

Esta instrucción resta el operando fuente al operando destino pero sin que éste
almacene el resultado de la operación, solo se afecta el estado de las banderas.

Instrucción CMPS (CMPSB) (CMPSW)

Propósito: Comparar cadenas de un byte o palabra.

Sintaxis:

CMP destino, fuente

Con esta instrucción la cadena de caracteres fuente se resta de la cadena destino.

Se utilizan DI como indice para el segmento extra de la cadena fuente y SI como


indice de la cadena destino.
Solo se afecta el contenido de las banderas y tanto DI como SI se incrementan.

Instrucción CLC

Propósito: Limpiar bandera de acarreo.

Sintaxis:

CLC

Esta instrucción apaga el bit correspondiente a la bandera de acarreo, o sea, lo


pone en cero.

Instrucción CLD

Propósito: Limpiar bandera de dirección

Sintaxis:

CLD

La instrucción CLD pone en cero el bit correspondiente a la bandera de


dirección.

Instrucción CLI

Propósito: Limpiar bandera de interrupción

Sintaxis:

CLI

CLI pone en cero la bandera de interrupciones, desabilitando así aquellas


interrupciones enmascarables.

Una interrupción enmascarable es aquella cuyas funciones son desactivadas


cuando IF = 0.

Instrucción CMC

Propósito: Complementar la bandera de acarreo.

Sintaxis:
CMC

Esta instrucción complementa el estado de la bandera CF, si CF = 0 la


instrucción la iguala a 1, y si es 1 la instrucción la iguala a 0.

Podemos decir que unicamente "invierte" el valor de la bandera.

Instrucción STC

Propósito: Activar la bandera de acarreo.

Sintaxis:

STC

Esta instrucción pone la bandera CF en 1.

Instrucción STD

Propósito: Activar la bandera de dirección.

Sintaxis:

STD

La instrucción STD pone la bandera DF en 1.

Instrucción STI

Propósito: Acticar la bandera de interrupción.

Sintaxis:

STI

La instrucción activa la bandera IF, esto habilita las interrupciones externas


enmascarables (las que funcionan unicamente cuando IF = 1 ).
Ejercicio 1: Escribir un código que verifique si dos cadenas son iguales

org 100h
comienzo:
mov si, x
mov al, msg2[si]
cmp msg[si], al ;comparar letra por letra las cadenas, si uno no coincide
manda directamente a fin y termina el programa
jne fin:
cmp msg[si], "$" ;si es el final y el programa llega aca, quiere decir
que son iguales
jz final:
inc x
loop comienzo
final:
mov dx, offset msg3
mov ah, 9
int 21h
fin:
ret
msg db "hello world $"
msg2 db "hello world $"
msg3 db "Son iguales $"
x dw 0

Ejercicio 2: Escribir un código que verifique si una cadena es subcadena de otra.

Por ejemplo: “la Mu” es subcadena de “Hola Mundo”.

La cadena: “233″ es subcadena de la cadena “2122432234″

org 100h
mov si, 0 ;ponemos si en 0
comienzo:
mov al, msg2[0] ;copiar la primera letra de la palabra a al
cmp msg[si],"$" ;si es el fin de la cadena mandar a final
jz final
cmp msg[si], al ;comparar si encuentra la primera letra de la cadena
jne seguir

mov di, 1 ;poner en 1 di


comprobar:
mov al, msg2[di]
mov bx, di
cmp msg[si+bx], al ;posicion de la letra coincidente + di, comparar con
la cadena
jne seguir ;si no coincide mandar a seguir

inc di ;incrementar di para seguir recorriendo cadena

cmp msg2[di],"$" ;si es el fin de la cadena y el programa llego aca


quiere decir que la cadena es parte de la palabra
jz resultado

loop comprobar ;bucle para recorrer cadena


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 código 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 dígitos, 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 número 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

Ejercicio 6: Escribir un programa que tome tres cadenas, la primera y la tercera


representan un número y la segunda una operación, por ejemplo: “329″, “-”, “21″ e
imprima el resultado “308″

org 100h ; inicio de programa


include 'emu8086.inc' ;Incluye funciones de libreria emu8086
; DEFINE_SCAN_NUM
; DEFINE_PRINT_STRING
DEFINE_PRINT_NUM
DEFINE_PRINT_NUM_UNS
mov si, 0
mov al, 0
;Convertir primera cadena a numero
cadAnum:
cmp cad1[si], "$"
jz seguir

mov bl, 10
mul bl
sub cad1[si], '0'
add al, cad1[si]

inc si
loop cadAnum

seguir:
mov aux1, al
;Convertir segunda cadena a numero
mov si, 0
mov al, 0
cadAnum2:
cmp cad3[si], "$"
jz seguir2

mov bl, 10
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: $"

Ejercicio 7: Escribir un programa que imprima X en la pantalla hasta que se presiones


ESC.

name "keybrd"
org 100h
; print a welcome message:
mov dx, offset msg
mov ah, 9
int 21h
;============================
; 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

Ejercicio 8: Escribir un programa que ordene un vector de mayor a menor.

name "arreglo-mayor"
org 100h
mov cx, 8
bucle1:
mov c, cx

mov bx, cx
mov cx, 9

bucle2:
mov si, cx
mov ah, v[si-1]
cmp ah,v[bx-1]
jnge seguir ;Si v[8] < v[7] no hacer nada, sino:
mov dh, v[bx-1] ;Copiar v[7] en dh
mov dl, v[si-1] ;Copiar v[8] en dl
mov v[bx-1], dl ;Copiar dl en v[7]
mov v[si-1], dh ;Copiar dh en v[8]
seguir:
loop bucle2

mov cx, c
loop bucle1
ret
v db 2,32,64,32,98,12,5,21,91
c dw 0

Ejercicio 9: Escribir un programa que halle el MCM Y MCD

; Programa que calcula el MCD y MCM de dos numeros decimales (soporta


numeros de 8 bits o 1 byte)
mov cont,1 ;inicializar variable cont en 1
bucle:
mov ah,0
mov al,cont
mov bl,nro1
div bl
cmp ah,0 ;si el resto de la division del contador con el nro1 es igual 0
je parte1
bc:
inc cont ;incrementar el contador
jmp bucle ;bucle hasta que encuentre el MCM

parte1: ;si nro1 es multiplo del contador


mov ah,0
mov al,cont
mov bl,nro2
div bl
cmp ah,0 ;compara si el resto de la division del contador con el nro2 es
0
je parte2
jmp bc ;si el nro2 no es multiplo del contador regresa a bucle1
parte2: ;si el nro1 y el nro2 son multiplos del contador
mov al,cont
mov MCM,al ;guarda el MCM
jmp parte3 ;ir a final

parte3: ;una vez que tengamos el MCM primero multiplicar nro1 * nro 2
mov al, nro1 ;con ese resultado, dividir por el MCM de nro1 y nro2 y
tenemos el MCD
mov bl, nro2
mul bl
mov bl, MCM
div bl
mov MCD, al
ret ;fin del programa
cont db 0 ;cont = contador
MCM db 0 ;en esta variable se guarda el MCM
MCD db 0 ;en esta variable se guarda el MCD
nro1 db 48 ;numero1 decimal
nro2 db 60 ;numero2 decimal

Ejercicio 10: Escribir un programa que dibuje una diagonal en la pantalla.

mov cx,1
mov al, 13h
mov ah, 0
int 10h ; set graphics video mode.

bucle1:
mov dx, cx
mov al, color ;AL = pixel color
mov ah, 0ch ;Change color for a single pixel
int 10h ;set pixel

cmp cx, 101 ;llegar hasta 100 x 100 (va en diagonal)


jz fin

inc cx ;DX = row.


add color, 2 ;para cambiar colores
jmp bucle1 ;CX = column
fin:
ret
color db 1

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
cmp ax, 0 ;ax queda en 0 cuando llega a EOF
jz FIN ;si es 0 entonces va a fin para cerrar archivo

;Detectar palabras que terminan con a


mov dl, leido[0]

cmp dl, " " ;comparar si es espacio


jz mostrar ;si es espacio entonces ir a mostrar

jmp abajo ;si no es espacio entonces ir a abajo

mostrar:
cmp aux, "a" ;compara si el anterior es a
jnz abajo

inc cont ;si es a entonces incrementar contador

abajo:
mov aux, dl ;guardar en aux lo que hay en dl para comparar en la proxima
vuelta
jmp leer

FIN:

;cerramos archivo
mov bx, handle
mov ah, 3eh
int 21h

ret

archivo db "C:\prueba.txt", 0 ;ascii del nombre del archivo


leido db "$"
handle dw ? ;identificador del arhivo
aux db "$"
cont db 0