C U R S O D E A S S E M B L E R = = = = = = = = = = = = = = = = Clase Nro: 3. Lamberti Ricardo J. Tema : Assembler 4:902/13.9 ASSEMBLER (1§Parte) ============================================================================= -------------------------------------------- Los registros de segmentos y la programacion -------------------------------------------- Como hemos dicho, el 8088 tiene cuatro registros de direccionamiento que tienen una importancia fundamental en la ejecucion de programas. Un programa consiste en un codigo que operan sobre unos datos. Una programaci˘n cuidadosa separa los datos del codigo. Y para hacer esto el 8088 pone los codigos y los datos en diferentes segmentos. Por este motivo necesita una direccion de segmento y tambien un registro de segmento para cada uno. El procesador asigna a cada registro un significado determinado. CS: El registro CS determina el segmento que contiene el codigo del programa que se esta ejecutando. El cambiarlo no producira otra cosa que un salto a otro segmento en la ejecucion, en una instruccion de salto no sucede otra cosa. El compa¤ero de CS que ofrece la direccion dentro del segmento es IP. Luego de que cada instruccion es accedida el procesador incrementa IP y lo deja apuntando a la siguiente instruccion. DS: El registro DS se utiliza para el acceso a los datos, el contenido del registro DS es el segmento que se toma cuando se hace referencia a una direccion sin especificar segmento (excepto con IP, SP, BP y algunas instrucciones que predeterminan para sus parametros un registro de segmento especial (Ej: MOVS )) SS: Cada programa tiene asociada una pila (stack), que no esta en otro lugar que la memoria, y tambien necesita de una direccion que refiera al ultimo dato apilado. Esta direccion necesita un segmento y un offset como hemos visto. SS es el segmento y SP es el offset (ocasionalmente tambien se utiliza BP). Es necesaria que los codigos en assembler tengan definida una pila, pues esta es utilizada por muchas instrucciones (Por ejemplo: CALL). Los lenguajes de alto nivel la utilizan para el pasaje de parametros entre procedimientos. ES: Este registro es libre a la utilizacion que quiera darle el programador, generalmente se utiliza como socio a DS, cuando se quiere copiar datos de diferente segmento, DS apunta al segmento origen y ES al segmento destino. --------------------------- Primeros pasos en Assembler --------------------------- Antes de explicar algunas instrucciones, observemos como el procesador ve las instrucciones. Las instrucciones se encuentran en memoria, son tan solo un numero, si se observa no se veria deferencia entre el codigo, datos y basura. El procesador tampoco puede saberlo, confia simplemente que en el lugar apuntado por CS:IP hay una instruccion. Por esta razon, si el CS:IP tienen valores erroneos la maquina se colgara seguramente. Los pasos a realizar por el procesador son: 1) Buscar la instruccion apuntado por CS:IP 2) Buscar sus operandos 3) Ajustar CS:IP a la proxima instruccion 4) Ejecutar instruccion 5) Volver al paso 1 para la instruccion siguiente. Observece que las instruciones de salto solo deben modificar CS:IP para provocar una bifurcacion del programa. ----- Debug ----- Para probar las instrucciones utilizaremos el Debug que viene con el sistema operativo. Al ingresar al Debug les aparecera un guion, ese es el prompt del debug, esta listo a recibir instrucciones. con ? recibiran una lista de los comandos disponibles. Con R(Registros) pueden pedir el estado del procesador, esto les mostrara el valor de los registros y las banderas. Ademas de la decodificacion de la instruccion apuntada por CS:IP. Obviamente, ya que todavia no ingresamos nuestro codigo, CS:IP esta apuntando a basura, por lo tanto, si damos la instruccion G (Ejecutar) ejecutaremos cualquier basura que alla. Con A ingresamos nuestro codigo, y luego podremos ejecutarlo paso a paso con P (Procesar) o T (Paso a Paso). Con U (Desensamblar) podremos ver como va quedando y con R seguido de un registro podremos cambiar el valor de este. Bueno probemos esto: A MOV ax, 10 R P Si quieren volver a ejecutarlo tendran que volver a apuntar a IP a la direccion de la instruccion MOV, haganlo con R IP e ingresen el offset de la instruccion MOV. (si no se lo acuerdan usen U 100) La mejor forma de aprender es la experimentacion asi que vayan probando las instrucciones que explicare a continuacion. Si usan G (Go), porque hicieron un codigo de muchas lineas, deberan avisarle al programa que termina, esto se hace llamando a un servicio del Sistema Operativo, ampliaremos sobre esto mas adelante, por ahora agregen al final estas dos lineas MOV AX, 4C00h INT 21 --------------------- Instrucciones Basicas --------------------- Como todavia no explicamos modos de direccionamiento, esta sera una descripcion informal sobre algunas de las instrucciones del set de instrucciones de 8086. Instrucciones de transferencia ------------- -- ------------- MOV Destino, Fuente (transferencia) Destino <- Fuente (<- Asignacion) Esta instruccion esta optimizada si se usa AX. Destino y fuente pueden ser de 8 bits o 16 bits, No se permiten transferencias de memoria a memoria. Si el destino es un segmento, Fuente debe ser un registro (es decir MOV ES, 2F45h no se puede) Si se quiere hacer eso, debe moverse el valor a un registro y luego copiarse al de segmento. En el ejemplo anterior: MOV AX, 2F45 MOV ES, AX La operacion MOV ES:[0300], 34 es valida, no es valido hacer MOV 1234:[0300], 34, debe primero cargarse el valor en un registro de segmento y luego moverse el valor. MOV AX, 1234 MOV ES, AX MOV ES:[0300], 34 EJ: MOV AX, BX MOV AX, 10F4 (si lo prueban en debug a los hexadecimales no se le pone la h caracteristica 10F4h) MOV AL, [400] ( Mueve a AL el contenido de la direccion DS:0400, para ponerle un valor con DEBUG use E 400, y D 400 para mirar como quedo) PUSH Origen (Apilar) SP <- SP - 2 [SS:SP] <- Origen ([direc] la celda apuntada por direc) Apila un elemento en la pila. Origen NO puede ser de 8 bits. Puede ser un registro o una direccion de memoria. Ej: PUSH CX PUSH ES POP Origen (Desapilar) Origen <- [SS:SP] ([direc] la celda apuntada por direc) SP <- SP + 2 Desapila un elemento en la pila. Origen NO puede ser de 8 bits. Puede ser un registro o una direccion de memoria. Ej: POP CX POP ES Instrucciones Matematicas ------------- ----------- ADD Destino, Fuente (Suma) Destino <- Destino + Fuente Operacion optimizada para AX Destino y Fuente pueden ser de 8 o 16 bits, pero ambos del mismo tama¤o, es decir NO se puede MOV AL, BX. No se permiten operaciones de memoria a memoria. Ej: ADD AX, 10 ADD AL, BL ADD AL, ES:[400] SUB Destino, Fuente (Resta) Destino <- Destino - Fuente Idem a ADD MUL Origen (Multiplicacion sin signo) Si origen es Byte ( 8 bits) AX <- origen * AL Si origen es Word (16 bits) DX:AX <- origen * AX ( ':' concatenacion, NO esta usado en el mismo sentido que las direcciones de memoria. Ej: 1234:5678 = 12345678) Origen puede ser de 8 o 16 bits (byte o Word), y ser un registro o una direccion de memoria EJ: MUL BX MUL BL MUL BYTE PTR [400] (Observece que el procesador no puede determinar si [400] es una referencia a un Word o un byte entonces se aclara anteponiendo BYTE PTR (puntero a Byte. Si fuera un Word seria WORD PTR) IMUL Origen (Multiplicacion con signo) Idem a MUL pero se toma a los operandos como complementados a dos (invertido y sumado 1). El resultado esta dado en complemento a dos. (Mas adelante incluiremos una explicacion de notacion hexadecimal y representacion de numeros negativos, punto fijo y flotante) DIV Origen (Division sin signo) Si origen es Byte ( 8 bits) AL <- AX / Origen AH <- resto Si origen es Word (16 bits) AX <- AX:DX / Origen DX <- resto Origen puede ser de 8 o 16 bits (byte o Word), y ser un registro o una direccion de memoria EJ: DIV BX DIV BL DIV BYTE PTR [400] IDIV Origen (Division con signo) Idem a DIV pero se toma a los operandos como complementados a dos. El resultado esta dado en complemento a dos. INC Destino (Incremento) Destino <- Destino + 1 Destino puede ser un byte o un word. Puede ser un Registor o una direccion de memoria. Ej: INC AX INC WORD PTR [400] INC DL DEC Destino (Decremento) Destino <- Destino - 1 Destino puede ser un byte o un word. Puede ser un Registor o una direccion de memoria. Ej: DEC CX DEC WORD PTR ES:[400] DEC CL --------------------------------------------------------------------------- Practica N§2- Debug (Todos lo numeros en hexadecimal) 1.- De la instruccion correspondiente ___________________________________________________ | PseudoInstruccion | Instrucciones | |_____________________|_____________________________| |a) AX<-45 | | |b) AX<-AX+45 | | |c) CL<-CL-2 | | |d) AX<-AX+1 | | |e) CX<-BX+45 | | |f) DX:AX<-BX*45 | | |g) Apilar AX | | |h) Desapilar en CX | | |i) DS<-3556 | | |j) AX<-DS:[DI] | | |k) AL<-DS:[DI] | | |l) AX<-0020:[DI] | | |m) AL<-0020:[DI] | | |n) DS:[DI]<-34 | | |¤) DS:[DI]<-3456 | | --------------------------------------------------- 2.- Dar la pseudoinstruccion de las siguientes instrucciones: ----------------------------------------------------------- | Instruccion | PseudoInstruccion | |---------------------------|------------------------------| | a) MOV DI, 4 | | | b) INC SI | | | c) MOV BX, AX | | | d) ADD AX, DI | | | e) DEC DI | | | f) PUSH AX | | | g) POP ES | | | h) MOV byte ptr [200], 23 | | | i) MOV word ptr [200], 23 | | ---------------------------------------------------------- 3.- Realice la siguiente operacion: A = (B*C)+5)/9 siendo A, B y C punteros a byte consecutivos en el offset 200h: |........| DS:0200 A |___00___| DS:0201 B |___12___| DS:0202 C |___54___| |........| | | Tipee el codigo con el debug ("A") y terminelo con MOV AX, 4C00 INT 21 Ejecutar con G o con P. 4.- DOS guarda el tama¤o de la memoria convencional en la posicion de memoria 0000:0413. Amplie su memoria convencional a FFFh. ------------------------------------------------------------------------- RESPUESTAS 1.- a) MOV AX, 0045 b) ADD AX, 0045 c) SUB CL, 2 d) INC AX e) MOV CX, BX ADD CX, 45 (hay otras maneras) f) MOV AX, BX MOV CX, 45 MUL CX g) PUSH AX h) POP CX i) MOV AX, 3556 MOV DS, AX j) MOV AX,DS:[DI] k) MOV AL,DS:[DI] l) MOV AX, 0020 MOV DS, AX MOV AX, DS:[DI] m) MOV AX, 0020 MOV DS, AX MOV AL, DS:[DI] n) MOV BYTE PTR DS:[DI],34 ¤) MOV WORD PTR DS:[DI],3456 2.- a) DI <- 4 b) SI <- SI + 1 c) BX <- AX d) AX <- AX + DI e) DI <- DI - 1 f) SP <- SP - 2 [SS:SP] <- ES g) AX <- [SS:SP] SP <- SP + 2 h) [200]<- 23 i) [200]<- 0023 (es decir el lugar [200] queda igual a 23 y [201] igual a 00) 3.- E 200 00 12 54 A MOV CL, [202] ; CL<- [202] MOV AL, [201] ; AL<- [201] MUL CL ; AX<- CL * AL ADD AX, 5 ; AX<- AX + 4 MOV BL, 9 ; BL<- 9 DIV BL ; AL<- AX / BL MOV [200], AL ; [200]<-AL MOV AX,4C00 INT 21 G o P 4.- A MOV AX, 0 MOV ES, AX MOV WORD PTR ES:[413], FFF MOV AX, 4C00 INT 21 G ----------------------------------------------------------------------------- Proxima entrega: Instrucciones Logicas. Labels. Instrucciones comparativas y de saltos. Bibliografia: PC Interno, Michel Tischer. y apuntes varios de la catedra de Arquitectura I de la UNLP, Turbo assembler, Manual del usuario. -----------------------------------------------------------------------------