Programa 40: Juego de piedra, papel o tijeras con la computadora en Assembly ARM64 - Alejandro Suarez
by pepinisillo
GNU/Linux
•
xterm
•
bash
105 views
📌 Demostración: Juego de piedra, papel o tijeras con la computadora en ARM64 Assembly
💻 Lenguajes de Interfaz en TECNM Campus ITT
👨💻 Autor: Alejandro Suarez Sandoval
📅 Fecha: 2025/04/10
🎯 Descripción
Este programa es un juego de piedra, papel o tijeras contra con la computadora.
La implementación se realiza en:
✅ Assembly ARM64 para RaspbianOS en Raspberry Pi
🔧 Compilación en Raspberry Pi (ARM64)
as jankenpon.s -o jankenpon.o
ld jankenpon.o -o jankenpon
▶️ Ejecución
./jankenpon
👀 Código fuente
🔗 Código fuente en Gist: Programa 40 Juego de piedra, papel o tijeras con la computadora mostrando resultado del juego 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 Juego de piedra, papel o tijeras contra la |
| computadora en Rust y Assembly ARM64 para RaspbianOS. |
| • Demostración: |
| https://asciinema.org/a/714719 |
| • Compilación (Raspberry Pi ARM64): |
| as jankenpon.s -o jankenpon.o |
| ld jankenpon.o -o jankenpon |
| • Ejecución: ./jankenpon |
 ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
⠂⠄⠄⠂⠁⠁⠂⠄⠄⠂⠁⠁⠂⠄⠄⠂ ⠂⠄⠄⠂☆
═════════•°• Demostración Código en lenguaje Rust •°•═══════
use std::io::{self, Write};
use rand::Rng;
#[derive(Debug, Clone, Copy, PartialEq)]
enum Opcion {
Piedra = 1,
Papel = 2,
Tijeras = 3,
}
#[derive(Debug)]
enum Resultado {
Ganas,
Pierdes,
Empate,
}
fn numero_a_opcion(num: u8) -> Option<Opcion> {
match num {
1 => Some(Opcion::Piedra),
2 => Some(Opcion::Papel),
3 => Some(Opcion::Tijeras),
_ => None,
}
}
fn opcion_a_texto(opcion: Opcion) -> &'static str {
match opcion {
Opcion::Piedra => "Piedra",
Opcion::Papel => "Papel",
Opcion::Tijeras => "Tijeras",
}
}
fn determinar_ganador(usuario: Opcion, computadora: Opcion) -> Resultado {
if usuario == computadora {
return Resultado::Empate;
}
match (usuario, computadora) {
(Opcion::Piedra, Opcion::Tijeras) => Resultado::Ganas,
(Opcion::Papel, Opcion::Piedra) => Resultado::Ganas,
(Opcion::Tijeras, Opcion::Papel) => Resultado::Ganas,
_ => Resultado::Pierdes,
}
}
fn obtener_eleccion_usuario() -> Option<Opcion> {
print!("Elige: 1-Piedra, 2-Papel, 3-Tijeras, 0-Salir: ");
io::stdout().flush().unwrap();
let mut entrada = String::new();
io::stdin().read_line(&mut entrada).expect("Error al leer la entrada");
let num = entrada.trim().parse::<u8>().ok()?;
if num == 0 {
return None;
}
numero_a_opcion(num)
}
fn eleccion_computadora() -> Opcion {
let mut rng = rand::thread_rng();
let num = rng.gen_range(1..=3);
numero_a_opcion(num).unwrap()
}
fn main() {
println!("¡Bienvenido a Piedra, Papel o Tijeras!");
loop {
let opcion_usuario = match obtener_eleccion_usuario() {
Some(opcion) => opcion,
None => {
println!("¡Gracias por jugar! Adiós.");
break;
}
};
println!("Tu elección: {}", opcion_a_texto(opcion_usuario));
let opcion_computadora = eleccion_computadora();
println!("PC eligió: {}", opcion_a_texto(opcion_computadora));
match determinar_ganador(opcion_usuario, opcion_computadora) {
Resultado::Ganas => println!("¡Ganaste!"),
Resultado::Pierdes => println!("¡Perdiste!"),
Resultado::Empate => println!("¡Empate!"),
}
println!();
}
}
════════════════════•°• ☆ •°•══════════════════════════════
/*
/* ⠂⠄⠄⠂⠁⠁⠂⠄⠄⠂⠁⠁⠂⠄⠄⠂ ⠂⠄⠄⠂☆
═════════════•°• Código en ARM64 Assembly •°•═════════════ */
// Constantes
.equ SYS_READ, 63 // Syscall para leer
.equ SYS_WRITE, 64 // Syscall para escribir
.equ SYS_EXIT, 93 // Syscall para salir
.equ STDIN, 0 // Descriptor de archivo para entrada estándar
.equ STDOUT, 1 // Descriptor de archivo para salida estándar
.equ STDERR, 2 // Descriptor de archivo para error estándar
.equ PIEDRA, 1 // Valor para piedra
.equ PAPEL, 2 // Valor para papel
.equ TIJERAS, 3 // Valor para tijeras
.equ MAX_RAND, 3 // Valor máximo para generación aleatoria
.section .data
// Constantes para el generador congruencial lineal
lcg_a:
.quad 6364136223846793005
lcg_c:
.quad 1442695040888963407
bienvenida:
.ascii "¡Bienvenido al juego de Piedra, Papel o Tijeras!\n\n"
bienvenida_len = . - bienvenida
menu:
.ascii "Escoge una opción:\n"
.ascii "1. Piedra\n"
.ascii "2. Papel\n"
.ascii "3. Tijeras\n"
.ascii "0. Salir\n"
.ascii "Tu elección: "
menu_len = . - menu
eleccion_pc:
.ascii "La computadora eligió: "
eleccion_pc_len = . - eleccion_pc
piedra_str:
.ascii "Piedra\n"
piedra_len = . - piedra_str
papel_str:
.ascii "Papel\n"
papel_len = . - papel_str
tijeras_str:
.ascii "Tijeras\n"
tijeras_len = . - tijeras_str
ganaste:
.ascii "¡Has ganado!\n\n"
ganaste_len = . - ganaste
perdiste:
.ascii "¡Has perdido!\n\n"
perdiste_len = . - perdiste
empate:
.ascii "¡Empate!\n\n"
empate_len = . - empate
opcion_invalida:
.ascii "Opción inválida. Intenta de nuevo.\n\n"
opcion_invalida_len = . - opcion_invalida
adios:
.ascii "¡Gracias por jugar! ¡Hasta pronto!\n"
adios_len = . - adios
.section .bss
.lcomm buffer, 8 // Buffer para la entrada del usuario
.lcomm seed, 8 // Semilla para el generador de números aleatorios
.section .text
.global _start
_start:
// Inicializar la semilla con el tiempo actual (contador de ciclos)
mrs x0, CNTVCT_EL0 // Leer el contador de ciclos virtual
adr x20, seed // Obtener la dirección de seed
str x0, [x20] // Guardar como semilla
// Mostrar mensaje de bienvenida
mov x0, STDOUT
adr x1, bienvenida
mov x2, bienvenida_len
mov x8, SYS_WRITE
svc 0
main_loop:
// Mostrar menú
mov x0, STDOUT
adr x1, menu
mov x2, menu_len
mov x8, SYS_WRITE
svc 0
// Leer elección del usuario
mov x0, STDIN
adr x1, buffer
mov x2, 8
mov x8, SYS_READ
svc 0
// Procesar la elección del usuario
ldrb w19, [x1] // Cargar el primer byte
sub w19, w19, '0' // Convertir ASCII a entero
// Comprobar si el usuario quiere salir
cmp w19, 0
beq salir
// Comprobar si la elección es válida
cmp w19, 1
blt opcion_invalida_msg
cmp w19, 3
bgt opcion_invalida_msg
// La elección es válida, generar la elección de la computadora
bl random
mov w20, w0 // w20 = elección de la computadora (1-3)
// Mostrar la elección de la computadora
mov x0, STDOUT
adr x1, eleccion_pc
mov x2, eleccion_pc_len
mov x8, SYS_WRITE
svc 0
// Imprimir la elección de la computadora
cmp w20, PIEDRA
beq imprimir_piedra
cmp w20, PAPEL
beq imprimir_papel
cmp w20, TIJERAS
beq imprimir_tijeras
continuar_despues_imprimir:
// Determinar el resultado
cmp w19, w20
beq es_empate
// Comprobar si el usuario gana
cmp w19, PIEDRA
beq check_piedra
cmp w19, PAPEL
beq check_papel
cmp w19, TIJERAS
beq check_tijeras
b main_loop
check_piedra:
cmp w20, TIJERAS
beq usuario_gana
b usuario_pierde
check_papel:
cmp w20, PIEDRA
beq usuario_gana
b usuario_pierde
check_tijeras:
cmp w20, PAPEL
beq usuario_gana
b usuario_pierde
imprimir_piedra:
mov x0, STDOUT
adr x1, piedra_str
mov x2, piedra_len
mov x8, SYS_WRITE
svc 0
b continuar_despues_imprimir
imprimir_papel:
mov x0, STDOUT
adr x1, papel_str
mov x2, papel_len
mov x8, SYS_WRITE
svc 0
b continuar_despues_imprimir
imprimir_tijeras:
mov x0, STDOUT
adr x1, tijeras_str
mov x2, tijeras_len
mov x8, SYS_WRITE
svc 0
b continuar_despues_imprimir
es_empate:
mov x0, STDOUT
adr x1, empate
mov x2, empate_len
mov x8, SYS_WRITE
svc 0
b main_loop
usuario_gana:
mov x0, STDOUT
adr x1, ganaste
mov x2, ganaste_len
mov x8, SYS_WRITE
svc 0
b main_loop
usuario_pierde:
mov x0, STDOUT
adr x1, perdiste
mov x2, perdiste_len
mov x8, SYS_WRITE
svc 0
b main_loop
opcion_invalida_msg:
mov x0, STDOUT
adr x1, opcion_invalida
mov x2, opcion_invalida_len
mov x8, SYS_WRITE
svc 0
b main_loop
salir:
// Mostrar mensaje de despedida
mov x0, STDOUT
adr x1, adios
mov x2, adios_len
mov x8, SYS_WRITE
svc 0
// Salir del programa
mov x0, 0
mov x8, SYS_EXIT
svc 0
// Función para generar un número aleatorio entre 1 y 3
random:
// Cargar la semilla actual
adr x3, seed
ldr x0, [x3]
// Cargar las constantes desde la sección de datos
adr x1, lcg_a
ldr x1, [x1]
adr x2, lcg_c
ldr x2, [x2]
// Realizar la operación del LCG: x_next = (a * x + c) mod 2^64
mul x0, x0, x1
add x0, x0, x2
str x0, [x3] // Guardar la nueva semilla
// Reducir al rango [1,3]
lsr x0, x0, 32 // Usar los bits superiores que tienen mejor distribución
mov x1, MAX_RAND
udiv x2, x0, x1
msub x0, x2, x1, x0 // x0 = x0 % MAX_RAND (0-2)
add w0, w0, 1 // Convertir a rango 1-3
ret