Вы находитесь на странице: 1из 24

1

Captulo 3.

Variables.
3.1. Definicin de datos enteros como variables globales.
El siguiente segmento ilustra una serie de definiciones de enteros inicializados. En C, se denomina definicin de datos, la instancia en que se asigna espacio en la memoria para las variables. Y se emplea declaracin cuando no existe asignacin de espacio en la memoria. Por ejemplo una declaracin extern, o bien la declaracin de una estructura. En C, los enteros ocupan una palabra, por definicin. Por ejemplo, en un PC, con determinado procesador, si un entero es de 16 bits, un long es de 32 bits. Por estar definidas fuera de una funcin, se las denomina variables globales. int i1 = 0x12345678; static int i2 = -1; const int i3 = 1; volatile int i4 = 8; short int i5 = 6; long int i6 = 7; int arr[] = {0,1,2,3}; int main(void) { return(0) ; } Al ensamblarlo, resulta para la zona de datos: .set reorder .globl i1 .sdata .align 2 i1: .word 0x12345678 .sdata .align 2

# la localiza en segmento small data

# .word asigna espacio para 32 bits.

Profesor Leopoldo Silva Bijit

30-08-2008

Estructuras de Computadores Digitales

i2: .word 0xffffffff # -1 en complemento a dos .globl i3 .sdata .align 2 i3: .word 0x1 .globl i4 .sdata .align 2 i4: .word 0x8 .globl i5 .sdata .align 1 # Ntese el alineamiento a medias palabras. i5: .half 0x6 .globl i6 .sdata .align 2 #Al volver a alineamiento de palabra, queda un espacio de un half i6: .word 0x7 .globl arr #Arreglos los localiza en segmento data .data .align 2 arr: .word 0x0 #Almacena las componentes secuencialmente. .word 0x1 # arr[1] en la direccin de palabra siguiente a la de arr[0]. .word 0x2 .word 0x3 A las variables se las localiza en memoria. Cada una de ellas queda asociada a una direccin en el segmento esttico de datos. Y al cargarlo en memoria, puede visualizarse la zona de datos segn: i1 es la direccin: 0x10010004 con contenido: 0x12345678 i2 es la direccin: 0x10010008 i3 es la direccin: 0x1001000C i4 es la direccin: 0x10010010

Profesor Leopoldo Silva Bijit

30-08-2008

Variables

Data Segment =========================


DATA [0x10000000]...[0x10010000] [0x10010000] [0x10010010] [0x10010020] [0x10010030]...[0x10040000] 0x00000000 0x00000000 0x12345678 0xffffffff 0x00000001 0x00000008 0x00000006 0x00000007 0x00000000 0x00000001 0x00000002 0x00000003 0x00000000 0x00000000

i5 es la direccin vlida de media palabra: 0x10010014 La direccin 0x10010016, vlida para media palabra, se rellena con ceros y no es utilizada. Las medias palabras se ordenan little endian dentro de la palabra. La media palabra menos significativa tiene la direccin menor. i6 es la direccin: 0x10010018 con contenido 0x00000007. Se aprecia que SPIM, no hace diferencia entre el segmento para small data con el segmento data. Tampoco hay diferencias para variables calificadas constantes y voltiles. El calificador static se aplica por defecto a las variables globales en C. En MIPS tampoco hay diferencia entre un int y un long. Ambos son de 32 bits. La misma definicin podra haberse logrado en assembler, segn: .sdata i1: .word 0x12345678 i2: .word 0xffffffff i3: .word 0x1 i4: .word 0x8 .align 1 i5: .half 0x6 .align 2 i6: .word 0x7 .data .align 2 arr: .word 0x0, 0x1, 0x2, 0x3 Es importante destacar que las variables en assembler estn asociadas a una direccin. Las siguientes definiciones son para variables globales no inicializadas. int i1; int arr[4]; int main(void) { return(0) ; } Profesor Leopoldo Silva Bijit 30-08-2008

Estructuras de Computadores Digitales

El ensamblador genera el siguiente cdigo a continuacin de main. .globl arr .comm arr,16 .globl i1 .comm i1,4 Donde .comm asocia el nombre con un nmero de bytes de un bloque comn de datos. En SPIM se almacenan los bloques comunes de datos en el segmento de datos. Pueden visualizarse las direcciones en que se localizan las variables no inicializadas con Simulator: Display symbol table: g g arr at 0x10010004 i1 at 0x10010014

En sistemas NT, SPIM no procesa los bloques comunes de datos. Si lo hace en XP y Windows 2000. Los datos no inicializados no se ven en la zona de datos, al cargarse el programa, en el caso del ejemplo, la zona se visualiza: Data Segment ========================= DATA [0x10000000]...[0x10040000]

0x00000000

3.2. Asignacin. Movimiento de datos entre memoria y registros.


La expresin de asignacin es bsica en el lenguaje C. Consiste en escribir en la variable que est ubicada a la izquierda del signo igual, el valor de la expresin ubicada a la derecha del signo igual. La expresin a la izquierda debe ser un left-value; es decir, debe ser una variable o una expresin que corresponda a una direccin del almacenamiento. La expresin a la derecha puede ser una expresin - constantes y/o variables relacionadas por operadores - para la cual pueda calcularse un valor. El tipo del valor de la expresin debe ser del mismo tipo que el del left-value. Excepcin a esto ltimo son las conversiones automticas de tipo, en las cuales el valor de la expresin se convierte al tipo del left-value. Consideremos el siguiente programa:

Profesor Leopoldo Silva Bijit

30-08-2008

Variables int x=1; int y=2; int main(void) { y = x; x = 5; y = 0xFFFF+2; return(0) ; }

Inicialmente las globales, x e y tienen valores enteros 1 y 2 respectivamente. La primera asignacin, copia el valor de x en la variable y. Luego de la ejecucin de la asignacin la variable y tiene valor 1; la variable x no cambia su valor. Puede decirse que se lee x y se escribe en y. La segunda asignacin escribe en el espacio asociado a x, la constante 5. La tercera asignacin realiza una suma de dos constantes, y deposita el valor resultante en la variable y. La constante 0xFFFF ocupa 16 bits y su valor equivalente en decimal es 65535. Si se ensambla con lcc, la parte del texto que traduce las asignaciones es la siguiente: lw $24,x sw $24,y la $24,5 sw $24,x la $24,65537 sw $24,y El procesador MIPS permite el movimiento de contenidos de memoria hacia registros y viceversa. Para esto dispone de las instrucciones load word (carga registro con una palabra de memoria) y store word (almacena o guarda en una direccin de la memoria, el contenido de un registro). La instruccin assembler lw $24, x toma el contenido de la variable global x y la almacena dentro del registro temporal $24 (cuyo smbolo es $t8). Como veremos, es una macroinstruccin. La instruccin assembler sw $24, y guarda el contenido del registro temporal $24 en el espacio asignado a la variable y. Es decir, escribe el valor de $t8 en la direccin asociada a y. Como veremos, es una macroinstruccin. Si cargamos en la memoria, mediante SPIM, visualizamos la zona de datos y de programa, segn:

Profesor Leopoldo Silva Bijit

30-08-2008

6 Globales despus de inicializadas: [0x10010000]

Estructuras de Computadores Digitales x y 0x00000000 0x00000001 0x00000002 0x00000000

Observamos que la variable global x, se almacena en la direccin: 0x1001004, y que la variable y est en la direccin: 0x10010008 Texto de la primera asignacin: [0x0040029c] 0x3c011001 [0x004002a0] 0x8c380004 [0x004002a4] 0x3c011001 [0x004002a8] 0xac380008 y = x; lui $1, 4097 lw $24, 4($1) lui $1, 4097 sw $24, 8($1)

; 19: lw $24,x ; 20: sw $24,y

En metodologa RISC, todas las instrucciones deben ocupar una palabra. Pero para especificar una direccin se requieren 32 bits. Y no es posible codificar el cdigo de operacin de la instruccin ms los 32 bits en una palabra. Para resolver esta dificultad se coloca en el repertorio de mquina a la instruccin: lui <registro>, <valor expresado en 16 bits> La cual carga en la parte ms significativa del registro, los 16 bits que se especifican, como dato inmediato, en la instruccin. Los 16 inferiores se rellenan con ceros. En el caso del ejemplo, el valor decimal 4097 equivale a 0x1001 en hexadecimal, que corresponden a la parte ms significativa de la direccin x. lui es load upper immediate En un caso general se emplea la instruccin: ori rt, rs, <inmediato de 16 bits> para colocar los 16 bits inferiores de una direccin en un registro. Ya que el ori efecta el or, bit a bit, del contenido del registro rs con el valor inmediato y el resultado se deposita en el registro destino. Al valor inmediato se lo rellena con 16 bits de ceros a la izquierda, para completar los 32 bits. La instruccin or inmediato setea los 16 bits inferiores, lui setea los 16 superiores. Por ejemplo, la secuencia: lui $t0, 0x1234 ori $t0,$t0,0x5678 escribe en $t0 el valor 0x12345678 Para efectuar los movimientos entre memoria y registros se disponen las instrucciones de mquina: lw rt, <offset>(rs) sw rt, <offset>(rs)

Profesor Leopoldo Silva Bijit

30-08-2008

Variables

Se emplea el mecanismo de direccionamiento: registro base + offset, para establecer la direccin de la celda de memoria en que lw leer su contenido y lo depositar en el registro rt; en la misma direccin sw escribir el contenido del registro rt. El offset es un valor con signo de 16 bits, que se escribe en un campo de la instruccin, y que expresa el nmero de bytes que deben ser sumados al contenido del registro rs, para obtener la direccin efectiva. La expansin de las macros se logra empleando el registro temporal $1 (en smbolo $at, el cual est reservado para uso del ensamblador). Zona de datos: x [0x10010004] y [0x10010008] Segmento instrucciones: lui $1, 0x1001 lw $t8, 4($1) lui sw $1, 0x1001 $t8, 8($1)

0x00000001 0x00000002

; lw

$t8, x

; sw

$t8, y

Luego de la asignacin la zona de datos globales queda: [0x10010000] 0x00000000 0x00000001 0x00000001 0x00000000 Un programador en assembler podra efectuar la asignacin y = x, en slo tres instrucciones. Para ello basta apuntar con un registro temporal a la zona global de datos, y luego leer la variable x a otro temporal; y desde ese registro escribir en la variable y. lui lw sw $t8, 0x1001 $t7, 4($t8) $t7, 8($t8) ; y=x

3.3. Punteros. Direccionar e indireccionar.


Todos los procesadores poseen un mecanismo de direccionamiento indirecto. En el caso del MIPS, basta hacer cero el offset, para tener este modo de apuntar a las variables. Se coloca la direccin de la variable en un registro, el cual se denomina puntero; ya que contiene una direccin. Y a travs del direccionamiento indirecto se puede leer o escribir en la celda de memoria que contiene variables globales. Por ejemplo, si $t8 contiene la direccin de x, puede escribirse el contenido del registro t7 en la variable x, mediante: sw $t7, 0 ( $t8) # *t8 = t7 Puede leerse en $t7 el contenido de la variable x, que est apuntada por $t8, mediante:

Profesor Leopoldo Silva Bijit

30-08-2008

8 lw $t7, 0( $t8) # t7 = *t8

Estructuras de Computadores Digitales

Como comentario, hemos usado la notacin de C, para la indireccin. El asterisco que precede a un puntero, indica indireccin. Es decir el contenido de dicha direccin. El operador &, del lenguaje C, que precede a una variable, tiene por resultado la direccin de esa variable. En assembler, existe el macro: la $t8, x # t8 = &x que carga la direccin de una variable, en un registro (load address). Debe recordarse que en assembler los rtulos que identifican a las variables, son direcciones. Antes vimos que este macro se expande en la secuencia de lui, seguida de ori. Un esquema de las variables y valores, en ambiente assembler, muestra el par de registros involucrados y una variable global, ubicada en memoria.

registro puntero direccin

memoria registro dato valor memoria valor reg

Figura 3.1. Esquema de variables. En lenguaje C, si p es un puntero a entero y x es un entero, la asignacin: p = &x; /* direccionar */ Escribe en p, la direccin de la variable x. Debe definirse: int *p; La expresin: *p hace referencia al contenido de lo apuntado por p. El programador en C, ve dos variables, el puntero a entero p, y el entero x. Si graficamos a las variables como casilleros con el nombre de la variable en la parte superior, lo que queda dentro de la casilla es el contenido o valor de la variable.

Profesor Leopoldo Silva Bijit

30-08-2008

Variables

p &x

x *p
Figura 3.2. Punteros notacin.

Lo que C modela con tomar la direccin de una variable, e indireccionar respecto de un puntero, son las capacidades de direccionamiento indirecto disponibles en assembler.

3.4. Constantes. Direccionamiento inmediato.


Volviendo al ejemplo, la traduccin de escribir una constante en una variable, demandar nuevas instrucciones assembler, como veremos a continuacin. x = 5, se traduce mediante: la sw $24, 5 $24, x

# macro ya explicada antes

Viendo en SPIM, el cdigo de mquina asociado a la macro la $24, 5 ; observamos que lo expande segn: ori $24, $0, 5 cuyo cdigo binario es: 0x34180005 Donde se ha destacado que el valor inmediato es un nmero que se expresa con 16 bits, en un campo de la instruccin binaria. En forma equivalente podramos usar: addi $24, $0, 5 Que efecta el add del valor inmediato con el registro cero, y lo deposita en $24. Si se hubiera asignado una constante negativa: x = -5. El cdigo generado por lcc para esta asignacin es la $24, -5 sw $24, x La macro: la $24, -5 , al ser cargada por SPIM, se interpreta con la secuencia: lui $1, -1 # extiende a 32 bits, con signo ori $24, $1, -5 Que podra ser reemplazada por solo una instruccin: addi $24, $0, -5

Sin embargo si la constante no puede ser expresada con 16 bits, se emplea la secuencia lui seguida de un ori, explicada antes. Este es el caso de la asignacin: y = 0xFFFF+2; El resultado de la expresin, en hexadecimal es: 0x10001, que no puede ser expresada en 16 bits.

Profesor Leopoldo Silva Bijit

30-08-2008

10

Estructuras de Computadores Digitales

Que es traducida por lcc en: la $24, 65537 sw $24, y Ntese que lcc efecta operaciones aritmticas al ensamblar. Y la macro la $24, 65537 es expandida por SPIM en: lui ori $1, 1 $24, $1, 1 ; la $24, 65537

3.5. Expresiones simples con variables globales y constantes.


Consideremos el programa C: int x=1; int y=2; int z=3; int main(void) { z = x + 2 -(y + 1); return(0) ; } Con la siguiente traduccin para el clculo de la expresin y la asignacin: lw $24,x la $24,2($24) lw $15,y la $15,1($15) subu $24,$24,$15 sw $24,z Al ser cargada en SPIM, resulta: [0x0040029c] 0x3c011001 lui $1, 4097 [0x004002a0] 0x8c380004 lw $24, 4($1) [0x004002a4] 0x23180002 addi $24, $24, 2 [0x004002a8] 0x3c011001 lui $1, 4097 [0x004002ac] 0x8c2f0008 lw $15, 8($1) [0x004002b0] 0x21ef0001 addi $15, $15, 1 [0x004002b4] 0x030fc023 subu $24, $24, $15 [0x004002b8] 0x3c011001 lui $1, 4097 [0x004002bc] 0xac38000c sw $24, 12($1)

; 24: lw $24,x ; 25: la $24,2($24) ; 26: lw $15,y ; 27: la $15,1($15) ; 28: subu $24,$24,$15 ; 29: sw $24,z

Ntese que la macro: la $24, 2($24) es cargada como addi $24, $24, 2 Similar situacin ocurre para formar y+1. Permite cargar un registro con la suma del valor en un registro ms un offset. Aparece una nueva instruccin aritmtica:

Profesor Leopoldo Silva Bijit

30-08-2008

Variables subu rd, rs, rt que realiza: R[rd] = R[rs] -R[rt]

11

3.6. Variables locales. Frame.


Se denominan variables locales a las definidas dentro de una funcin. En C se denominan automticas, y tienen existencia slo durante la ejecucin de la funcin. Para lograr lo anterior, en el assembler se requiere tener una zona de la memoria en que se almacenarn estas variables. Esta zona se denomina frame, y se crea en el stack. De tal modo que cuando se ingresa a una funcin, se crea el espacio; y cuando se sale de la funcin el espacio es devuelto, y puede ser reutilizado. Por esta razn se dice que se manejan en forma dinmica. Adicionalmente en arquitecturas RISC, se dispone de un elevado nmero de registros. El compilador intenta emplear el mximo de variables locales localizadas en registros. Si una funcin llama a otra, sta ltima podra intentar ocupar registros ya empleados por la anterior, produciendo un conflicto con los datos. Para evitar lo anterior, una funcin puede usar en forma segura los registros, si salva todos los que emplee antes de sobrescribirlos, y luego al salir recuperar los valores originales; ya que no conoce la forma en que las otras funciones emplean los registros (esto es importante si fueron otras personas las que disearon dichas funciones). Evidentemente esto implica gran concentracin, y fue fuente de innumerables errores en el diseo de grandes sistemas. Adems implica mayor tiempo de ejecucin ya que salvar y restaurar implica escribir y leer en memoria (en el frame) y los tiempos de acceso a memoria son mayores que los de acceso a registros. Los procesadores disponan de instrucciones push y pop, que permitan salvar y recuperar un registro en la zona de stack. En el cdigo assembler esto se refleja en una serie de push al entrar a la funcin y una serie de pop al salir. Si estas instrucciones no estn en cierto orden se producen errores (cambia valores a locales); si no estn balanceadas tambin se producen severos errores (pueden ocasionar el rebalse de la zona de stack, si se meten elementos que no se sacan; tambin pueden alterar la direccin de retorno de las funciones, que tambin suele almacenarse en el frame). Por lo tanto se requiere alguna poltica de administracin del uso de los registros. Una forma de administracin es dividir a los registros en dos grupos, uno denominado de tipo t, y otro grupo de tipo s. Entonces los registros de tipo t, pueden ser usados libremente por cada funcin, y no puede asumirse que tengan valores. Los registros s, pueden ser usados por la funcin, pero debe salvar sus contenidos antes de usarlos, y al salir debe restaurar los contenidos. Profesor Leopoldo Silva Bijit 30-08-2008

12

Estructuras de Computadores Digitales

Entonces en los registros s, pueden almacenarse en forma segura las variables locales. Esto implica que los valores de variables locales, de una funcin, tienen los mismos valores antes y despus de un llamado a otra funcin. Este convenio se denomina: "el llamado salva las locales". La s del tipo le recuerda al programador assembler, que debe salvar dichos registros antes de usarlos. Sin embargo, si despus del llamado, la funcin que defini las locales, no las emplea, ser una prdida de tiempo el salvarlas. Para visualizar los conceptos anteriores, veremos una funcin en C y en assembler que emplee variables locales. Para simplificar veremos funciones que no tengan argumentos inicialmente. Luego agregaremos los argumentos. 3.6.1. Locales en registros. Usaremos en un primer ejemplo, variables locales definidas en la funcin principal main, y realizaremos una accin simple sobre las variables para visualizar la forma de acceso. int main(void) { register int x = 0, y = 1, z = 2; z = x + y; return(0) ; } El programador C, slo requiere visualizar sus variables locales, como casilleros con nombres. As entonces una vez dentro de la funcin se tiene:

x 0

y 1

z 2

Figura 3.3. Variables iniciadas. Luego de la asignacin se tendr:

x 0

y 1

z 1

Figura 3.4. Variables luego de la asignacin.

Profesor Leopoldo Silva Bijit

30-08-2008

Variables Si se traduce a assembler, tendremos: .set reorder .globl main .text .align 2 .ent main main: .frame $sp,16,$31 addu $sp,$sp,-16 .mask 0x40c00000,-8 sw $22,0($sp) sw $23,4($sp) sw $30,8($sp) move $30,$0 la $23,1 la $22,2

13

# creacin del frame # salva reg. s

# inicializa locales

addu $22,$30,$23
move $2,$0 L.1: lw $22,0($sp) lw $23,4($sp) lw $30,8($sp) addu $sp,$sp,16 j $31 .end main # valor de retorno # restaura registros s6, s7 y s8

# desarma frame.

sp

s6 s7 s8

Tope del frame

offset

Fondo del frame

Figura 3.5. Frame de la funcin. El programador assembler visualiza el frame de la funcin. En el texto assembler, inmediatamente despus del punto de entrada, aparece la sentencia: .frame <reg1>, <nmero>, <reg2> Donde reg1 indica el registro puntero al frame, el nmero indica los bytes que tendr el frame, reg2 indica el registro que contiene la direccin de retorno. En lcc, se emplea el registro stack

Profesor Leopoldo Silva Bijit

30-08-2008

14

Estructuras de Computadores Digitales

pointer, como reg1 y ra como almacn de la direccin de retorno. El nmero de niveles de stack es el nmero de bytes dividido por 4. Esta sentencia no genera directamente instrucciones de mquina, pero es una indicacin til para el programador assembler; en este sentido se denominan pseudoinstrucciones. Se emplean para depuradores de programas assembler. Luego viene la creacin del frame, mediante el cambio del stack pointer. Ntese que se resta, lo cual indica que la ocupacin del stack es desde direcciones mayores hacia direcciones menores; es decir crece hacia arriba, siempre que se asuma que las direcciones mayores estn hacia abajo. El stack pointer despus de la instruccin (addu $sp,$sp,-16) queda apuntando al tope del frame, esto se ilustra en el diagrama del frame. A continuacin, viene otra pseudoinstruccin, que le sirve al programador assembler como comentario, y cuyo uso est orientado a depuradores. .mask <mscara>, offset

Considerando 32 registros, se emplean ocho cifras hexadecimales, para codificar los registros que deben salvarse. Se marca con valor 1, cada uno de los registros que deben ser salvados en el frame. El bit 31 de la mscara corresponde al registro 31 y as correlativamente. El offset es la distancia en bytes, relativo al tope del frame anterior, donde se van guardando los registros; los registros con nmero mayor se almacenan ms hacia el fondo del frame.
3 1 r a 3 0 s 8 2 9 2 8 2 7 2 6 2 5 2 4 2 3 s 7 2 2 s 6 2 1 s 5 2 0 s 4 1 9 s 3 1 8 s 2 1 7 s 1 1 6 s 0 1 5 1 4 1 3 1 2 1 1 1 0 9 8 7 6 5 4 3 2 1 0

Figura 3.6. Mscara de registros.

Luego en el ejemplo, se salvan los registros 22, 23 y 30 en el stack.


Hacia el final del segmento assembler se restauran los contenidos originales de los registros s, en el mismo orden en que fueron salvados. Y se desarma el frame, volviendo el sp al tope del frame de la funcin que invoc a la que acaba de terminar. Siempre existe un frame activo, el que es apuntado por sp. Desde este momento dejan de existir las asociaciones de celdas de memoria del frame con los elementos que se guardaron en el frame. Automticamente se crean y automticamente desaparecen. Luego de esto se retorna de la funcin. Volviendo al ejemplo, inmediatamente despus de salvar los registros s, que se emplearn, se inicializan los registros s con los valores definidos para las locales. Esto muestra la importancia de definir locales con valores determinados, antes de ser ledas.

Profesor Leopoldo Silva Bijit

30-08-2008

Variables Luego de esto comienzan a existir las variables locales. Despus de toda esta actividad aparecen las acciones del bloque de la funcin. 3.6.2. Locales en registros y en el frame.

15

El siguiente ejemplo ilustra cmo se tratan las variables locales que no pueden ser almacenadas en registros s. Tenemos nueve variables locales que podemos almacenar en registros, la dcima se almacena en el stack. int main(void) { register int v1= 0, v2 = 1, v3 = 2, v4 = 4, v5 = 5, v6=6, v7=7, v8=8, v9=9, v10=10; v1 = v2 + v3; v10 = v10 + v1; return(0) ; } La variable global v10, a pesar que est precedida por la clase de almacenamiento registro, se trata de forma diferente. Es una celda del stack, ubicada en el fondo del stack, en este caso. El compilador asocia la direccin efectiva: -4+40($sp) a la variable local v10. La siguiente secuencia inicializa a v10: la $24,10 sw $24,-4+40($sp) Si se desea leer el contenido de v10 a un registro temporal, se emplea: lw $t8,-4+40($sp) Si se desea escribir en v10 desde un registro temporal, se emplea: sw $t8,-4+40($sp) Un esquema del frame:

Profesor Leopoldo Silva Bijit

30-08-2008

16

Estructuras de Computadores Digitales

sp

offset

s0 s1 s2 s3 s4 s5 s6 s7 s8 v10

Tope del frame

Fondo del frame

Figura 3.7. Frame con registros salvados y local. 3.6.3. Locales en el frame. En forma similar, si no se especifica register para las locales, stas son almacenadas en el stack, el siguiente ejemplo ilustra la situacin: int main(void) { int v1 = 0, v2 = 1, v3 = 2; v1 = v2 + v3; return(0) ; } Figura 3.8. Frame con locales. Se crea un frame de cuatro palabras. El compilador determina las siguientes direcciones efectivas para las variables: -4+16($sp) para v1; -8+16($sp) para v2; y -12+16($sp) para v3. Tratando a las locales en memoria, no se requiere salvar ni restaurar registros s, pero si iniciar las variables locales antes de usarlas; y esta operacin emplea accesos a memoria. Donde se presentan diferencias es en la manipulacin de las variables dentro del bloque de la funcin, ya que resulta ms eficiente, en tiempo, si las variables estn en registros. El texto que inicia las locales, ahora en memoria, es: sw $0,-4+16($sp) la $24,1 sw $24,-8+16($sp) la $24,2 sw $24,-12+16($sp)

sp

offset

v3 v2 v1

Tope del frame

Fondo del frame

Profesor Leopoldo Silva Bijit

30-08-2008

Variables

17

An nos falta analizar la forma de tratamiento de los argumentos, pero ya podemos darnos cuenta del costo de administracin de una funcin. Cuando se busca la mxima velocidad es preferible evitar las funciones y emplear variables globales. Sin embargo esta alternativa lleva a programas difciles de mantener y depurar.

3.7. Acciones. Corrimientos. Operadores lgicos al bit.


A continuacin veremos la traduccin de algunas expresiones con determinados tipos de operadores. Estudiaremos su descripcin en C, y observaremos nuevas instrucciones del repertorio de un procesador. Si est el operador en C, debe poder traducirse casi directamente a assembler; ste fue uno de los conceptos fundamentales de C: producir textos en alto nivel, que fueran eficientemente traducidos a assembler. Acciones complejas deben desarrollarse como funciones. Asumiremos que las variables estn en registros s, y slo describiremos la traduccin de expresiones. Los accesos a memoria para leer y escribir variables, se asume ya suficientemente ilustrado. Suponemos el siguiente esquema: int main(void) { register int v8=8, v7=7, v6=6, v5=5, v4=4, v3=3, v2=2, v1=1, v0=0; acciones; /* colocar una expresin y ver cmo es traducida */ return(0) ; } Quedan las siguientes equivalencias:

Variable Registro smbolo registro v8 $30 s8 v7 $23 s7 v6 $22 s6 v5 $21 s5 v4 $20 s4 v3 $19 s3 v2 $18 s2 v1 $17 s1 v0 $16 s0
Figura 3.9 Equivalencias entre variables y registros

Profesor Leopoldo Silva Bijit

30-08-2008

18 Corrimientos y operadores al bit.

Estructuras de Computadores Digitales

Expresin en C v8=v7<<4; v8=v7>>4; v8=v7>>v6; v7=~v6; v6=v5&v4; v5=v4|v3; v7=v6^v5; v6=v5*2;

Texto assembler sll $s8,$s7,4 sra $s8,$s7,4 sra $s8,$s7,$s6 not $s7,$s6 and $s6,$s5,$s4 or $s5,$s4,$s3 xor $s7,$s6,$s5 sll $s6,$s5,1

Mnemnico shift left logical shift right arithmetic immediate shift right arithmetic register

Figura 3.10. Compilacin de corrimientos y operadores al bit. Ntese que existe una traduccin de una instruccin de alto nivel por una de mquina.

3.8. Acceso en assembler a variables de diferente tipo, en segmento esttico de datos.


A continuacin, repasaremos algunos de los conceptos vistos antes, haciendo nfasis en los tipos de datos. En assembler las variables se tratan como las direcciones de las celdas que contienen los valores almacenados en ellas. Bsicamente se dispone de los tipos: palabras, medias palabras y bytes. Y las estructuras de datos: arreglos (de los tipos bsicos) y strings (arreglos de bytes, interpretados como caracteres). Para poder estructurar el espacio para las variables, el assembler dispone de las directivas siguientes: i) .data <direccin de carga> establece que las sentencias siguientes son datos(cambia de modo texto a data), hasta encontrar la sentencia .text que cambia a modo programa. El assembler tambin va llevando la cuenta de cules sern las direcciones que se asociaran a los identificadores de las variables, segn sus tipos; esto lo hace a partir de una direccin de carga, que se coloca despus de data. En caso de no definir una direccin de carga, el simulador asume por defecto que la primera direccin en que se tendrn datos es la: 0x1001000. Debe notarse que el segmento de datos puede comenzar en 0x10000000 o en 0x10010000 esto depende si est o no marcada la casilla bare-machine.

Profesor Leopoldo Silva Bijit

30-08-2008

Variables

19

ii) Las directivas: .word, .half y .byte establecen el tipo de la variable. Al mismo tiempo permiten iniciar con valores a las variables. Se denomina segmento esttico de datos a la zona de la memoria en que se almacenan datos que permanecern vigentes durante toda la ejecucin de un programa. Tambin se dispone de un segmento dinmico de datos (en un stack) en el cual las variables se crean, se modifican y desaparecen, durante la ejecucin del programa. El segmento assembler siguiente, crea 6 variables de tipo palabra (v1 a v6), luego almacena una media palabra en la variable v7; seguida de un byte identificado por la direccin simblica o variable v8; despus un arreglo arr, de 6 palabras; finalmente un arreglo de caracteres o string. .data 0x10010000 #variables estticas v1: .word 0x10001000 v2: .word 0x20002000 v3: .word 0x30003000 v4: .word 0x40004000 v5: .word 0x50005001 v6: .word 0x60006000 v7: .half 0x1234 v8: .byte 0xFF .align 2 arr: .word 0,1,2,3,4,5 string: .asciiz "abcdef" Para minimizar el tiempo de acceso las variables de tipo palabra se almacenan alineadas, es decir comienzan en una direccin vlida de palabra. As entonces a v1 le corresponde la direccin 0x10010000 y a v6 le corresponde 0x10010014. En la palabra que comienza en 0x10010018 se almacena la media palabra y tambin cabe el byte, y an queda espacio para otro byte. Al no existir la necesidad de almacenar otro byte, debe asegurarse que la nueva variable est alineada segn su tipo. En el ejemplo, a continuacin del byte, se dispone un arreglo de palabras. Por esta razn se fuerza el alineamiento de palabra, con la directiva .align 2. Los mecanismos de direccionamiento de memoria permiten accesar a palabras, medias palabras y bytes, con una instruccin. El arreglo, de seis palabras, comienza entonces en la direccin: 0x1001001C. Luego un arreglo de caracteres, terminado automticamente por un carcter nulo (con valor 0x00), que comienza en la direccin: 0x10010034. Se carga en el simulador SPIM, el programa assembler anterior, y se muestra a continuacin el segmento esttico de datos, que permite confirmar las direcciones de las variables, que se han

Profesor Leopoldo Silva Bijit

30-08-2008

20

Estructuras de Computadores Digitales

dado antes. Debe recordarse que las direcciones son de bytes, y que cada palabra tiene 4 bytes. Puede obtenerse un texto del ambiente del simulador, con el comando: File; Save log file. Data Segment [0x10010000] [0x10010010] [0x10010020] [0x10010030]

0x10001000 0x50005001 0x00000001 0x00000005

0x20002000 0x60006000 0x00000002 0x64636261

0x30003000 0x00ff1234 0x00000003 0x00006665

0x40004000 0x00000000 0x00000004 0x00000000

Para compactar el despliegue de los datos, se colocan cuatro palabras por lnea. De este modo las direcciones aumentan en diecisis senas (no en decenas), ya que se tienen 16 bytes en una lnea. El carcter a tiene cdigo ASCII 0x61, el f tiene cdigo 0x66. En el simulador, puede advertirse el orden de los bytes dentro de una palabra. As entonces, el carcter a est depositado en 0x10010034; el b en 0x10010035; el c en 10010036; el d en 0x10010037; el e en 0x10010038; el f en 0x10010039; y el carcter nulo, con que se termina el string en 0x1001003A. Este orden es little endian, ya que el byte ms derechista de una palabra tiene una direccin binaria que termina en 00. La variable, de tipo byte, v8 se encuentra en el byte 2 de la palabra ubicada en 0x10010018; es decir en la direccin: 0x1001001A. La variable v7, de tipo media palabra, se encuentra ubicada en direccin 0x10010018 y ocupa dos bytes. El valor 0x34 se almacena en 0x10010018 y el valor 0x12 en 0x10010019. 3.8.1. Manipulacin de palabras. Para cargar en un registro la variable v1 desde la memoria, debe tenerse en un registro la direccin de v1, pero sta ocupa 32 bits. Para ello se emplean dos instrucciones con direccionamiento inmediato; una que carga (16 bits) en la parte superior de un registro y otra que efecta un or con los 16 bits inferiores. Ejemplos: Los 16 bits ms significativos de la direccin de v2 son: 0x1001, y los 16 inferiores son 0x0004. Emplearemos el temporal $t1 para formar la direccin de v2. lui $t1, 0x1001 ori $t1, $t1, 0x0002 Los 16 bits ms significativos de la direccin de v1 son: 0x1001, y los 16 inferiores son 0x0000. Emplearemos el temporal $t1 para formar la direccin de v1. lui $t1, 0x1001

Profesor Leopoldo Silva Bijit

30-08-2008

Variables

21

No es necesario el ori, para cargar con ceros los 16 bits menos significativos ya la instruccin lui lo hace. Como la accin de fijar un registro como puntero a una palabra de la memoria, es una accin muy frecuente, los diseadores de SPIM crearon una macro instruccin que efecta la secuencia anterior, de modo ms simple, y en forma simblica. la $t1, v1 # t1 = &v1 carga direccin de v1 en t1.

La macro instruccin se denomina la, por load address. Para su ejecucin en Settings, debe estar deshabilitada la casilla bare-machine (se trabaja con la mquina virtual: la mquina sola ms el repertorio de macros). En este caso, el simulador reserva el registro $1(de nombre simblico at) para implementar las macros, cuando necesita almacenamiento temporal; de esta forma el programador no puede emplear dicho registro en su cdigo. Ahora la carga del valor de v1 en el registro temporal $t2, es simplemente: lw $t2, 0($t1) # t2 = *t1 indirecciona, va puntero.

Equivale a: t2 = v1 Se denomina indireccionar, a traer el valor almacenado en la direccin.

Se ha empleado direccionamiento indirecto relativo a registro, empleando el modo base+offset nativo del procesador, con desplazamiento cero.
Para accesar la variable v2, u otra, puede emplearse un mecanismo similar al visto. Sin embargo resulta conveniente dejar apuntando con $t1 al inicio del segmento de datos y efectuar el direccionamiento con un offset relativo a $t1. Por ejemplo v2 est cuatro bytes ms adelante, v3 a 8 bytes. En un caso ms general, para este fin se provee de un registro especial denominado gp(con nmero decimal 28) global pointer, para apuntar a la zona esttica de datos. Entonces, la carga del registro $t3 con la variable v4, estando fijado el valor de $t1 con anterioridad, se logra con: lw $t3, 12($t1) # t3 = v4

3.8.2. Manipulacin de medias palabras. Veamos ahora el acceso a medias palabras. la $t4, v7 # t4 = &v7 lh $t5,0($t4) # t5 = *t4 que equivale a t5 = v7

Profesor Leopoldo Silva Bijit

30-08-2008

22

Estructuras de Computadores Digitales

se ha trado la media palabra al registro $t5, y se ha rellenado con el bit ms significativo de 0x1234 (que es un cero y corresponde al bit del signo, como se ver ms adelante) las primeras 16 posiciones del registro $t5. Si se suma uno al contenido de $t5 y se vuelve a depositar en v7, mediante la secuencia: addi $t5, $t5, 1 # t5 ++ sh $t5, 0($t4) # *t4 = t5 equivale a v7 = t5 (t4 contiene la direccin de v7) Debe notarse que no se altera la variable v8 que comparte la palabra con v7. Cuestin que habra ocurrido si en lugar del store half se hubiese empleado sw. 3.8.3. Manipulacin de bytes. Veamos ahora el direccionamiento de bytes. Se genera cdigo para implementar v8 = v8-1 la $t6,v8 # t6 = &v8 lb $t7,0($t6) # t7 = *t6 o bien t7 = v8 addi $t7,$t7,-1 # t7-- o bien t7 = t7 1; esto debido a que no existe subi sb $t7,0($t6) # *t6 = t7, que equivale a v7 = t7 Debe notarse que la carga del byte, coloca en los 24 bits ms significativos de $t7, el bit del signo del byte en que est almacenada v8 (en este caso un uno). El almacenamiento del byte, no modifica el espacio de los otros bytes de la misma palabra. Sobre las direcciones de palabras, medias palabras y bytes: Supongamos que en la direccin 0x0010 tenemos una palabra, luego cuatro medias palabras, y finalmente ocho bytes. El espacio podra visualizarse: Direccin 0x0010 0x0014 0x0018 0x001C 0x0020 Contenido de las palabras de memoria de 32 bits Word1 Halfword1 Halfword0 Halfword3 Halfword2 Byte3 Byte2 Byte1 Byte0 Byte7 Byte6 Byte5 Byte4 Figura 3.11. Palabras, medias palabras, bytes. Las variables se han almacenado alineadas de acuerdo a sus tipos. La zona de medias palabras, con sus direcciones, puede visualizarse segn:

Profesor Leopoldo Silva Bijit

30-08-2008

Variables 0x0014 0x0016 0x0018 0x001A Halfword0 Halfword1 Halfword2 Halfword3

23

Figura 3.12. Zona de medias palabras. Debe notarse el ordenamiento little endian, de las medias palabras. La zona de bytes, con sus respectivas direcciones, puede visualizarse segn: 0x001C 0x001D 0x001E 0x001F 0x0020 0x0021 0x0022 0x0023 Byte0 Byte1 Byte2 Byte3 Byte4 Byte5 Byte6 Byte7

Figura 3.13. Zona de medias palabras. As entonces, si el registro $t1 apunta a 0x0010, la variable Halfword0 puede referenciarse segn 4($t1); la Halfword1 por 6($t1). De igual forma, el Byte0 queda referenciado por 0xC($t1); el Byte4 por 0x10($t1). Si $t2 contiene 0x0020 el Byte3 puede direccionarse segn: -1($t2); el Byte6 por 2($t2). En direccionamiento base+offset, el desplazamiento es en bytes.

Profesor Leopoldo Silva Bijit

30-08-2008

24

Estructuras de Computadores Digitales

ndice general.
CAPTULO 3. .............................................................................................................................................1 VARIABLES...............................................................................................................................................1 3.1. DEFINICIN DE DATOS ENTEROS COMO VARIABLES GLOBALES..........................................................1 3.2. ASIGNACIN. MOVIMIENTO DE DATOS ENTRE MEMORIA Y REGISTROS..............................................4 3.3. PUNTEROS. DIRECCIONAR E INDIRECCIONAR. ....................................................................................7 3.4. CONSTANTES. DIRECCIONAMIENTO INMEDIATO................................................................................9 3.5. EXPRESIONES SIMPLES CON VARIABLES GLOBALES Y CONSTANTES. ................................................10 3.6. VARIABLES LOCALES. FRAME. .........................................................................................................11 3.6.1. Locales en registros. ................................................................................................................12 3.6.2. Locales en registros y en el frame............................................................................................15 3.6.3. Locales en el frame. .................................................................................................................16 3.7. ACCIONES. CORRIMIENTOS. OPERADORES LGICOS AL BIT. ...........................................................17 Corrimientos y operadores al bit. ......................................................................................................18 3.8. ACCESO EN ASSEMBLER A VARIABLES DE DIFERENTE TIPO, EN SEGMENTO ESTTICO DE DATOS. .....18 3.8.1. Manipulacin de palabras. ......................................................................................................20 3.8.2. Manipulacin de medias palabras. ..........................................................................................21 3.8.3. Manipulacin de bytes. ............................................................................................................22 NDICE GENERAL. ....................................................................................................................................24 NDICE DE FIGURAS. ................................................................................................................................24

ndice de figuras.
FIGURA 3.1. ESQUEMA DE VARIABLES...........................................................................................................8 FIGURA 3.2. PUNTEROS NOTACIN. ...............................................................................................................9 FIGURA 3.3. VARIABLES INICIADAS.............................................................................................................12 FIGURA 3.4. VARIABLES LUEGO DE LA ASIGNACIN....................................................................................12 FIGURA 3.5. FRAME DE LA FUNCIN. ...........................................................................................................13 FIGURA 3.6. MSCARA DE REGISTROS.........................................................................................................14 FIGURA 3.7. FRAME CON REGISTROS SALVADOS Y LOCAL. ..........................................................................16 FIGURA 3.8. FRAME CON LOCALES. .............................................................................................................16 FIGURA 3.9 EQUIVALENCIAS ENTRE VARIABLES Y REGISTROS ....................................................................17 FIGURA 3.10. COMPILACIN DE CORRIMIENTOS Y OPERADORES AL BIT. .....................................................18 FIGURA 3.11. PALABRAS, MEDIAS PALABRAS, BYTES. .................................................................................22 FIGURA 3.12. ZONA DE MEDIAS PALABRAS..................................................................................................23 FIGURA 3.13. ZONA DE MEDIAS PALABRAS..................................................................................................23

Profesor Leopoldo Silva Bijit

30-08-2008

Вам также может понравиться