GNU/Linux xterm bash 84 views

📌 Demostración: Multiplicación de dos números en ARM64 Assembly

💻 Lenguajes de Interfaz en TECNM Campus ITT
👨‍💻 Autor: Alejandro Suarez Sandoval
📅 Fecha: 2025/04/10

🎯 Descripción

Este programa multiplica dos números ingresados por un usuario.
La implementación se realiza en:

Assembly ARM64 para RaspbianOS en Raspberry Pi

🔧 Compilación en Raspberry Pi (ARM64)

as multiplicacion.s -o multiplicacion.o  
ld multiplicacion.o -o multiplicacion

▶️ Ejecución

./multiplicacion

👀 Código fuente

🔗 Código fuente en Gist: Programa 33 Multiplicación de dos números mostrando resultado en terminal Código Assembly ARM64 para RaspbianOS

/*
 ______  ____               ____  __ __      
/\  _  \/\  _`\   /'\_/`\  /'___\/\ \\ \     
\ \ \L\ \ \ \L\ \/\      \/\ \__/\ \ \\ \    
 \ \  __ \ \ ,  /\ \ \__\ \ \  _``\ \ \\ \_  
  \ \ \/\ \ \ \\ \\ \ \_/\ \ \ \L\ \ \__ ,__\
   \ \_\ \_\ \_\ \_\ \_\\ \_\ \____/\/_/\_\_/
    \/_/\/_/\/_/\/ /\/_/ \/_/\/___/    \/_/  
                                             
♡ ∩_∩ 
(„• ֊ •„)♡
| ̄U U ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄| 
| • Lenguajes de Interfaz en TECNM Campus ITT                            |   
| • Autor: Alejandro Suarez Sandoval                                     | 
| • Fecha: 2025/04/10                                                    | 
| • Descripción: Programa que multiplica dos numeros y muestra el        |
|   el resultado en terminal en Go y Assembly ARM64 para RaspbianOS.     | 
| • Demostración:                                                        |
|   https://asciinema.org/a/714484                                       |
| • Compilación (Raspberry Pi ARM64):                                    |  
|     as multiplicacion.s -o multiplicacion.o                            |  
|     ld multiplicacion.o -o multiplicacion                              |  
| • Ejecución: ./multiplicacion                                          |  
 ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄                                        

⠂⠄⠄⠂⠁⠁⠂⠄⠄⠂⠁⠁⠂⠄⠄⠂ ⠂⠄⠄⠂☆
═════════•°• Demostración Código en lenguaje Go •°•═══════

package main

import "fmt"

func main() {
    var a, b float64
    fmt.Print("Ingrese primer número: ")
    fmt.Scan(&a)
    fmt.Print("Ingrese segundo número: ")
    fmt.Scan(&b)
    fmt.Printf("Resultado: %.2f\n", a*b)
}

════════════════════•°• ☆ •°•══════════════════════════════
/*

/* ⠂⠄⠄⠂⠁⠁⠂⠄⠄⠂⠁⠁⠂⠄⠄⠂ ⠂⠄⠄⠂☆
═════════════•°• Código en ARM64 Assembly •°•═════════════ */

// Multiplicador de números en ARM64 (aarch64)
// Ensamblado con: as -o multiplicar.o multiplicar.s && ld -o multiplicar multiplicar.o

.global _start

.section .data
    prompt1:    .asciz "Ingrese el primer número: "
    len_prompt1 = . - prompt1
    
    prompt2:    .asciz "Ingrese el segundo número: "
    len_prompt2 = . - prompt2
    
    result_msg: .asciz "El resultado de la multiplicación es: "
    len_result = . - result_msg
    
    newline:    .asciz "\n"
    
    // Buffer para entrada (10 dígitos + newline + null)
    buffer:     .fill 12, 1, 0

.section .text
_start:
    // Mostrar primer prompt
    mov x0, #1          // stdout
    ldr x1, =prompt1
    ldr x2, =len_prompt1
    mov x8, #64         // sys_write
    svc #0
    
    // Leer primer número
    mov x0, #0          // stdin
    ldr x1, =buffer
    mov x2, #12         // tamaño del buffer
    mov x8, #63         // sys_read
    svc #0
    
    // Convertir primer número a entero
    ldr x1, =buffer
    bl atoi
    mov x19, x0         // Guardar primer número en x19
    
    // Mostrar segundo prompt
    mov x0, #1          // stdout
    ldr x1, =prompt2
    ldr x2, =len_prompt2
    mov x8, #64         // sys_write
    svc #0
    
    // Leer segundo número
    mov x0, #0          // stdin
    ldr x1, =buffer
    mov x2, #12         // tamaño del buffer
    mov x8, #63         // sys_read
    svc #0
    
    // Convertir segundo número a entero
    ldr x1, =buffer
    bl atoi
    mov x20, x0         // Guardar segundo número en x20
    
    // Multiplicar los números
    mul x21, x19, x20   // x21 = x19 * x20
    
    // Mostrar mensaje de resultado
    mov x0, #1          // stdout
    ldr x1, =result_msg
    ldr x2, =len_result
    mov x8, #64         // sys_write
    svc #0
    
    // Convertir resultado a string y mostrar
    mov x0, x21         // Número a convertir
    ldr x1, =buffer     // Buffer para el string
    bl itoa
    
    // Calcular longitud del string
    ldr x1, =buffer
    bl strlen
    mov x2, x0          // Longitud en x2
    
    // Mostrar el número
    mov x0, #1          // stdout
    ldr x1, =buffer
    mov x8, #64         // sys_write
    svc #0
    
    // Mostrar nueva línea
    mov x0, #1          // stdout
    ldr x1, =newline
    mov x2, #1          // longitud
    mov x8, #64         // sys_write
    svc #0
    
    // Salir
    mov x0, #0          // status 0
    mov x8, #93         // sys_exit
    svc #0

// Función atoi: convierte string a entero
// Entrada: x1 = dirección del string
// Salida: x0 = valor entero
atoi:
    mov x0, #0          // Inicializar resultado
    mov x2, #10         // Base 10
    mov x3, #0          // Índice
    
atoi_loop:
    ldrb w4, [x1, x3]   // Cargar byte
    cmp w4, #0xA        // Verificar si es newline
    b.eq atoi_done
    cmp w4, #0          // Verificar si es null
    b.eq atoi_done
    
    // Verificar que sea dígito (0-9)
    cmp w4, #'0'
    b.lo atoi_done
    cmp w4, #'9'
    b.hi atoi_done
    
    sub w4, w4, #'0'    // Convertir a valor numérico
    mul x0, x0, x2      // resultado *= 10
    add x0, x0, x4      // resultado += dígito
    
    add x3, x3, #1      // Incrementar índice
    b atoi_loop
    
atoi_done:
    ret

// Función itoa: convierte entero a string
// Entrada: x0 = número, x1 = dirección del buffer
// Salida: buffer lleno con el string
itoa:
    mov x2, #10         // Base 10
    mov x3, #0          // Contador de dígitos
    mov x4, x1          // Guardar dirección del buffer
    
    // Caso especial para 0
    cmp x0, #0
    b.ne itoa_loop
    mov w5, #'0'
    strb w5, [x1]
    mov w5, #0
    strb w5, [x1, #1]
    ret
    
itoa_loop:
    cmp x0, #0
    b.eq itoa_reverse
    
    udiv x5, x0, x2     // x5 = x0 / 10
    msub x6, x5, x2, x0 // x6 = x0 % 10 (resto)
    add w6, w6, #'0'    // Convertir a ASCII
    
    // Guardar dígito (en orden inverso)
    strb w6, [x1], #1
    add x3, x3, #1      // Incrementar contador
    
    mov x0, x5          // x0 = cociente
    b itoa_loop
    
itoa_reverse:
    // Terminar string con null
    mov w5, #0
    strb w5, [x1]
    
    // Ahora invertir los dígitos
    sub x1, x1, #1      // Último dígito escrito
    mov x5, x4          // Inicio del buffer
    
reverse_loop:
    cmp x5, x1
    b.hs reverse_done
    
    // Intercambiar [x5] y [x1]
    ldrb w6, [x5]
    ldrb w7, [x1]
    strb w7, [x5], #1
    strb w6, [x1], #-1
    b reverse_loop
    
reverse_done:
    ret

// Función strlen: calcula longitud de string
// Entrada: x1 = dirección del string
// Salida: x0 = longitud
strlen:
    mov x0, #0          // Contador
    
strlen_loop:
    ldrb w2, [x1, x0]   // Cargar byte
    cmp w2, #0          // Verificar si es null
    b.eq strlen_done
    add x0, x0, #1      // Incrementar contador
    b strlen_loop
    
strlen_done:
    ret