GNU/Linux xterm-256color bash 150 views

// ****************************************************************************
// * Nombre del archivo: practica.s
// * Descripción: Convertir un numero binario a decimal
// * Autor: Roldan Castro Luis Alberto
// * Fecha: 07-04-2025
// * Plataforma: Raspberry Pi OS (64 bits)
// * Asciinema: https://asciinema.org/a/FmnOH3qWxUddY7HvkB2JW5KjM
// ****************************************************************************

// ****************************************************************************
// Version en C
//
//#include <stdio.h>
//#include <string.h>
//
//int bin_to_dec(const char *bin_str) {
//    int decimal_value = 0;
//    while (*bin_str) {
//        decimal_value = decimal_value * 2 + (*bin_str - '0');
//        bin_str++;
//    }
//    return decimal_value;
//}
//
//int main() {
//    // Cadena binaria de entrada
//    const char *binary_input = "10011";
//
//    // Convertir binario a decimal
//    int decimal_value = bin_to_dec(binary_input);
//
//    // Imprimir los resultados
//    printf("El numero binario es: %s\n", binary_input);
//    printf("y su valor decimal es: %d\n", decimal_value);
//
//    return 0;
//}
// ****************************************************************************

.section .data
binary_input:    .asciz "10011\n"        // Número binario de entrada: "10011" (19 en decimal)
decimal_str:     .space 20              // Reservamos espacio para la cadena que almacenará el número decimal
message_bin:     .asciz "El numero binario es: "  // Mensaje previo a la cadena binaria
message_dec:     .asciz " y su valor decimal es: "  // Mensaje que precede el valor decimal

.section .text
.global _start  // Especificamos el punto de inicio del programa

_start:
    ldr x0, =message_bin    // Cargamos la dirección del mensaje de "El numero binario es: " en x0
    bl print_string         // Llamamos a la función para imprimir el mensaje

    ldr x0, =binary_input   // Cargamos la dirección del número binario en x0
    bl print_string_bin     // Llamamos a la función para imprimir el número binario

    ldr x0, =message_dec    // Cargamos la dirección del mensaje " y su valor decimal es: " en x0
    bl print_string         // Llamamos a la función para imprimir el mensaje

    ldr x0, =binary_input   // Cargamos la dirección de la cadena binaria
    mov x1, #0              // Inicializamos el valor de x1 (resultado decimal) a 0

// INICIO DE LA CONVERSIÓN DE BINARIO A DECIMAL
loop_bin:
    ldrb w2, [x0], #1       // Leemos el siguiente byte (carácter) de la cadena binaria
    cmp w2, #'0'             // Comparamos el byte con '0'
    beq bit_is_zero          // Si es un '0', saltamos a la etiqueta 'bit_is_zero'
    cmp w2, #'1'             // Comparamos el byte con '1'
    beq bit_is_one           // Si es un '1', saltamos a la etiqueta 'bit_is_one'
    cmp w2, #'\n'            // Comparamos el byte con el carácter de nueva línea ('\n')
    beq convert_done         // Si encontramos el final de la cadena binaria, saltamos a 'convert_done'
    b loop_bin               // Si el byte no es '0', '1' ni '\n', continuamos el bucle

bit_is_zero:
    lsl x1, x1, #1           // Si el bit es 0, desplazamos el resultado a la izquierda (multiplicamos por 2)
    b loop_bin               // Continuamos con el siguiente bit

bit_is_one:
    lsl x1, x1, #1           // Si el bit es 1, desplazamos el resultado a la izquierda (multiplicamos por 2)
    add x1, x1, #1           // Sumamos 1 al resultado (por el bit 1)
    b loop_bin               // Continuamos con el siguiente bit

convert_done:
    ldr x2, =decimal_str + 19 // Cargamos la dirección del último espacio en la cadena decimal
    mov w3, #0x0A            // Cargamos el valor ASCII de la nueva línea ('\n')
    strb w3, [x2, #-1]!      // Guardamos la nueva línea en la cadena decimal

    mov x3, x1               // Copiamos el valor decimal a x3
    cbz x3, print_zero       // Si el valor decimal es 0, saltamos a 'print_zero' para imprimir 0

// CONVERSIÓN DE DECIMAL A CADENA ASCII (de derecha a izquierda)
convert_loop:
    mov x4, #10              // Cargamos el valor 10 (base decimal)
    udiv x5, x3, x4          // x5 = x3 / 10 (división entera)
    msub x6, x5, x4, x3      // x6 = x3 - x5 * 10 (el resto de la división, el dígito)
    add x6, x6, #'0'         // Convertimos el dígito a ASCII sumando el valor de '0'
    strb w6, [x2, #-1]!      // Almacenamos el carácter en la cadena
    mov x3, x5               // Actualizamos x3 con el cociente (dividido por 10)
    cbnz x3, convert_loop    // Si x3 no es cero, continuamos el bucle

    b print_decimal          // Una vez terminada la conversión, saltamos a 'print_decimal'

print_zero:
    mov w6, #'0'             // Si el número decimal es 0, colocamos el valor '0' en la cadena
    strb w6, [x2, #-1]!      // Guardamos el '0' en la cadena

print_decimal:
    mov x0, #1               // Preparamos para escribir en la salida estándar (stdout)
    mov x1, x2               // Pasamos la dirección de la cadena decimal a x1
    ldr x3, =decimal_str + 20 // Cargamos la dirección del final de la cadena decimal
    sub x2, x3, x2           // Calculamos la longitud de la cadena (fin - inicio)
    mov x2, x2               // Longitud de la cadena
    mov x8, #64              // Preparamos la llamada al sistema para escribir (syscall: write)
    svc #0                   // Realizamos la llamada al sistema para escribir

    mov x0, #0               // Preparamos para salir del programa
    mov x8, #93              // Preparamos la llamada al sistema para salir (syscall: exit)
    svc #0                   // Llamada al sistema para terminar el programa

// -----------------------------------------------------------
// Función para imprimir una cadena de caracteres hasta '\0'
print_string:
    mov x1, x0               // Cargamos la dirección de la cadena en x1
    mov x2, #0               // Inicializamos el índice de la cadena a 0

print_string_loop:
    ldrb w3, [x1, x2]        // Leemos un byte de la cadena
    cmp w3, #0               // Comparamos con el byte nulo '\0' (fin de la cadena)
    beq print_string_done    // Si es el final de la cadena, terminamos
    add x2, x2, #1           // Avanzamos al siguiente carácter
    b print_string_loop      // Continuamos el bucle

print_string_done:
    mov x0, #1               // Preparamos la llamada al sistema para escribir en stdout
    mov x8, #64              // syscall: write
    svc #0                   // Realizamos la llamada al sistema para escribir
    ret                      // Retornamos de la función

// -----------------------------------------------------------
// Función para imprimir la cadena binaria hasta el salto de línea '\n'
print_string_bin:
    mov x1, x0               // Cargamos la dirección de la cadena binaria en x1
    mov x2, #0               // Inicializamos el índice de la cadena a 0

print_string_loop_bin:
    ldrb w3, [x1, x2]        // Leemos un byte de la cadena binaria
    cmp w3, #'\n'            // Comparamos con el salto de línea '\n'
    beq print_string_bin_done // Si encontramos '\n', terminamos
    add x2, x2, #1           // Avanzamos al siguiente carácter
    b print_string_loop_bin  // Continuamos el bucle

print_string_bin_done:
    mov x0, #1               // Preparamos para escribir en la salida estándar (stdout)
    mov x8, #64              // syscall: write
    svc #0                   // Realizamos la llamada al sistema para escribir
    ret                      // Retornamos de la función