C U R S O D E A S S E M B L E R = = = = = = = = = = = = = = = = Clase Nro: 2. Lamberti Ricardo J. Tema : Hardware 4:902/13.9 INTRODUCCION (2§ Parte) ============================================================================= ------------- El Procesador ------------- El procesador se encarga de ejecutar las instrucciones. Estas instrucciones estan codificadas en Codigo de Maquina, el cual, es el unico lenguaje que entiende la maquina. El C, BASIC, PASCAL y aun el ASSEMBLY requieren otros programas traductores que transformen los codigo hechos por el usuario a codigo de maquina. El ASSEMBLY (ASSEMBLER es el compilador ASSEMBLY es el lenguaje) es el lenguaje que mas cerca esta del codigo de maquina, la mayor parte de la traduccion se basa en traducir siglas nemotecnicas en codigo. Las instrucciones de maquina no son iguales en todos los procesadores Sin embargo, los miembros de la familia 80xxx trabajan con el mismo lenguaje lo que permite que sean compatibles. Es ta compatibilidad es solo ascendente. Ya que cada nueva generaci˘n agrega instrucciones. Los Registros del procesador ---------------------------- En el coraz˘n de los procesadores se encuentran los registros, estos son "las variables de hardware", un procesador tiene muchos registros y algunos pueden ser accedidos por los usuarios. Los registros son lugares de almacenamiento de informaci˘n, que tienen la ventaja de estar emplazados en el mismo procesador, de tal forma que su acceso es directo y no debe pasar antes por el bus. Ademas de la velocidad, los registros son el medio utilizado para pasar informacion a las funciones de BIOS y del DOS. Los registros pueden dividirse en cuatro grupos: registros generales, registros de segmento, contadores de programas, y registros de banderas. ----------------------------------------------------------------------------- Registro en Modo Real registros generales 1 5 87 0 -------------- |......AX......| Accumulador |__AH__||__AL__| |......BX......| Base |__BH__||__BL__| |......CX......| Count |__CH__||__CL__| |......DX......| Data |__DH__||__DL__| |______DI______| Destination index |______SI______| Source index |______SP______| Stack Pointer |______BP______| Baser Pointer registros de segmento ______________ |______DS______| Segmento de datos |______ES______| Segmento extra |______CS______| Segmento codigo |______SS______| Segmento de pila (stack) Contador de programa _______________ |______IP_______| Instruction Pointer Flag Register _______________________________ |_|_|_|_|O|D|I|T|S|Z|_|A|_|P|_|C| FIG 1: REGISTROS EN MODO REAL ----------------------------------------------------------------------------- Los registros generales Los registros generales se utilizan para la mayoria de las operaciones aritmeticas, ellos son AX, BX, CX, DX. Estos registros tienen 16 bits cada uno, es decir pueden representar valores desde 0 a 65535. Tambien se puede acceder en forma separada a los primeros 8 bits o a los ultimos 8. Esto es se llaman parte baja (low) y alta (high) del registro. Y se denominan AL (la parte baja) y AH (la parte alta). Observese que si se cambia el bit 4 de AH, se modifica tambien el bit 12 de AX. Los nombres que aparecen en la figura N§1, Acumulador, Count, etc. tienen que ver con cierta especializacion que tiene cada uno de los registros. Por estar ligados directamente con la forma de operar del procesador algunos registros estan dise¤ados de tal forma que algunas operacion funcionan con solo uno de ellos. Por ejemplo, CX el contador, es usado por funciones como LOOP que toman su valor y lo decrementan mientras no sea cero. Assembler Pseudocodigo MOV CX, 10 CX = 10 ciclo: ciclo: .... ... ...;codigo repetitivo ... .... ... LOOP ciclo CX = CX - 1 IF (CX>0) THEN GOTO CICLO Observese que realmente CX se esta usando como contador en forma implicita. Mas adelante haremos una explicacion detallada de la correcta utilizacion de cada registro. El registro de banderas El registro de banderas sirve para la comunicacion entre instrucciones consecutivas en lenguaje de maquina. Almacenan el estado de la ultima operacion aritmetico/logica realizada. ---------------------------------------------------------------------- _______________________________ |_|_|_|_|O|D|I|T|S|Z|_|A|_|P|_|C| O = Overflow Flag D = Direction Flag I = Interruption Flag T = Trap Flag S = Sign Flag Z = Zero Flag A = Auxiliary Flag P = Parity Flag C = Carry Flag Figura N§2: Banderas ----------------------------------------------------------------------- Explicare muy por arriba como funciona. Cuando sumamos por ejemplo dos registros de 16 bits: ADD AX,BX ;Pseudo :AX=AX+BX si el resultado es mayor que 65535 entonces no puede almacenarse en AX conclusion la maquina pierde los bits sobrantes e informa poniendo en 1 la bandera de desborde (Overflow Flag). Si el resulatado es un numero negativo, la bandera de signo se pone en 1, si es cero se activa la bandera de cero. A su vez hay instrucciones que de acuerdo al estado de las banderas hacen una cosa u otra. Por ejemplo: JNZ (Jump no zero) produce un salto a otra instruccion si el flag zero esta desactivado. Repitamos nuevamente el codigo anterior, pero esta vez sin usar LOOP. Assembler Pseudocodigo MOV CX, 10 CX = 10 ciclo: ciclo: ... ... ... ... ... ... DEC CX CX = CX - 1 JNZ ciclo IF CX<>0 THEN GOTO ciclo Cuendo el CX llegue a valer 1 el decrementarlo (DEC CX) producira como resultado 0, esto pondra en 1 el flag zero. entonces la operacion no se ejecutara y el programa seguira su curso sin saltar. Los registros de segmento y las direcciones de memoria Un paso muy importante en el aprendizaje del assembler es conocer la forma en que el CPU construye las direcciones de memoria. El 8088 y sus sucesores lo hace de una manera realmente complicada que solo pude entenderse teniendo en cuenta la historia del 8086. En aquel entonces se trataba de hacer un procesador que superara los 64K y elevarse por encima de la competencia (Z80, 6502 que son de 8bits) Los constructores del 8086 se pusieron una meta ambisiosa llegar a lo 20bits es decir 1Mbyte de memoria. El numero de direcciones al cual puede accederse en un procesador depende de un registro especial, el registro de direcciones. Este registra la direccion del punto de memoria cada vez que accede de la misma, que esta en el reticulado del CPU. A cada punto de la memoria le corresponde su propio numero (direccion) es sucesion ascendente, el cual le permite acceder a estos puntos, por este motivo el numero de cifras representables en el registro de direcciones es el que define el numero de puntos de memorias diferentes al cual pude dirigirse Esto es igual en el bus de direcciones que tambien tiene que cumplir este requisito. El registro de direcciones del 8086 tenia 16 bits de ancho. Por lo tanto, podia registrar un valor de 0 a 65535 (o sea en total 65536 direcciones de memoria) es decir, 64 Kbytes. Para acceder a 1Mbyte se necesitaba un registro de direcciones considerablemente mas ancho 20 bits. Con el estado de la tecnica en aquel momento esto no era posible, apenas recien habian alcanzado los 20 bits. Para ello se unieron dos direcciones de 16 bits de forma tal que resultara una de 20. Union de direcciones segmento y offset La primera de las dos direcciones se toma de uno de los cuatro registros de segmento. El 8086 permite que la otra provenga de otro registro o un punto de memoria. Estas dos direcciones no pueden sumarse directamente ya que obtendriamos como maximo un numero de 17 bits. Lo que se hace es multiplicar por 16 (desplazar 4 bits) a la primera direccion y luego sumarle la otra sin desplazar. 19 15 . . 4 3 2 1 0 bit _______________________________________ Direccion Logica |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|0|0|0|0| Direc. Segmento + 15 . . 4 3 2 1 0 bit _______________________________ |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| Direc. Offset __________________________________________________ 19 15 . . 4 3 2 1 0 bit _______________________________________ Direccion Fisica |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| Para referenciar a cada direccion se llama segmento a la direccion a la cual se le aplica el desplazamiento y offset a la que se agrega luego. A esto se deba a que los registros ES, DS, CS, SS se llamen de segmento porque son ellos los que proveen el segmento. Redondeando la idea, para conseguir una direccion de memoria se debe desplazar cuatro lugares el segmento y completar con cero, luego sumar el offset. Segmento * 16 + offset = Direccion Fisica La idea es simple pero tiene implicancias insospechadas: Si tenemos el segmento igual a 0 y el offset igual a 0 entonces estamos en la direccion de memoria fisica 0, pero si sumamos 1 al segmento no nos moveremos a la direccion de memoria fisica 1, sino a la 16. 1 * 16 + 0 = 16 Si se continua incrementando el segmento se pasara a 32, 48, 60, etc. Siempre y cuando la direccion de offset siga siendo 0. Siguiendo este metodo la direccion 1Mbyte se alcanzara cuan el segmento alcance el valor 65535 (FFFF en hexadecimal). Si en cambio se mantiene constante el segmento y se incrementa el offset. Se denota que el registro de segmento funciona como registro base, y el offset no es mas que el desplazamiento desde ese punto hasta 65536 puntos de memoria diferentes (64Kbytes). Conclusion el offset representa la distancia desde el punto deseado de memoria al principio del semgento. Debido a que los diferentes segmentos de memoria estan separados 16bytes unos de otros, pero cada uno recoge 64Kb (parado en un segemento puedo llegar hasta 64 KB de el aumentando el offset), esta claro que dentro de la memoria se superponen unos a otros. La direccion de memoria 130 puede expresarse de muchas maneras en funcion del segmento y el offset: segmento = 1 offset = 114 1 * 16 + 114 = 130 segmento = 2 offset = 98 2 * 16 + 98 = 130 y asi sucesivamente Esta superposicion no tiene que confundirnos, ya que al introducir una direcion se puede elegir la combinacion de segmento y offset que se desee. La notacion utilizada para representar una direccion de memoria es el segmento seguido del offset separados con dos puntos y los numeros expresados en un hexadecimal de 4 digitos. segmento: 2000h offset AF3h direccion: 2000:0AF3h Punteros Near y Far Lo que aqui se conoce como direccion de memoria, en los lenguajes de alto nivel se denominan punteros. Los punteros no son otra cosa que las direcciones de memoria de los objetos que apuntan. Sin embargo, se hace la diferencia entre puntero "near" y "far". Los punteros "near" solo indican el offset de un objeto, por lo que tienen 16 bits de ancho. Ya que sin la direccion de segmento no se puede acceder a la memoria, el compilador proporciona el segmento al acceder al objeto en cuestion. Por el contrario, los punteros tipo "far", consisten en la direccion de segmento y offset, y se salva en dos palabas de 16bytes cada una. Tipos de datos y su forma de almacenamiento Los bytes y los words (palabras) no son los unicos datos que se manejan en la programacion en assembler, se utilizan tambien los DWords, QWords, etc. Los miembros de la familia 80xxx almacenan los datos en memoria de forma tal que la parte menos significativa quede adelante que la mas significativa. ________________ |Lo-Byte|Hi-Byte | Word ________________________________ |Lo-Word |Hi Word | DWord ________________________________ |Offset |Segmento | FAR-PTR _______________________________________________________________ |Lo-Dword |Hi-DWord | Qword Ejemplos: El Word A345h se guarda como FFFF:000F ____________ | | ....... |____________| ^ |_____A3_____| | |_____45_____| | | | | ............ 0000:0000 |____________| El DWord DEF3A345h se guarda como FFFF:000F ____________ | | ....... |____________| |_____DE_____| ^ |_____F3_____| | |_____A3_____| | |_____45_____| | | | ............ 0000:0000 |____________| El QWord AE35E30FDEF3A345h se guarda como FFFF:000F ____________ | | ....... |____________| |_____AE_____| |_____35_____| ^ |_____E3_____| | |_____0F_____| | |_____DE_____| | |_____F3_____| | |_____A3_____| | |_____45_____| | | ............ 0000:0000 |____________| Comunicaciones con el Hardware -------------- --- -- -------- La comunicacion entre los programas y el hardware, es decir los chips de soporte se hace atraves de los ports. Como port uno tiene que imaginarse una entrada o salida de 8 o 16 bits de ancho, que se identificara por una direccion de 0 a 65535. Este autoriza el registro a las diferentes unidades de hardware. Acceso a los puertos Para la comunicacion con los ports la CPU utiliza el bus de datos y direcciones y se comporta de manera muy similar al acceso a memoria. En primer lugar el CPU manda una se¤al mediante una conexion especial al bus, para que todos los dispositivos conectados sepan que no se va ha dirigir a un punto de memoria sino a un Port. Seguidamente coloca la direccion del port en los 16 bits inferiores del bus de direcciones y espera a que uno de los dispositivos se de por aludido y responda al llamado. Una vez, que responde se envian los datos atraves del bus de datos. En direccion contraria, se actua en forma muy similar, exepto que el datos lo manda la tarjeta de ampliacion hacia el CPU. La tarjeta mandara los datos solo cuando el CPU se lo requiera. Para manejar esto en assembler existen dos instrucciones IN y OUT. IN para recibir datos de los port, y OUT para enviar. Mas adelante profundizaremos sobre estas instrucciones. ----------------------------------------------------------------------------- Practica N§1 ----------------------------------------------------------------------------- 1. De la direccion fisica para los siguientes segmentos y offsets segmento offset Direccion Fisica a) 2345h 4550h b) 2000h FFFFh c) 0200h FFFFh d) 0FFFh 000Fh e) 3450h 0200h 2. De por lo menos 3 combinaciones de segmento y offset para cada direccion Fisica Segmento Offset Direccion Fisica a) 23445h b) FFF09h c) 00222h d) E4512h 3. Dada la direccion 0000:5450 que segmento comienza en esa direccion (es decir xxxx:0000h, offset = 0) 4. Dada la direccion 3456:8F34 que valor quedaria en el offset si tomo como base el segmento 3455h. --------------------------------------------------------------------------- Respuestas: 1. a) 279A0h b) 2FFFFh c) 11FFFh d) 0FFFFh e) 34700 2. a) 2344:0005 - 2343:0015 - 2340:0045 b) FFF0:0009 - FFEF:0019 - FF00:0F09 c) 0022:0002 - 0021:0012 - 0000:0222 d) E451:0002 - E450:0012 - E000:4512 3. 0545h 4. 8F44h ----------------------------------------------------------------------------- Bibliografia: PC Interno, Michel Tischer. y apuntes varios de la catedra de Arquitectura I de la UNLP, Turbo assembler, Manual del usuario. -----------------------------------------------------------------------------