Primero que nada, mi intención era mostrar el código generado por Mac OS X, sin embargo es un poco complicado ya que muestra demaciadas lineas a comparación de las que genera Ubuntu 10.10, mostrare a modo de ejemplo ambos códigos generados y pasare a explicar el código modificado de Ubuntu.
Éste es el código en C. Los números se generan de manera aleatoria.
#include (stdio.h) int main(void){ srand(time(0)); int i = 0, j = 0; int matriz[5][5]; for (i = 0; i <= 5; i++){ for (j = 0; j<=5; j++){ matriz[i][j]=(rand () %9)+1; } } for (i = 0; i <= 5; i++){ for (j = 0; j<=5; j++){ printf("%d",matriz[i][j]); } printf("\n"); } return 0; }Éste es el código ensamblador autogenerado del archivo anterior con el comando "gcc -S archivo.c" de Ubuntu.
.file "matriz.c" # Nombre del archivo .section .rodata # .LC0: # Etiqueta para el string .string "%d " # El string .text # Inicio .globl main # Indica que main es global .type main, @function # Indica que main es una función main: # Inicio de main pushl %ebp # Se coloca ebp al inicio movl %esp, %ebp # Se mueve esp a ebp andl $-16, %esp # Operación lógica entre esp y -16 pushl %esi # Registro esi pushl %ebx # Registor ebx subl $136, %esp # Se reserva espacio en esp movl $0, (%esp) # Se asigna la dirección 0 a esp call time # Se llama a time de la librería estandar movl %eax, (%esp) # Se mueve eax a esp call srand # Se llama a srand de la librería estandar movl $0, 124(%esp) # Se asigna la dirección 0 a la posición 124 de esp movl $0, 120(%esp) # Se asigna la dirección 0 a la posición 120 de esp movl $0, 124(%esp) # Se asigna la dirección 0 a la posición 124 de esp jmp .L2 # Se salta a la sección L2 .L5: # Sección L5 movl $0, 120(%esp) # Se mueve la dirección 0 a la posición 120 dde esp jmp .L3 # Salta a L3 .L4: # Sección L4 movl 124(%esp), %ebx # Se mueve el valor de la posición 124 de esp a ebx movl 120(%esp), %esi # Se mueve el valor de la posición 120 de esp a esi call rand # Se llama a rand de la librería estandar movl %eax, %ecx # Se mueve eax a ecx movl $954437177, %edx # Se asigna la dirección 954437177 a edx movl %ecx, %eax # Se mueve ecx a eax imull %edx # Se multiplica edx por 1 sarl %edx # Se desplaza 1 posición a la derecha en edx movl %ecx, %eax # Se mueve ecx a eax sarl $31, %eax # Se desplaza 31 posiciones a la derecha en eax subl %eax, %edx # Se resta eax a edx movl %edx, %eax # se mueve edx a eax sall $3, %eax # Se desplaza 3 posiciones a la izquierda en eax addl %edx, %eax # Se agrega edx a eax movl %ecx, %edx # Se mueve ecx a edx subl %eax, %edx # Se resta eax a ecx addl $1, %edx # Se agrega 1 a edx movl %ebx, %eax # Se mueve ebx a eax sall $2, %eax # Se desplaza dos posiciones a la izquierda en eax addl %ebx, %eax # Se agrega ebx a eax addl %esi, %eax # Se agrega esi a eax movl %edx, 20(%esp,%eax,4) ######### addl $1, 120(%esp) # Se agrega 1 al valor de la posición 120 de esp .L3: # Sección L3 cmpl $5, 120(%esp) # Comparación entre 5 y el valor de la posición 120 de esp jle .L4 # Salta a L4 si la comparación anterior es menor o igual al valor de esp addl $1, 124(%esp) # Se agrega 1 al valor de la posición 124 de esp .L2: # Sección L2 cmpl $5, 124(%esp) # Comparación entre 5 y el valor de la posición 124 de esp jle .L5 # Salta a L5 si la comparación anterior es menor o igual al valor de esp movl $0, 124(%esp) # Se asigna la dirección 0 a la posición 124 de esp jmp .L6 # Se salta a la sección L6 .L9: # Sección L9 movl $0, 120(%esp) # Se asigna la dirección 0 a la posición 120 de esp jmp .L7 # Salta a la sección L7 .L8 # Sección L8 movl 124(%esp), %edx # Se asigna el valor de la posición 124 de esp a edx movl 120(%esp), %ecx # Se asigna el valor de la posición 120 de esp a ecx movl %edx, %eax # Se mueve edx a ecx sall $2, %eax # Se desplaza dos posiciones a la izquierda en eax addl %edx, %eax # Se agrega el valor de edx a eax addl %ecx, %eax # Se agrega el valor de ecx a eax movl 20(%esp,%eax,4), %edx ######### movl $.LC0, %eax # Se asigna el string LC0 a eax movl %edx, 4(%esp) # Se mueve edx a la posición 4 de esp movl %eax, (%esp) # Se mueve eax a el principio de esp call printf # Se llama a printf de la librería estandar addl $1, 120(%esp) # Se agrega 1 a la posición 120 de esp .L7: # Sección L7 cmpl $5, 120(%esp) # Comparación entre 5 y el valor de la posición 120de esp jle .L8 # Salta a L8 si la comparación anterior es menor o igual al valor de esp movl $10, (%esp) # Se asigna 10 al inicio de esp call putchar # Se llama a putchar de la librería estandar addl $1, 124(%esp) # Se agrega 1 a la posición 124 de esp .L6: # Sección L6 cmpl $5, 124(%esp) # Comparación entre 5 y el valor de la posición 124 de esp jle .L9 # Salta a L9 si la comparación anterior es menor o igual al valor de esp movl $0, %eax # Se asigna el valor 0 a eax addl $136, %esp # Se agrega 136 a esp popl %ebx # Sale ebx popl %esi # Sale esi movl %ebp, %esp # Se mueve ebp a esp popl %ebp # Sale ebp ret # Return, fin del programa .size main, .-main .ident "GCC: (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5" .section .note.GNU-stack,"",@progbitsEste es el código generado por Mac OS X
.section __TEXT,__text,regular,pure_instructions .globl _main .align 4, 0x90 _main: Leh_func_begin1: pushq %rbp Ltmp0: movq %rsp, %rbp Ltmp1: subq $128, %rsp Ltmp2: xorl %eax, %eax xorb %cl, %cl movl %eax, %edi movb %cl, %al callq _time movl %eax, %ecx xorb %dl, %dl movl %ecx, %edi movb %dl, %al callq _srand movl $0, -12(%rbp) movl $0, -16(%rbp) movl $0, -12(%rbp) jmp LBB1_5 LBB1_1: movl $0, -16(%rbp) jmp LBB1_3 LBB1_2: movl -12(%rbp), %eax movl -16(%rbp), %ecx xorb %dl, %dl movl %eax, -120(%rbp) movb %dl, %al movl %ecx, -124(%rbp) callq _rand movl %eax, %ecx movl $954437177, %esi movl %ecx, %eax imull %esi movl %edx, %eax movl %eax, %esi shrl $31, %esi sarl %eax leal (%rax,%rsi), %eax movl %eax, %esi leal (%rax,%rsi,8), %eax negl %eax leal 1(%rcx,%rax), %eax movl -120(%rbp), %ecx movslq %ecx, %rcx movq %rcx, %rsi leaq (%rcx,%rsi,4), %rcx leaq -116(%rbp,%rcx,4), %rcx movl -124(%rbp), %esi movslq %esi, %rsi movl %eax, (%rcx,%rsi,4) movl -16(%rbp), %eax leal 1(%rax), %eax movl %eax, -16(%rbp) LBB1_3: movl -16(%rbp), %eax cmpl $5, %eax jle LBB1_2 movl -12(%rbp), %eax addl $1, %eax movl %eax, -12(%rbp) LBB1_5: movl -12(%rbp), %eax cmpl $5, %eax jle LBB1_1 movl $0, -12(%rbp) jmp LBB1_11 LBB1_7: movl $0, -16(%rbp) jmp LBB1_9 LBB1_8: movl -12(%rbp), %eax movl -16(%rbp), %ecx movslq %eax, %rax leaq -116(%rbp), %rdx movabsq $20, %rsi imulq %rsi, %rax addq %rax, %rdx movslq %ecx, %rax movl (%rdx,%rax,4), %eax xorb %cl, %cl leaq L_.str(%rip), %rdx movq %rdx, %rdi movl %eax, %esi movb %cl, %al callq _printf movl -16(%rbp), %eax addl $1, %eax movl %eax, -16(%rbp) LBB1_9: movl -16(%rbp), %eax cmpl $5, %eax jle LBB1_8 movl $10, %eax movl %eax, %edi callq _putchar movl -12(%rbp), %eax addl $1, %eax movl %eax, -12(%rbp) LBB1_11: movl -12(%rbp), %eax cmpl $5, %eax jle LBB1_7 movl $0, -8(%rbp) movl -8(%rbp), %eax movl %eax, -4(%rbp) movl -4(%rbp), %eax addq $128, %rsp popq %rbp ret Leh_func_end1: .section __TEXT,__cstring,cstring_literals L_.str: .asciz "%d " .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support EH_frame0: Lsection_eh_frame: Leh_frame_common: Lset0 = Leh_frame_common_end-Leh_frame_common_begin .long Lset0 Leh_frame_common_begin: .long 0 .byte 1 .asciz "zR" .byte 1 .byte 120 .byte 16 .byte 1 .byte 16 .byte 12 .byte 7 .byte 8 .byte 144 .byte 1 .align 3 Leh_frame_common_end: .globl _main.eh _main.eh: Lset1 = Leh_frame_end1-Leh_frame_begin1 .long Lset1 Leh_frame_begin1: Lset2 = Leh_frame_begin1-Leh_frame_common .long Lset2 Ltmp3: .quad Leh_func_begin1-Ltmp3 Lset3 = Leh_func_end1-Leh_func_begin1 .quad Lset3 .byte 0 .byte 4 Lset4 = Ltmp0-Leh_func_begin1 .long Lset4 .byte 14 .byte 16 .byte 134 .byte 2 .byte 4 Lset5 = Ltmp1-Ltmp0 .long Lset5 .byte 13 .byte 6 .align 3 Leh_frame_end1: .subsections_via_symbolsAmbos códigos tienen una sintaxis parecida, ya que en ambos utilicé una versión de gcc para el sistema. Pero en Ubuntu me lanza menos lineas de código y me es más comprensible, mientras que en OS X lanza demasiadas lineas de debug mezcladas con el código principal.
Ahora, analizaremos cada sección del programa, gcc me dividió el código en 9 secciones. La sección del main define principalmente los registros que se utilizaran durante la ejecución, aparte ejecuta funciones estandar llamadas en el código.
main:
main: pushl %ebp movl %esp, %ebp andl $-16, %esp pushl %esi pushl %ebx subl $136, %esp movl $0, (%esp) call time movl %eax, (%esp) call srand movl $0, 124(%esp) movl $0, 120(%esp) movl $0, 124(%esp) jmp .L2Esta parte del código se encarga de colocar las variables en el programa, llama a srand y a time para generar un número aleatorio.
L2:
.L2: cmpl $5, 124(%esp) jle .L5 movl $0, 124(%esp) jmp .L6L2 se encarga de hacer la comparación entre el valor de "esp" y el número 5. ¿Por qué esto? Porque la matriz sera de 5 x 5, se puede decir que L2 es la parte del código donde se comprueba una dimención de la matriz, y se guarda su dirección para saber donde guardar los números generados.
L5:
.L5: movl $0, 120(%esp) jmp .L3En L5 solo se guarda un 0 en la posición 120 de "esp" y se salta a L3.
L3:
.L3: cmpl $5, 120(%esp) jle .L4 addl $1, 124(%esp)En esta parte se vuelve a hacer una comparación, esta vez para asignar la segunda dimención de la matriz y se guardara en la posición 120 de "esp". Salta a la sección L4. En esta parte se vuelve a hacer una comparación, esta vez para asignar la segunda dimención de la matriz y se guardara en la posición 120 de "esp". Salta a la sección L4.
Como en los casos anteriores ocurren comparaciones, no se saldra de esas secciones hasta que las coparaciones acierten el "jle" que es un if que comprueba que el valor dado sea menor o igual al del parametro dado, por lo que esta parte seria como el "for" que todos conocen.
L4:
.L4: movl 124(%esp), %ebx movl 120(%esp), %esi call rand movl %eax, %ecx movl $954437177, %edx movl %ecx, %eax imull %edx sarl %edx movl %ecx, %eax sarl $31, %eax subl %eax, %edx movl %edx, %eax sall $3, %eax addl %edx, %eax movl %ecx, %edx subl %eax, %edx addl $1, %edx movl %ebx, %eax sall $2, %eax addl %ebx, %eax addl %esi, %eax movl %edx, 20(%esp,%eax,4) addl $1, 120(%esp)Esta parte es donde se asignan los números aleatorios, en "ebx" y en "esi" se trataran los números generados en forma aleatoria, estos se suman en "eax", en "edx" se guarda un número "954437177" que se guarda como un entero y se resta a "eax" para poner el límite de 0 a 9 a la hora de generar los números, "eax" se suma a "ebx" de nuevo y finalmente pasa a la posición 120 de "esp" y se guarda el número generado.
L4 regresa a L3, L3 a L5 y L5 a L2. El número generado se guarda en la posición 124 de "esp", ahora salta a L6.
L6:
.L6: cmpl $5, 124(%esp) jle .L9 movl $0, %eax addl $136, %esp popl %ebx popl %esi movl %ebp, %esp popl %ebp retEn esta sección se vuelve a comprobar la dimención de la matriz, y se salta a L9, los "popl" sacan los registros para finalizar con el "ret".
L9:
.L9: movl $0, 120(%esp) jmp .L7
L9 al igual que L5, solo guarda la dirección en 120 de "esp", pero esta ocación en lugar de guardar el número, se va a imprimir en pantalla. Para eso se pasa a L7.
L7:
.L7: cmpl $5, 120(%esp) jle .L8 movl $10, (%esp) call putchar addl $1, 124(%esp)
Esta parte del código hace lo mismo que L3, solo que despues de ejecutar L8 imprime el valor en pantalla. Al haber comparaciones en estos casos tambien, sucede lo mismo que paso anteriormente, por lo que esta parte esria el segundo for del programa, este para recorrer la matriz e imprimir cada valor.
L8:
.L8 movl 124(%esp), %edx movl 120(%esp), %ecx movl %edx, %eax sall $2, %eax addl %edx, %eax addl %ecx, %eax movl 20(%esp,%eax,4), %edx movl $.LC0, %eax movl %edx, 4(%esp) movl %eax, (%esp) call printf addl $1, 120(%esp)Esta es la parte final del programa, donde se imprime número por número, imprime los valores almacenados en "esp" que están almacenados en las posiciones 120 y 124, todo se agrega a "eax" y se le hace apuntar a LC0 para que imprima un "%d" que sera reemplazado por el valor guardado, justo como sucede en lenguaje C. Se llama a printf.
L8 regresa a L7, L7 a L9 y L9 a L6 donde salen los registros y finaliza el programa.
Los resultados son los siguientes:
Como vemos hay un error en el código que hace a que genere un número más grande de lo esperado, mejoremos el código un poco.
Código Mejorado | Código Antiguo |
.LC0: .string "%d" .text .globl main .type main, @function main: pushl %ebp movl %esp, %ebp andl $-16, %esp pushl %esi pushl %ebx subl $136, %esp movl $0, (%esp) call time movl %eax, (%esp) call srand movl $0, 124(%esp) movl $0, 120(%esp) jmp .L2 .L5: movl $0, 120(%esp) jmp .L3 .L4: movl 124(%esp), %ebx movl 120(%esp), %esi call rand movl $954437177, %edx imull %edx sarl %edx movl %ecx, %eax sarl $31, %eax subl %eax, %edx movl %edx, %eax sall $3, %eax addl %edx, %eax movl %ecx, %edx subl %eax, %edx addl $1, %edx movl %ebx, %eax sall $2, %eax addl %ebx, %eax addl %esi, %eax movl %edx, 20(%esp,%eax,4) addl $1, 120(%esp) .L3: cmpl $5, 120(%esp) jle .L4 addl $1, 124(%esp) .L2: cmpl $5, 124(%esp) jle .L5 movl $0, 124(%esp) jmp .L6 .L9: movl $0, 120(%esp) jmp .L7 .L8: movl 124(%esp), %edx movl 120(%esp), %ecx sall $2, %edx addl %edx, %eax addl %ecx, %eax movl 20(%esp,%eax,4), %edx movl $.LC0, %eax movl %edx, 4(%esp) movl %eax, (%esp) call printf addl $1, 120(%esp) .L7: cmpl $5, 120(%esp) jle .L8 movl $10, (%esp) call putchar addl $1, 124(%esp) .L6: cmpl $5, 124(%esp) jle .L9 movl $0, %eax addl $136, %esp popl %ebx popl %esi movl %ebp, %esp popl %ebp ret |
.file "matriz.c" .section .rodata .LC0: .string "%d" .text .globl main .type main, @function main: pushl %ebp movl %esp, %ebp andl $-16, %esp pushl %esi pushl %ebx subl $136, %esp movl $0, (%esp) call time movl %eax, (%esp) call srand movl $0, 124(%esp) movl $0, 120(%esp) movl $0, 124(%esp) jmp .L2 .L5: movl $0, 120(%esp) jmp .L3 .L4: movl 124(%esp), %ebx movl 120(%esp), %esi call rand movl %eax, %ecx movl $954437177, %edx movl %ecx, %eax imull %edx sarl %edx movl %ecx, %eax sarl $31, %eax subl %eax, %edx movl %edx, %eax sall $3, %eax addl %edx, %eax movl %ecx, %edx subl %eax, %edx addl $1, %edx movl %ebx, %eax sall $2, %eax addl %ebx, %eax addl %esi, %eax movl %edx, 20(%esp,%eax,4) addl $1, 120(%esp) .L3: cmpl $5, 120(%esp) jle .L4 addl $1, 124(%esp) .L2: cmpl $5, 124(%esp) jle .L5 movl $0, 124(%esp) jmp .L6 .L9: movl $0, 120(%esp) jmp .L7 .L8: movl 124(%esp), %edx movl 120(%esp), %ecx movl %edx, %eax sall $2, %eax addl %edx, %eax addl %ecx, %eax movl 20(%esp,%eax,4), %edx movl $.LC0, %eax movl %edx, 4(%esp) movl %eax, (%esp) call printf addl $1, 120(%esp) .L7: cmpl $5, 120(%esp) jle .L8 movl $10, (%esp) call putchar addl $1, 124(%esp) .L6: cmpl $5, 124(%esp) jle .L9 movl $0, %eax addl $136, %esp popl %ebx popl %esi movl %ebp, %esp popl %ebp ret .size main, .-main .ident "GCC: (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5" .section .note.GNU-stack,"",@progbits |
Cualquier error, porfa comenten :)
ResponderBorrar10 y 10
ResponderBorrar