GNU/Linux xterm-256color zsh 163 views

.global _start

.section .bss
input:  .skip 20
buffer: .skip 32

.section .rodata
newline: .asciz "\n"

.section .text
_start:
    // Leer número desde teclado
    mov x0, #0          // STDIN
    ldr x1, =input
    mov x2, #20
    mov x8, #63         // syscall read
    svc 0

    // Convertir string a entero en x20
    ldr x1, =input
    mov x20, #0         // acumulador
    mov x2, #0
    mov x9, #10         // constante 10

parse_input:
    ldrb w3, [x1, x2]
    cmp w3, #10
    beq end_parse
    sub w3, w3, #'0'
    uxtw x4, w3
    mul x20, x20, x9
    add x20, x20, x4
    add x2, x2, #1
    b parse_input
end_parse:

    // F(0) = 0
    cmp x20, #0
    bne continue
    mov x7, #0
    b print_result

continue:
    // F(1) = 1
    cmp x20, #1
    bne start_fibo
    mov x7, #1
    b print_result

// ----------------------------------------------------
// Matriz base: A = {{1,1},{1,0}}, B = resultado
// Almacenes en registros:
// A: x0 x1
//    x2 x3
// B: x4 x5
//    x6 x7
// ----------------------------------------------------

start_fibo:
    // Inicializar matriz base A
    mov x0, #1  // A[0][0]
    mov x1, #1  // A[0][1]
    mov x2, #1  // A[1][0]
    mov x3, #0  // A[1][1]

    // Inicializar identidad B
    mov x4, #1  // B[0][0]
    mov x5, #0  // B[0][1]
    mov x6, #0  // B[1][0]
    mov x7, #1  // B[1][1]

    mov x8, x20         // x8 = n
    sub x8, x8, #1      // n - 1

fib_power_loop:
    // while (n > 0)
    cmp x8, #0
    beq done_power

    // if (n % 2 == 1) → B = B * A
    and x9, x8, #1
    cmp x9, #0
    beq skip_mult
    bl matrix_mult_BA

skip_mult:
    // A = A * A
    bl matrix_mult_AA

    // n = n / 2
    lsr x8, x8, #1
    b fib_power_loop

done_power:
    // Resultado en x5 = B[0][1] = F(n)
    mov x7, x5

// --------------------------------
// Imprimir número x7
// --------------------------------
print_result:
    ldr x5, =buffer
    add x5, x5, #31
    mov x2, #0
    mov x10, x7
    mov x9, #10

conv_loop:
    udiv x7, x10, x9
    mul x8, x7, x9
    sub x4, x10, x8
    add x4, x4, #'0'
    strb w4, [x5]
    sub x5, x5, #1
    add x2, x2, #1
    mov x10, x7
    cmp x10, #0
    bne conv_loop

    add x5, x5, #1
    mov w3, #'\n'
    strb w3, [x5, x2]
    add x2, x2, #1

    mov x0, #1
    mov x1, x5
    mov x8, #64
    svc 0

    // salir
    mov x0, #0
    mov x8, #93
    svc 0

// ----------------------------------------------------
// Subrutina: matrix_mult_BA → B = B * A
// Entrada: A = x0..x3, B = x4..x7
// Salida:  B actualizada
// ----------------------------------------------------
matrix_mult_BA:
    // Guardar copias
    mov x11, x4
    mov x12, x5
    mov x13, x6
    mov x14, x7

    // B * A
    mul x4, x11, x0      // B[0][0] = b00*a00
    madd x4, x12, x2, x4 //         + b01*a10

    mul x5, x11, x1      // B[0][1] = b00*a01
    madd x5, x12, x3, x5

    mul x6, x13, x0      // B[1][0] = b10*a00
    madd x6, x14, x2, x6

    mul x7, x13, x1      // B[1][1] = b10*a01
    madd x7, x14, x3, x7
    ret

// ----------------------------------------------------
// Subrutina: matrix_mult_AA → A = A * A
// Entrada/Salida: A en x0..x3
// ----------------------------------------------------
matrix_mult_AA:
    mov x11, x0
    mov x12, x1
    mov x13, x2
    mov x14, x3

    mul x0, x11, x11
    madd x0, x12, x13, x0

    mul x1, x11, x12
    madd x1, x12, x14, x1

    mul x2, x13, x11
    madd x2, x14, x13, x2

    mul x3, x13, x12
    madd x3, x14, x14, x3
    ret