//=========================================================================
// Nombre del estudiante: Vargas Perez Leonardo Gael
// Fecha de creación: 2025-04-09
// Descripción: Programa que cuenta las ocurrencias de una letra en una cadena
// Link asciinema: [https://asciinema.org/a/4ftk4GL6utyBtPXdtYohod6rB]
//=========================================================================
// Versión alternativa en Python:
// python // cadena = input("Ingrese una cadena: ") // letra = input("Ingrese la letra a buscar: ") // if len(letra) != 1: // print("Error: Debe ingresar exactamente un carácter") // else: // print(f"La letra '{letra}' aparece {cadena.count(letra)} veces") //
//=========================================================================
.section .data
// Mensajes para el usuario
prompt_str: .asciz "Ingrese una cadena: "
prompt_char: .asciz "Ingrese la letra a buscar: "
result_msg1: .asciz "La letra '"
result_msg2: .asciz "' aparece "
result_msg3: .asciz " veces.\n"
error_msg: .asciz "Error: Debe ingresar exactamente un carácter.\n"
newline: .asciz "\n"
.section .bss
// Buffers para entrada/salida
input_str: .skip 256 // Buffer para la cadena (255 caracteres + null)
input_char: .skip 4 // Buffer para el carácter (1 char + \n + null)
count_str: .skip 21 // Buffer para el contador como string
.section .text .global _start
_start:
// ----- Fase 1: Leer entrada del usuario -----
// Solicitar cadena principal
ldr x0, =prompt_str
bl print_string
ldr x0, =input_str
mov x1, #256
bl read_input
// Solicitar carácter a buscar
ldr x0, =prompt_char
bl print_string
ldr x0, =input_char
mov x1, #4
bl read_input
// ----- Fase 2: Validar entrada -----
// Verificar que se ingresó exactamente 1 carácter
ldr x0, =input_char
ldrb w1, [x0, #1] // Segundo byte
cbz w1, valid_input // Null terminator es válido
cmp w1, #10 // Newline también es válido
beq valid_input
b invalid_input // Cualquier otra cosa es error
valid_input:
// ----- Fase 3: Procesamiento -----
// Cargar carácter a buscar
ldr x0, =input_char
ldrb w19, [x0] // w19 = carácter a buscar (byte)
// Contar ocurrencias en la cadena
ldr x0, =input_str
mov w1, w19
bl count_occurrences
mov x20, x0 // x20 = contador de ocurrencias
// ----- Fase 4: Mostrar resultados -----
// Construir mensaje de resultado
ldr x0, =result_msg1
bl print_string
// Imprimir el carácter buscado (seguro usando stack)
sub sp, sp, #16 // Reservar espacio en stack
strb w19, [sp, #8] // Almacenar carácter
mov x0, #1 // stdout
add x1, sp, #8 // Dirección del carácter
mov x2, #1 // Longitud 1 byte
mov x8, #64 // syscall write
svc #0
add sp, sp, #16 // Liberar stack
ldr x0, =result_msg2
bl print_string
// Convertir y mostrar el contador
mov x0, x20
ldr x1, =count_str
bl int_to_string
ldr x0, =count_str
bl print_string
ldr x0, =result_msg3
bl print_string
b exit
invalid_input:
ldr x0, =error_msg
bl print_string
exit:
// Terminar programa exitosamente
mov x0, #0 // Código de retorno 0
mov x8, #93 // syscall exit
svc #0
// ==================== SUBRUTINAS ====================
//—————————————————– // count_occurrences - Cuenta apariciones de un carácter // Entrada: x0 = dirección de la cadena // w1 = carácter a buscar (byte) // Salida: x0 = número de ocurrencias //—————————————————– count_occurrences:
mov x2, #0 // Inicializar contador
count_loop:
ldrb w3, [x0], #1 // Cargar byte y avanzar puntero
cbz w3, count_done // Terminar al llegar a null
cmp w3, w1 // Comparar con el carácter buscado
bne count_loop // Si no coincide, continuar
add x2, x2, #1 // Incrementar contador
b count_loop
count_done:
mov x0, x2 // Devolver resultado
ret
//—————————————————– // print_string - Imprime una cadena terminada en null // Entrada: x0 = dirección de la cadena //—————————————————– print_string:
mov x1, x0 // Guardar dirección
mov x2, #0 // Inicializar contador de longitud
str_len_loop:
ldrb w3, [x1, x2] // Cargar byte actual
cbz w3, str_print // Si es null, terminar
add x2, x2, #1 // Incrementar contador
b str_len_loop
str_print:
mov x1, x0 // Dirección de la cadena
mov x0, #1 // stdout
mov x8, #64 // syscall write
svc #0
ret
//—————————————————– // read_input - Lee entrada del usuario // Entrada: x0 = buffer de destino // x1 = tamaño máximo del buffer //—————————————————– read_input:
mov x2, x1 // Tamaño máximo
mov x1, x0 // Buffer de destino
mov x0, #0 // stdin
mov x8, #63 // syscall read
svc #0
ret
//—————————————————– // int_to_string - Convierte entero a string // Entrada: x0 = número a convertir // x1 = buffer de destino //—————————————————– int_to_string:
mov x2, x1 // Guardar buffer destino
mov x3, #10 // Base 10
mov x4, #0 // Contador de dígitos
// Caso especial para 0
cbz x0, handle_zero
conversion_loop:
udiv x5, x0, x3 // Dividir por 10
msub x6, x5, x3, x0 // Obtener residuo
add x6, x6, #'0' // Convertir a ASCII
strb w6, [x1, x4] // Almacenar dígito
add x4, x4, #1 // Incrementar contador
mov x0, x5 // Actualizar número
cbnz x0, conversion_loop // Continuar si no es cero
// Terminar cadena
mov w5, #0
strb w5, [x1, x4]
// Invertir los dígitos
mov x5, #0 // Índice inicial
sub x6, x4, #1 // Índice final
reverse_loop:
cmp x5, x6
bge conversion_done
ldrb w7, [x1, x5] // Intercambiar
ldrb w8, [x1, x6] // caracteres
strb w8, [x1, x5]
strb w7, [x1, x6]
add x5, x5, #1
sub x6, x6, #1
b reverse_loop
handle_zero:
mov w5, #'0'
strb w5, [x1]
mov w5, #0
strb w5, [x1, #1]
conversion_done:
ret
// Fin del programa