GNU/Linux xterm-256color bash 145 views

/*
Autor: Victor Manuel Madrid Lugo
Fecha: 08/04/2025
Descripción: Imprime la fecha actual del sistema
Demostración: [https://asciinema.org/a/9fllKL8vwWmKhAgTISz9lV5aW]
*/

/*
Equivalente en Python:

import time
from datetime import datetime

def main():
    try:
        # Obtener el tiempo actual
        current_time = time.time()
        
        # Convertir a formato legible
        date_string = datetime.fromtimestamp(current_time).strftime('%d/%m/%Y %H:%M:%S')
        
        # Imprimir el resultado
        print(f"Fecha actual: {date_string}")
    except Exception as e:
        print(f"Error al obtener la fecha: {e}")

if __name__ == "__main__":
    main()
*/
.global _start

.data
msg_fecha:     .asciz "Fecha actual: "
msg_fecha_len = . - msg_fecha

buffer:        .space 128
formato:       .asciz "%d/%m/%Y %H:%M:%S"
formato_len = . - formato

error_msg:     .asciz "Error al obtener la fecha\n"
error_msg_len = . - error_msg

newline:       .asciz "\n"

.text
_start:
    // Reservar espacio para la estructura timespec (tiempo actual)
    sub sp, sp, #32
    mov x0, sp          // x0 = puntero a timespec

    // Llamar a clock_gettime(CLOCK_REALTIME, timespec)
    mov x8, #113        // syscall clock_gettime
    mov x1, x0          // x1 = puntero a timespec
    mov x0, #0          // CLOCK_REALTIME
    svc 0
    
    // Verificar error
    cmp x0, #0
    bne error
    
    // Cargar el tiempo (time_t) desde la estructura timespec
    ldr x0, [sp]        // x0 = time_t (segundos desde epoch)
    
    // Reservar espacio para la estructura tm
    sub sp, sp, #64
    
    // Llamar a localtime_r(time_t, struct tm *)
    // Necesitamos usar la syscall mmap para conseguir memoria para la función
    mov x8, #222        // syscall mmap
    mov x0, #0          // NULL (dejar que el kernel decida la dirección)
    mov x1, #4096       // tamaño de página
    mov x2, #3          // PROT_READ | PROT_WRITE
    mov x3, #0x22       // MAP_PRIVATE | MAP_ANONYMOUS
    mov x4, #-1         // fd = -1
    mov x5, #0          // offset = 0
    svc 0
    
    // Verificar error en mmap
    cmp x0, #0
    ble error
    
    // Guardar la dirección de memoria asignada
    mov x19, x0
    
    // Preparar parámetros para syscall nanosleep (para simular localtime)
    // En sistemas reales se usaría la biblioteca libc para localtime
    ldr x0, [sp, #64]   // Cargar time_t
    
    // Imprime el mensaje "Fecha actual: "
    mov x0, #1          // stdout
    ldr x1, =msg_fecha
    mov x2, msg_fecha_len
    mov x8, #64         // syscall write
    svc 0
    
    // Como no podemos llamar a funciones de biblioteca, simulemos la fecha
    // con el valor bruto de epoch

    // Convertir segundos desde epoch a tiempo legible
    // Nota: Normalmente usaríamos strftime, pero en puro assembly
    // implementaremos algo básico
    ldr x0, [sp, #64]   // Cargar time_t
    
    // Imprimir los segundos desde epoch como texto
    bl print_int
    
    // Imprimir nueva línea
    mov x0, #1
    ldr x1, =newline
    mov x2, #1
    mov x8, #64
    svc 0
    
    // Liberar memoria asignada con mmap
    mov x8, #215        // syscall munmap
    mov x0, x19         // dirección a liberar
    mov x1, #4096       // tamaño
    svc 0
    
    // Limpieza y salida
    add sp, sp, #96     // restaurar pila
    mov x0, #0          // código de salida exitoso
    mov x8, #93         // syscall exit
    svc 0

error:
    // Imprimir mensaje de error
    mov x0, #2          // stderr
    ldr x1, =error_msg
    mov x2, error_msg_len
    mov x8, #64         // syscall write
    svc 0
    
    // Salir con código de error
    mov x0, #1          // código de error
    mov x8, #93         // syscall exit
    svc 0

// Función para imprimir un entero (simplificada)
print_int:
    // Guardar registros
    sub sp, sp, #48
    str x19, [sp, #0]
    str x20, [sp, #8]
    str x21, [sp, #16]
    str x22, [sp, #24]
    str x30, [sp, #32]   // Link register
    
    mov x19, x0         // Guardar el valor a imprimir
    
    // Asignar buffer en la pila
    sub sp, sp, #32     // 32 bytes para el buffer
    mov x21, sp         // x21 = buffer
    
    // Manejar caso especial de 0
    cmp x19, #0
    bne convert_loop
    mov w22, #'0'
    strb w22, [x21]
    mov x20, #1         // Longitud = 1
    b print_digits
    
convert_loop:
    mov x20, #0         // x20 = contador de dígitos
    mov x22, x19        // x22 = valor a convertir
    
    // Obtener dígitos en orden inverso
loop:
    cmp x22, #0
    beq reverse_digits
    mov x0, x22
    mov x1, #10
    udiv x2, x0, x1     // x2 = x0 / 10
    msub x3, x2, x1, x0 // x3 = x0 - (x2 * 10) = x0 % 10
    
    add w3, w3, #'0'    // Convertir a ASCII
    strb w3, [x21, x20] // Guardar en buffer
    add x20, x20, #1    // Incrementar contador
    
    mov x22, x2         // Continuar con el cociente
    b loop
    
reverse_digits:
    // Invertir los dígitos (si hay más de 1)
    cmp x20, #1
    ble print_digits
    
    mov x0, #0          // índice inicio
    sub x1, x20, #1     // índice fin
    
reverse_loop:
    cmp x0, x1
    bge print_digits
    
    ldrb w2, [x21, x0]  // cargar byte de inicio
    ldrb w3, [x21, x1]  // cargar byte de fin
    
    strb w3, [x21, x0]  // intercambiar
    strb w2, [x21, x1]
    
    add x0, x0, #1
    sub x1, x1, #1
    b reverse_loop
    
print_digits:
    // Agregar terminador nulo por seguridad
    mov w22, #0
    strb w22, [x21, x20]
    
    // Imprimir los dígitos
    mov x0, #1          // stdout
    mov x1, x21         // buffer
    mov x2, x20         // longitud
    mov x8, #64         // syscall write
    svc 0
    
    // Limpiar y restaurar
    add sp, sp, #32     // liberar buffer
    ldr x19, [sp, #0]
    ldr x20, [sp, #8]
    ldr x21, [sp, #16]
    ldr x22, [sp, #24]
    ldr x30, [sp, #32]  // Link register
    add sp, sp, #48
    ret