GNU/Linux xterm-256color bash 133 views

/*
Autor: Victor Manuel Madrid Lugo
Fecha: 07/04/2025
Descripción: Ordena 3 números ingresados por el usuario de mayor a menor
Demostración: [https://asciinema.org/a/YDn9TXoKzFgoPNE16dTiXcQX0]
*/

/*
# Ordenamiento de 3 números en Python (mayor a menor)

# Solicitar números al usuario
num1 = int(input("Ingrese el primer número: "))
num2 = int(input("Ingrese el segundo número: "))
num3 = int(input("Ingrese el tercer número: "))

# Ordenamiento (usando comparaciones simples)
if num1 < num2:
    num1, num2 = num2, num1  # Intercambiar si están en orden incorrecto

if num1 < num3:
    num1, num3 = num3, num1

if num2 < num3:
    num2, num3 = num3, num2

# Mostrar resultado
print(f"Números ordenados: {num1}, {num2}, {num3}")
*/

.section .data
    msg_prompt1:    .asciz "Ingrese el primer número: "
    msg_prompt2:    .asciz "Ingrese el segundo número: "
    msg_prompt3:    .asciz "Ingrese el tercer número: "
    msg_result:     .asciz "Números ordenados: "
    comma_space:    .asciz ", "
    newline:        .asciz "\n"
    buffer:         .skip 21      // Buffer para entrada
    num_buffer:     .skip 21      // Buffer para conversión numérica

.section .text
.global _start

_start:
    // =============================================
    // Leer los tres números del usuario
    // =============================================
    
    // Primer número
    mov x0, #1                  // stdout
    ldr x1, =msg_prompt1        // mensaje
    mov x2, #27                 // longitud
    mov x8, #64                 // syscall write
    svc #0
    
    mov x0, #0                  // stdin
    ldr x1, =buffer             // buffer de entrada
    mov x2, #21                 // tamaño máximo
    mov x8, #63                 // syscall read
    svc #0
    
    ldr x0, =buffer             // convertir a número
    bl atoi
    mov x19, x0                 // guardar en x19

    // Segundo número
    mov x0, #1
    ldr x1, =msg_prompt2
    mov x2, #27
    mov x8, #64
    svc #0
    
    mov x0, #0
    ldr x1, =buffer
    mov x2, #21
    mov x8, #63
    svc #0
    
    ldr x0, =buffer
    bl atoi
    mov x20, x0                 // guardar en x20

    // Tercer número
    mov x0, #1
    ldr x1, =msg_prompt3
    mov x2, #27
    mov x8, #64
    svc #0
    
    mov x0, #0
    ldr x1, =buffer
    mov x2, #21
    mov x8, #63
    svc #0
    
    ldr x0, =buffer
    bl atoi
    mov x21, x0                 // guardar en x21

    // =============================================
    // Ordenar los números (x19, x20, x21)
    // =============================================
    
    // Comparar x19 y x20
    cmp x19, x20
    b.ge comp1_ok
    // Intercambiar si x19 < x20
    mov x22, x19
    mov x19, x20
    mov x20, x22

comp1_ok:
    // Comparar x19 y x21
    cmp x19, x21
    b.ge comp2_ok
    // Intercambiar si x19 < x21
    mov x22, x19
    mov x19, x21
    mov x21, x22

comp2_ok:
    // Comparar x20 y x21
    cmp x20, x21
    b.ge comp3_ok
    // Intercambiar si x20 < x21
    mov x22, x20
    mov x20, x21
    mov x21, x22

comp3_ok:
    // =============================================
    // Mostrar resultados
    // =============================================
    
    // Imprimir "Números ordenados: "
    mov x0, #1
    ldr x1, =msg_result
    mov x2, #20                 // longitud del mensaje
    mov x8, #64
    svc #0

    // Imprimir primer número (x19)
    ldr x0, =num_buffer
    mov x1, x19
    bl int_to_str               // convertir a string
    mov x2, x0                  // longitud del número
    
    mov x0, #1                  // stdout
    ldr x1, =num_buffer         // buffer con el número
    mov x8, #64                 // write
    svc #0

    // Imprimir ", "
    mov x0, #1
    ldr x1, =comma_space
    mov x2, #2
    mov x8, #64
    svc #0

    // Imprimir segundo número (x20)
    ldr x0, =num_buffer
    mov x1, x20
    bl int_to_str
    mov x2, x0
    
    mov x0, #1
    ldr x1, =num_buffer
    mov x8, #64
    svc #0

    // Imprimir ", "
    mov x0, #1
    ldr x1, =comma_space
    mov x2, #2
    mov x8, #64
    svc #0

    // Imprimir tercer número (x21)
    ldr x0, =num_buffer
    mov x1, x21
    bl int_to_str
    mov x2, x0
    
    mov x0, #1
    ldr x1, =num_buffer
    mov x8, #64
    svc #0

    // Imprimir newline
    mov x0, #1
    ldr x1, =newline
    mov x2, #1
    mov x8, #64
    svc #0

    // =============================================
    // Terminar programa
    // =============================================
    mov x0, #0                  // código de salida
    mov x8, #93                 // syscall exit
    svc #0

// =============================================
// Función atoi: Convierte string a entero
// Entrada: x0 = dirección del string
// Salida: x0 = número convertido
// =============================================
atoi:
    mov x1, #0                  // resultado
    mov x3, #10                 // base 10
    mov x4, #0                  // indicador negativo

    // Verificar signo negativo
    ldrb w2, [x0], #1
    cmp w2, #'-'
    b.ne atoi_loop
    mov x4, #1
    ldrb w2, [x0], #1

atoi_loop:
    // Verificar fin de string
    cmp w2, #10                 // '\n'
    b.eq atoi_done
    cbz w2, atoi_done           // '\0'
    
    // Verificar que es dígito
    cmp w2, #'0'
    b.lt atoi_error
    cmp w2, #'9'
    b.gt atoi_error
    
    // Convertir y acumular
    sub w2, w2, #'0'
    mul x1, x1, x3
    add x1, x1, x2
    
    // Siguiente carácter
    ldrb w2, [x0], #1
    b atoi_loop

atoi_done:
    // Aplicar signo si es negativo
    cbz x4, atoi_positive
    neg x1, x1

atoi_positive:
    mov x0, x1
    ret

atoi_error:
    mov x0, #0
    ret

// =============================================
// Función int_to_str: Convierte entero a string
// Entrada: x0 = buffer, x1 = número
// Salida: x0 = longitud del string
// =============================================
int_to_str:
    mov x2, #10                 // base 10
    mov x3, #0                  // contador de dígitos
    mov x4, x0                  // guardar dirección inicial

    // Manejar caso especial de 0
    cbz x1, zero_case

    // Manejar negativos
    cmp x1, #0
    b.gt positive
    neg x1, x1
    mov w5, #'-'
    strb w5, [x4], #1
    add x3, x3, #1

positive:
    // Convertir dígitos (en orden inverso)
convert_loop:
    udiv x5, x1, x2             // x5 = x1 / 10
    msub x6, x5, x2, x1         // x6 = x1 % 10
    add x6, x6, #'0'            // convertir a ASCII
    strb w6, [x4], #1           // almacenar dígito
    add x3, x3, #1              // incrementar contador
    mov x1, x5                  // x1 = cociente
    cbnz x1, convert_loop       // repetir si no es cero

    // Invertir los dígitos en el buffer
    sub x4, x4, #1              // x4 apunta al último dígito
    mov x5, x0                  // x5 apunta al inicio
    add x6, x0, x3              // x6 apunta después del último dígito
    sub x6, x6, #1              // x6 apunta al último dígito

    // Si es negativo, saltar el signo -
    cbz x4, no_negative         // x4 = 0 si no hay dígitos (no debería pasar)
    ldrb w7, [x5]
    cmp w7, #'-'
    b.ne reverse_loop
    add x5, x5, #1              // saltar el signo -

reverse_loop:
    cmp x5, x6
    b.ge reverse_done
    ldrb w7, [x5]               // intercambiar caracteres
    ldrb w8, [x6]
    strb w8, [x5], #1
    strb w7, [x6], #-1
    b reverse_loop

zero_case:
    mov w5, #'0'
    strb w5, [x4]
    mov x0, #1
    ret

no_negative:
    // Caso de error, no debería ocurrir
    mov x0, #0
    ret

reverse_done:
    mov x0, x3                  // devolver longitud
    ret