Páginas

Mostrando las entradas con la etiqueta asm. Mostrar todas las entradas
Mostrando las entradas con la etiqueta asm. Mostrar todas las entradas

martes, 28 de febrero de 2012

[CÓMPUTO INTEGRADO] Arquitectura MIPS y simulador SPIM

Aquí van algunas cosas sobre la arquitectura MIPS:

Primero que nada, los diseños del MIPS son utilizados en la línea de productos informáticos de SGI; en muchos sistemas embebidos; en dispositivos para Windows CE; routers Cisco; y videoconsolas como la Nintendo 64 o las Sony PlayStation, PlayStation 2 y PlayStation Portable.

Existe un simulador MIPS R2000/R3000 totalmente libre llamado SPIM compatible con varios sistemas operativos ideado para el aprendizaje de la programación en ensamblador MIPS y de los conceptos generales del ensamblador.

Un emulador MIPS más completo pertenece al proyecto GXemul, el cual no sólo emula las diferentes versiones de los microprocesadores MIPS III y superiores, sino también sistemas enteros que utilicen esos procesadores.

Por ejemplo, GXemul puede emular tanto una DECstation con un procesador MIPS R4400 como un SGI O2 con CPU MIPS R10000, entre otros, así como también diferentes framebuffers y controladoras SCSI.

El software QEMU es capaz de emular también, entre muchas otras, la arquitectura MIPS y MIPSel, así como ejecutar GNU/Linux en la máquina emulada.

Hablando de MIPS, este posee ciertas características:
  • Los procesadores MIPS generalmente fueron de 32 bits, a excepción de los más actuales.
  • Su arquitectura es RISC (Reduced Instruction Set Computer)
  • Tiene 32 registros de 32 bits.
Juegos de registros:
  • $zero tiene cableado el valor numérico cero.
  • Los registros $a0, $a1, $a2 y $a3 se utilizan para pasar parámetros a subrutinas.
  • $v0 y $v1 se utilizan para devolver valores de subrutinas.
  • El registro $ra contiene la dirección de retorno y se utiliza para volver después de una llamada a subrutina.
  • Los registros $s0, $s1, $s2, $s3, $s4, $s5, $s6 y $s7 son registros salvados. 
  • Los registros $t0, $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8 y $t9 son registros temporales.
  • El registro $gp contiene el puntero global.
  • El registro $sp contiene el puntero de pila.
  • El registro $fp contiene el puntero de marco de pila.
  • El registro $at está reservado para el uso por el ensamblador y no debe ser usado por los programadores.
  • Los registros $k0 y $k1 están reservados para su uso por el núcleo del sistema operativo
Existen 3 registros especiales de 32 bits:
  • pc es el registro contador de programa que almacena la dirección de la siguiente instrucción a ejecutar.
  • hi y lo almacenan el resultado de operaciones de multiplicación o división que generan resultados de 64 bits:
    • hi almacena la parte alta del registro
    • lo almacena la parte baja del registro
Directivas MIPS:

.data Los elementos siguientes se almacenan en segmento de datos.
.text Los elementos siguientes se almacenan en segmento de código (texto).
.ascii "tira de caracteres" Almacena cadena de caracteres NO terminada en caractér nulo.
.asciiz "tira de caracteres" Almacena cadena de caracteres terminada en caracter nulo.
.byte 1, 2, 3 Almacena bytes en memoria, consecutivamente.
.half 300, 301, 302 Almacena medias palabras en memoria, consecutivamente.
.word 80000, 80001 Almacena palabras en memoria, consecutivamente.
. float 1.23, 2.23 Almacena valores flotantes en memoria, consecutivamente.
.double 3.0e21 Almacena dobles en memoria, consecutivamente.
.space 10 Reserva un espacio de 10 bytes e el segmento actual.
.extern etiqueta n Declara que etiqueta es global de tamaño n
.globl etiqueta Declara etiqueta como global
.align n Alínea el siguiente dato en un límite de 2^n

Tipos de instrucciones: 
  • Aritméticas y lógicas
    • addRd,R1,R2 #add,addi,addu,addiu – Comparación
    • seq Rd, R1, R2 # seq, sge, sgt, sle, slt, slti, ...
  • Carga y almacenamiento
    • la Rd label # la, lb, lbu, lh, lw (Carga)
    • swRolabel #sb,sh,sw(Almacenamiento)
  • Salto condicional e incondicional
    • beqR1,R2,label #beqz,bge,bgt,ble,...
  • Manejo excepciones / interrupciones
    • rfe,nop,breakn,syscall.
Codigos de llamadas a sistema:



    jueves, 23 de febrero de 2012

    [CÓMPUTO INTEGRADO] Programa MIPS

    En esta parte mostraré y explicare el código de un programa en ensamblador de MIPS explicando cada sección del código:

    Primero que nada el código:

    .data
    prompt:     .asciiz "Enter in an integer: "
    str1:  .asciiz "the answer is: "
    newline:  .asciiz "\n"
    bye:  .asciiz "Goodbye!\n"
     .globl main
    
     .text
    main:
    
     # Inicializando
     li $s0, 10
    
     # Imprime la linea para captura de datos
     li $v0, 4       # Carga $v0 para imprimir un string 
     la $a0, prompt  # Carga en $a0 la dirección de prompt
     syscall              # Se hace la llamada al sistema
    
     # Lee el valor
     li $v0, 5       # Carga $v0 para leer un entero
     syscall              # Se hace la llamada al sistema
     move  $s0, $v0     # Mueve el valor de $v0 a $s0
    
    
    loop:
     # Imprime str1
     li $v0, 4       # Carga $v0 para imprimir un string
     la $a0, str1    # Carga en $a0 la dirección de str1
     syscall           # Se hace la llamada al sistema
    
     # Imprime el valor del loop
     li $v0, 1  # Carga $v0 para imprimir un entero
     move $a0, $s0 # Mueve $s0 a $a0
     syscall   # Se hace llamada al sistema
    
     # Imprime el nuevo valor
     li $v0, 4  # Carga $v0 para imprimir un string
     la $a0, newline  # Carga en $a0 la direción de newline
     syscall   # Se hace llamada al sistema
    
     # Decrementa la variable
     sub $s0, $s0, 1     # Iguala $s0 a $s0 -1
     bgez $s0, loop    # Si $s0 >= 0 regresa a loop, si no, continua.
    
     # Imprime mensaje de adios
     li $v0, 4  # Carga $v0 para imprimir un string
     la $a0, bye # Carga en $a0 la dirección de bye
     jr  $ra  # Se guardan registros en $ra y sale del programa
    
    
    
    

    [CÓMPUTO INTEGRADO] Tarea intro

    Mi programa trata de hacer una simple matriz de 5 por 5.

    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,"",@progbits
    
    
    Este 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_symbols
    
    Ambos 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 .L2          
    Esta 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 .L6                             
    
    
    L2 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 .L3
                            
    
    En 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            
     ret                     
    
    
    En 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
    
    
    Despues de unas mejoras y quitando un poco de código de debug, el resultado nuevo es el siguiente: