Sei sulla pagina 1di 9

Prctica 1. Introduccin a los entornos de desarrollo. Modos de direccionamiento en un compilador de C.

Cuestin 1. Cuando un compilador de lenguaje de alto nivel genera una aplicacin, puede organizar la memoria siguiendo este esquema: Posiciones ms bajas de memoria virtual introduce el cdigo del programa. Posiciones intermedias introduce las variables globales. Posiciones ms altas de la mem. virtual las reserva para la pila. Utiliza el compilador de VC++ este esquema? Para contestar se puede utilizar un programa muy sencillo: 1. int VariableGlobal = 0xaabbccdd; 2. void main (void) 3. { 4. VariableGlobal ++; 5. } Direcciones bajas: pila (registro ESP). Direcciones intermedias: cdigo. Direcciones altas: datos. Esta sera la organizacin de la memoria: 0x00000000 esp ebp (cima pila) cdigo datos 0xFFFFFFFF 0x002cf86c 0x00fc138e 0x00fc7000

Cuestin 2. Ver cmo se almacenan los tipos bsicos de C en memoria cuando se usan variables globales: enteros (int), caracteres (char), enteros cortos (short int). Ver cmo se accede a esos datos. Realizar un programa que defina variables de estos tipos y las incremente. Utilizarlo para contestar a las siguientes preguntas: 1- En la ventana de desensamblado del depurador, intentar reconocer los modos de direccionamiento vistos en la seccin P1.3. 2- Qu modo de direccionamiento se usa? Se almacenan en la zona de pila?

3- Qu tamao tienen los datos de tipo int, char y short int. 4- Cuando el IA32 almacena un dato de 16 o 32 bits usa el modo little endian o big endian? Cdigo fuente:
int entero = 0xabcdabcd; short int entero_corto = 0x1234; char caracter = 0xaa; int main (void){ entero ++; entero_corto ++; caracter ++; }

Ensamblador:
entero ++; 009B138E mov eax,dword ptr [_entero (9B703Ch)] 009B1393 add eax,1 009B1396 mov dword ptr [_entero (9B703Ch)],eax entero_corto ++; 009B139B mov ax,word ptr [_entero_corto (9B7040h)] 009B13A1 add ax,1 009B13A5 mov word ptr [_entero_corto (9B7040h)],ax caracter ++; 009B13AB mov al,byte ptr [_caracter (9B7042h)] 009B13B0 add al,1 009B13B2 mov byte ptr [_caracter (9B7042h)],al

1- Direccionamiento absoluto (el operando est en memoria). 2- Las variables no se guardan en la pila (ya que son variables globales, y solo las locales se guardan en la pila) 3- Int: 32 bits; short int: 16 bits; char: 8 bits

4- Usa little endian. Cuestin 3. Ver cmo se almacenan los tipos bsicos de C en memoria cuando se usan variables locales: enteros, enteros cortos, caracteres. Ver cmo se accede a esos datos. 1) Qu modo de direccionamiento se usa? Se almacenan en la zona de pila? 2) Hay diferencias en el mtodo de inicializacin de variables globales y locales? 3) Definir 3 variables locales de tipo char, short int e int. Comprobar que no se almacenan en posiciones de memoria contiguas. Por qu? Cdigo fuente:
int main (void){ int entero = 0xabcdabcd; short int entero_corto = 0x1234; char caracter = 0xaa; entero ++; entero_corto ++; caracter ++; }

Ensamblador:
int entero = 0xabcdabcd; 00281016 mov dword ptr [ebp-4],0ABCDABCDh short int entero_corto = 0x1234; 0028101D mov eax,1234h 00281022 mov word ptr [ebp-0Ch],ax

char caracter = 0xaa; 00281026 mov byte ptr [ebp-5],0AAh entero ++; 0028102A mov ecx,dword ptr [ebp-4] 0028102D add ecx,1 00281030 mov dword ptr [ebp-4],ecx entero_corto ++; 00281033 mov dx,word ptr [ebp-0Ch] 00281037 add dx,1 0028103B mov word ptr [ebp-0Ch],dx caracter ++; 0028103F mov al,byte ptr [ebp-5] 00281042 add al,1 00281044 mov byte ptr [ebp-5],al }

1- Direccionamiento relativo a registro base (siendo el registro base EBP). Las variables se almacenan en la pila, ya que ebp apunta a la cima de la pila. 2- Si hay diferencias, en el de las variables globales no se ve la inicializacin (no hay cdigo ensamblador explcito se ver en el tema 3), mientras que en las variables locales el direccionamiento si es explcito (direccionamiento relativo a registro base se almacenan en la pila). 3- No se almacenan en posiciones de memoria contigua, porque se requiere alineamiento en memoria de 32 bits. Cuestin 4. Definir punteros para cada una de las variables definidas en el punto P1 y usarlos para incrementarlas. 1) Qu modo de direccionamiento se usa ahora? 2) En qu se diferencia el cdigo generado para la operacin puntero ++; cuando puntero se define como puntero a entero, del que se genera cuando est definido como puntero a carcter. 3) Si pent es un puntero a entero, analizar el cdigo que generan las expresiones (*pent)++ y *pent++ para determinar qu diferencia hay en las operaciones que realizan. 4) Qu pasa si se usa un puntero sin inicializar? 1int entero = 0xabcdabcd; int *pentero = &entero; short int entero_corto = 0x1234; short int *pentero_corto = &entero_corto; char caracter = 0xaa; char *pcaracter = &caracter; void main (void){ 010A1010 push ebp 010A1011 mov ebp,esp (*pentero)++; 010A1013 mov eax,dword ptr ds:[010A501Ch] 010A1018 mov ecx,dword ptr [eax] 010A101A add ecx,1 010A101D mov edx,dword ptr ds:[010A501Ch] 010A1023 mov dword ptr [edx],ecx (*pentero_corto)++; 010A1025 mov eax,dword ptr ds:[010A5024h] 010A102A mov cx,word ptr [eax] 010A102D add cx,1 010A1031 mov edx,dword ptr ds:[010A5024h] 010A1037 mov word ptr [edx],cx (*pcaracter)++; 010A103A mov eax,dword ptr ds:[010A5028h] 010A103F mov cl,byte ptr [eax] 010A1041 add cl,1 010A1044 mov edx,dword ptr ds:[010A5028h] 010A104A mov byte ptr [edx],cl

Direccionamiento absoluto y direccionamiento relativo a registro base (sin desplazamiento). 2*pentero++; 00F51013 mov eax,dword 00F51018 add eax,4 00F5101B mov dword ptr *pentero_corto++; 00F51020 mov ecx,dword 00F51026 add ecx,2 00F51029 mov dword ptr *pcaracter++; 00F5102F mov edx,dword 00F51035 add edx,1 00F51038 mov dword ptr } ptr ds:[00F5501Ch] ds:[00F5501Ch],eax ptr ds:[00F55024h] ds:[00F55024h],ecx ptr ds:[00F55028h] ds:[00F55028h],edx

En el incremento de un puntero a entero es de 4 bytes, mientras que el incremento de un puntero a char es de 1 byte (ya que un int ocupa 4 bytes y un char 1): 3- (*pent)++: incrementa el contenido de la direccin a la que apunta pent *pent++: incrementa el puntero, en este caso, como es un puntero a entero, incrementara la direccin en 4 bytes. 4char * cadena; void main (void){ strcpy(cadena, "Hola");

Da el siguiente error: Excepcin no controlada en 0x623af689 (msvcr90d.dll) en Practica1.exe: 0xC0000005: Infraccin de acceso al escribir en la ubicacin 0x00000000. El programa intenta acceder en una posicin de memoria a la que no tiene acceso. Cuestin 5. Hacer un programa que defina una variable global como un vector de 256 enteros, y los inicialice con valores de 0 a 255. 1) Qu modo de direccionamiento se usa para acceder a los elementos del vector? 2) Dibujar un esquema que muestre el papel que realiza cada uno de los elementos del modo de direccionamiento. 3) En qu cambia el modo de direccionamiento si el vector es de enteros cortos o de caracteres? 1int vector[256]; void main (void){ 00A11010 push ebp 00A11011 mov ebp,esp 00A11013 push ecx int i; for(i=0;i<256;i++) 00A11014 mov dword ptr 00A1101B jmp 00A11026 00A1101D mov eax,dword 00A11020 add eax,1 00A11023 mov dword ptr 00A11026 cmp dword ptr 00A1102D jge 00A1103E

[ebp-4],0 ptr [ebp-4] [ebp-4],eax [ebp-4],100h

00A1102F 00A11032 00A11035 00A1103C }

mov mov mov jmp

vector[i] = i; ecx,dword ptr [ebp-4] edx,dword ptr [ebp-4] dword ptr [ecx*4+00A15480h],edx 00A1101D

Para acceder a la variable ndice i (que se encuentra en la pila ya que es una variable local) se usa direccionamiento relativo a registro base (ebp) con desplazamiento. Para acceder a los elementos del vector (vector[i]) se usa direccionamiento indexado escalado (registro ndice*escala + desplazamiento; [ecx*4+00A15480h] donde ecx es el registro en el que se va guardando la variable ndice i, la cual se multiplica por 4 porque es el tamao en bytes de un entero se va avanzando en el vector-; se le suma ese desplazamiento porque esa direccin de memoria es donde se encuentra el inicio del vector).
ecx edx ndice (variable i) Dato a almacenar (i) 0x00A15480 0x00A15484 0 1 Vector[0] Vector[1]

Memoria indice*tamao_int + direccin_vector = vector[ndice+1] 3int i; for(i=0;i<256;i++) 012C1014 mov dword ptr [ebp-4],0 012C101B jmp 012C1026 012C101D mov eax,dword ptr [ebp-4] 012C1020 add eax,1 012C1023 mov dword ptr [ebp-4],eax 012C1026 cmp dword ptr [ebp-4],100h 012C102D jge 012C103D vector[i] = i; 012C102F mov ecx,dword ptr [ebp-4] 012C1032 mov dl,byte ptr [ebp-4] 012C1035 mov byte ptr [ecx+012C5480h],dl 012C103B jmp 012C101D }

Si es de short int cambia la escala, es decir, ahora ser 2 (tamao del short int en bytes) en lugar de 4. Para el caso de un vector de char la escala sera de 1 (y el direccionamiento sera indexado, ya que la escala 1 es como no tener escala). [De este ltimo no estoy muy seguro si es as o direccionamiento relativo a registro base con desplazamiento] Cuestin 6. Modificar el programa anterior de forma que el vector est definido como variable local. 1) Qu modo de direccionamiento se usa para acceder a los elementos del vector? 2) Dibujar un esquema que muestre el papel que realiza cada uno de los elementos del modo de direccionamiento. 1void main (void){ 00DC1010 push 00DC1011 mov ebp ebp,esp

00DC1013 sub esp,408h int vector[256]; int i; for(i=0;i<256;i++) 009D1019 mov dword ptr 009D1020 jmp 009D102B 009D1022 mov eax,dword 009D1025 add eax,1 009D1028 mov dword ptr 009D102B cmp dword ptr 009D1032 jge 009D1043 vector[i] = i; 009D1034 mov ecx,dword 009D1037 mov edx,dword 009D103A mov dword ptr 009D1041 jmp 009D1022 }

[ebp-4],0 ptr [ebp-4] [ebp-4],eax [ebp-4],100h ptr [ebp-4] ptr [ebp-4] [ebp+ecx*4+FFFFFBF8h],edx

Para acceder al ndice se usa direccionamiento relativo a registro base (ebp) con desplazamiento. Para acceder a los elementos del vector se usa direccionamiento indexado escalado (registro base: ebp; registro ndice: ecx; escala:4; desplazamiento: FFFFFBF8h). 2- La direccin de desplazamiento es una direccin negativa, lo que indica que es una direccin ms pequea que la cima de la pila. Ecx contiene el ndice, el cual vamos multiplicando por 4 porque cada acceso es un entero. A esta direccin le sumamos FFFFFBF8h (para colocarnos en vector[i]). Cuestin 7. Hacer un programa que defina una variable global como una matriz de 200*256 enteros e inicialice cada fila con valores de 0 a 255. 1) Que modo de direccionamiento se usa para acceder a los elementos del vector? 2) En qu variar el modo de direccionamiento si el vector es de enteros cortos o de caracteres? 3) Dibujar un esquema que muestre el papel que realiza cada uno de los elementos del modo de direccionamiento. 1int matriz[200][256]; void main (void){ 00191010 push ebp 00191011 mov ebp,esp 00191013 sub esp,8 int i; int j; for(i=0;i<200;i++){ 00191016 mov dword ptr [ebp-4],0 0019101D jmp 00191028 0019101F mov eax,dword ptr [ebp-4] 00191022 add eax,1 00191025 mov dword ptr [ebp-4],eax 00191028 cmp dword ptr [ebp-4],0C8h 0019102F jge 00191063 for(j=0;j<256;j++){ 00191031 mov dword ptr [ebp-8],0 00191038 jmp 00191043 0019103A mov ecx,dword ptr [ebp-8] 0019103D add ecx,1 00191040 mov dword ptr [ebp-8],ecx 00191043 cmp dword ptr [ebp-8],100h 0019104A jge 00191061 matriz[i][j] = j; 0019104C mov edx,dword ptr [ebp-4] / 0019104F shl edx,0Ah //desplazamiento a la izquierda. Para multiplicar por una //potencia de 2. En este caso por 2^10 (1024) 00191052 mov eax,dword ptr [ebp-8]

00191055 00191058

mov mov }

ecx,dword ptr [ebp-8] dword ptr [edx+eax*4+00195480h],ecx 0019103A 0019101F

0019105F jmp } 00191061 jmp }

Para acceder a los elementos del vector se usa direccionamiento indexado escalado (base: edx; ndice: eax; escala: 4; desplazamiento: 00195480h, que es la direccin de memoria de comienzo de la variable matriz). En edx estara la i y en eax la j. 2- La variacin es en la escala, que pasa a ser 2 en short int y 1 en char.
char matriz[200][256]; void main (void){ 00AB1010 push ebp 00AB1011 mov ebp,esp 00AB1013 sub esp,8 int i; int j; for(i=0;i<200;i++){ 00AB1016 mov dword ptr [ebp-4],0 00AB101D jmp 00AB1028 00AB101F mov eax,dword ptr [ebp-4] 00AB1022 add eax,1 00AB1025 mov dword ptr [ebp-4],eax 00AB1028 cmp dword ptr [ebp-4],0C8h 00AB102F jge 00AB1063 for(j=0;j<256;j++){ 00AB1031 mov dword ptr [ebp-8],0 00AB1038 jmp 00AB1043 00AB103A mov ecx,dword ptr [ebp-8] 00AB103D add ecx,1 00AB1040 mov dword ptr [ebp-8],ecx 00AB1043 cmp dword ptr [ebp-8],100h 00AB104A jge 00AB1061 matriz[i][j] = j; 00AB104C mov edx,dword ptr [ebp-4] 00AB104F shl edx,8 //no lo entiendo 00AB1052 mov eax,dword ptr [ebp-8] 00AB1055 mov cl,byte ptr [ebp-8] 00AB1058 mov byte ptr [edx+eax+00AB5480h],cl }

3- Anlogo a los anteriores y medio contestado en el apartado 1. Cuestin 8. Hacer un programa que defina una variable global como una estructura con seis campos, definidos en el siguiente orden: char, short, int, char, short, int. 1) Almacena el compilador los campos en el mismo orden en que han sido definidos? 2) Qu efecto tiene la directiva #pragma pack(1) colocada delante de la definicin de la estructura. 3) Dibujar un esquema que muestre el papel que realiza cada uno de los elementos del modo de direccionamiento. 4) Repetir el punto anterior con la variable definida como local. 1- (Primero est hecho como variable local. El resultado es el mismo si se declara la estructura dentro del main)
struct estructura{ char char1; short short1; int int1; char char2; short short2; int int2; }; void main (void){

00F01010 push ebp 00F01011 mov ebp,esp 00F01013 sub esp,10h struct estructura st = { 0xaa, 00F01016 mov byte ptr [ebp-10h],0AAh 0x1111, 00F0101A mov eax,1111h 00F0101F mov word ptr [ebp-0Eh],ax 0x66666666, 00F01023 mov dword ptr [ebp-0Ch],66666666h 0xbb, 00F0102A mov byte ptr [ebp-8],0BBh 0x3333, 00F0102E mov ecx,3333h 00F01033 mov word ptr [ebp-6],cx 0xabcdabcd }; 00F01037 mov dword ptr [ebp-4],0ABCDABCDh }

No se almacenan los datos en el mismo orden en el que han sido definidos. Se almacenan de la siguiente manera:

0XE64 0XE65 0XE66 0XE67 0XE68 0XE69 0xE6A 0xE6B 0xE6C 0xE6D 0xE6E 0xE6F 0xE70 0xE71 0xE72 0xE73 0xE74

aa (char1) 11 (short1) 11 (short1) 66 (int1) 66 (int1) 66 (int1) 66 (int1) bb (char2) 33 (short2) 33 (short2) cd (int2) ab (int2) cd (int2) ab (int2)

esp (ebp - 0x10) ebp - 0x0F ebp - 0x0E ebp - 0x0D ebp - 0x0C ebp - 0x0B ebp - 0x0A ebp - 0x09 ebp - 0x08 ebp - 0x07 ebp - 0x06 ebp - 0x05 ebp - 0x04 ebp - 0x03 ebp - 0x02 ebp - 0x01 ebp (cima)

2- La directiva #pragma pack() se usa para cambiar la alienacin de bytes cuando se declaran objetos o estructuras. #pragma pack(1) lo que hace es empaquetar en grupos de 1 byte (#pragma pack(2) empaquetara en grupo de 2 bytes, etc).
#pragma pack(1) struct estructura{ char char1; short short1; int int1; char char2; short short2; int int2; };

void main (void){ 01261010 push ebp 01261011 mov ebp,esp 01261013 sub esp,10h struct estructura st = { 0xaa, 01261016 mov byte ptr [ebp-10h],0AAh 0x1111, 0126101A mov eax,1111h 0126101F mov word ptr [ebp-0Fh],ax 0x66666666, 01261023 mov dword ptr [ebp-0Dh],66666666h 0xbb, 0126102A mov byte ptr [ebp-9],0BBh 0x3333, 0126102E mov ecx,3333h 01261033 mov word ptr [ebp-8],cx 0xabcdabcd }; 01261037 mov dword ptr [ebp-6],0ABCDABCDh }

As quedara la pila: 0XA5C 0XA5D 0XA5E 0XA5F 0XA60 0XA61 0XA62 0XA63 0XA64 0XA65 0XA66 0XA67 0XA68 0XA69 0xA6A 0xA6B 0xA6C aa (char1) 11 (short1) 11 (short1) 66 (int1) 66 (int1) 66 (int1) 66 (int1) bb (char2) 33 (short2) 33 (short2) cd (int2) ab (int2) cd (int2) ab (int2) esp (ebp - 0x10) ebp - 0x0F ebp - 0x0E ebp - 0x0D ebp - 0x0C ebp - 0x0B ebp - 0x0A ebp - 0x09 ebp - 0x08 ebp - 0x07 ebp - 0x06 ebp - 0x05 ebp - 0x04 ebp - 0x03 ebp - 0x02 ebp - 0x01 ebp (cima)

En este caso el tamao de la estructura es de 14 bytes, mientras que en el caso anterior el tamao era de 16 bytes. Para comprobarlo se puede aadir la siguiente lnea de cdigo en el main:
printf("el tam de st es: %d",sizeof(st));

4- Direccionamiento relativo a registro base con desplazamiento, siendo el registro base el EBP (cima de la pila) ya que la variable es local. 3- Falta usando variable global.

Potrebbero piacerti anche