Unidad 4 Programación de dispositivos - JoseCorreaMorales/lenguajes-de-interfaz GitHub Wiki

Unidad 4 - Programación de dispositivos

4.1 El buffer de video en modo texto

El buffer de video en modo texto es un espacio de memoria reservado en la tarjeta gráfica , donde se almacenan los datos que se mostrarán en una pantalla en modo texto. En lenguaje ensamblador, se puede acceder a este buffer para leer o escribir datos directamente en la pantalla. Para esto, se utilizan ciertas instrucciones específicas del procesador y de la tarjeta gráfica, las cuales permiten manipular el contenido del buffer y, por consiguiente, la información mostrada en la pantalla. Es importante destacar que el acceso al buffer de video en modo texto se realiza a través de direcciones de memoria específicas , por lo que se debe tener un conocimiento detallado de la estructura de la memoria del sistema y de los registros relacionados con la tarjeta gráfica.

En relación al buffer de video en modo texto en lenguaje ensamblador, se puede agregar que este se encuentra organizado de manera matricial, donde cada posición del buffer representa un carácter en la pantalla. Cada posición en el buffer contiene información sobre el carácter a mostrar, así como el color de fondo y texto correspondientes. Es importante tener en cuenta que el direccionamiento del buffer es lineal, es decir, las filas se almacenan de manera continua en la memoria del sistema.

En cuanto a su manipulación en lenguaje ensamblador, se pueden utilizar diversas instrucciones para cambiar el contenido del buffer, como MOV, ADD, SUB, entre otras, lo que permite controlar la posición y el valor de los caracteres a mostrar en la pantalla. Además, es posible utilizar interrupciones de pantalla para hacer que la tarjeta gráfica presente en la pantalla la información contenida en el buffer.

En los sistemas x86, el buffer de video en modo texto se encuentra en la memoria de video, específicamente en el rango de direcciones de 0xB8000 a 0xBFFFF. Cada carácter en el modo texto está representado por dos bytes consecutivos en el buffer de video: un byte para el carácter y otro byte para los atributos del carácter.

4.2 Acceso a discos en lenguaje ensamblador

El acceso a discos en lenguaje ensamblador es una técnica utilizada para leer o escribir datos en dispositivos de almacenamiento de datos , como discos duros o unidades flash USB, a través de instrucciones en lenguaje ensamblador . En términos generales, la forma en que se accede a estos dispositivos es mediante la emisión de comandos a través de los puertos de entrada/salida del sistema, específicamente a través del controlador de disco. Por lo tanto, es necesario acceder a la memoria del sistema y a los registros de la tarjeta controladora para poder realizar esta actividad. En resumen, el acceso a discos en lenguaje ensamblador se basa en la emisión de órdenes y la manipulación de datos en la memoria y en los registros de la controladora , que permiten interactuar con el dispositivo de almacenamiento y realizar las operaciones de lectura y escritura en los sectores correspondientes.

En primer lugar, para acceder a un dispositivo de almacenamiento, como un disco duro, se debe identificar el puerto de entrada/salida al que está conectado el dispositivo, así como la dirección de memoria física de la controladora del disco. Luego, se pueden utilizar instrucciones de entrada/salida específicas para leer o escribir datos en los registros de la controladora, que se encargan de coordinar la transferencia de datos entre la memoria del sistema y el dispositivo de almacenamiento.

En el caso de la lectura de datos, se determina la dirección física en el disco donde se encuentra el sector que se quiere leer y se envía una señal a la controladora para que encuentre ese sector y lo lea. En cambio, para escribir, se debe identificar la dirección física en el disco donde se desea escribir y enviar los datos a través de la controladora para que se escriban en ese sector. Es importante tener en cuenta que, para lograr un acceso eficiente y seguro al dispositivo de almacenamiento, es necesario contar con un conocimiento específico de la arquitectura del sistema y de la controladora del disco en particular.

4.3 Programación del puerto seria

La programación del puerto serie en lenguaje ensamblador se utiliza para permitir la comunicación entre un sistema informático y dispositivos externos a través de un puerto serie . Este proceso implica la manipulación de los registros de control del puerto para configurar la velocidad de transmisión, el control de flujo y otros parámetros de comunicación. En lenguaje ensamblador, se pueden utilizar instrucciones específicas para acceder a la memoria y los registros, y así controlar la comunicación a través del puerto serie.

Por ejemplo, se pueden utilizar instrucciones de entrada/salida específicas para leer o escribir datos en los registros del puerto serie, y así enviar y recibir información desde y hacia dispositivos externos. Es importante tener en cuenta que la programación del puerto serie en lenguaje ensamblador requiere un conocimiento detallado de la arquitectura del sistema y de los registros de control del puerto serie en particular.

Se pueden utilizar diversas instrucciones específicas para acceder a los registros del puerto y configurar la velocidad, bits de datos, bits de parada, paridad, entre otros parámetros. Una vez configurado el puerto, se pueden utilizar instrucciones de entrada y salida para leer y escribir datos desde y hacia el puerto serial.

Por lo general, se usan interrupciones para comunicarse con el puerto serial. Cuando el puerto recibe datos, se genera una interrupción que notifica al procesador. Luego se pueden leer los datos desde los registros del puerto serial mediante la utilización de instrucciones específicas, y procesarlos según sea necesario. Del mismo modo, se pueden enviar datos desde el procesador a través del puerto serial utilizando instrucciones específicas, lo que permite comunicarse con dispositivos externos.

4.4 Programación del puerto paralelo

La programación del puerto paralelo en lenguaje ensamblador con sintaxis Intel implica el uso de instrucciones específicas para comunicarse con los registros de control y datos del puerto paralelo. En el caso de la sintaxis Intel, se utilizan las instrucciones de entrada/salida (in/out) para transferir datos entre el procesador y el puerto paralelo.

El puerto paralelo más comúnmente utilizado en las computadoras personales es el LPT1, que tiene 8 bits de datos y algunos registros de control adicionales. Los registros de control se utilizan para configurar el modo de funcionamiento del puerto y controlar las señales de control, como la dirección de datos y las señales de control de hardware.

section .text
    global _start

_start:
    mov dx, 0x378    ; Dirección base del puerto paralelo (LPT1)
    mov al, 0xAA     ; Datos a enviar al puerto paralelo
    out dx, al       ; Escribir los datos en el registro de datos

exit:
    ; Salir del programa
    mov ah, 0x4c
    int 0x21

Es importante tener en cuenta que la programación del puerto paralelo puede variar según el sistema operativo y la configuración de hardware específicos. Además, es posible que se requieran permisos elevados para acceder y programar el puerto paralelo en algunos sistemas operativos.

4.5 Programación híbrida

Es una técnica que combina el uso del lenguaje ensamblador con lenguajes de alto nivel , creando programas que aprovechan las ventajas de ambos enfoques . Esta técnica permite beneficiarse de la velocidad y bajo nivel de programación que ofrece el lenguaje ensamblador, mientras se facilita la programación utilizando lenguajes de alto nivel.

Para implementar esta técnica , se debe utilizar un compilador que permita integrar ambos lenguajes. Se pueden crear rutinas en lenguaje ensamblador que puedan ser invocadas desde un programa en un lenguaje de alto nivel , lo que aporta las ventajas de ambos enfoques. Se pueden utilizar instrucciones específicas de ensamblador para acceder a hardware y memoria, lo que permite una mayor flexibilidad en la programación de dispositivos y sistemas incrustados.

La programación híbrida puede ser útil en diversas situaciones. Por ejemplo, se puede utilizar código ensamblador para optimizar partes críticas de un programa, como bucles o algoritmos intensivos en cálculos. Además, el ensamblador puede ser útil para interactuar con hardware específico o realizar operaciones que no están disponibles directamente en el lenguaje de alto nivel.

Ejemplo con javascript

section .text
    global myAssemblyFunction

myAssemblyFunction:
    mov rdi, hello_msg  ; Puntero al mensaje a imprimir
    mov rax, 0          ; Código de llamada al sistema para escribir en la salida estándar
    mov rsi, 18         ; Longitud del mensaje
    mov rdx, 1          ; Descriptor de archivo para la salida estándar
    syscall             ; Llamada al sistema para escribir el mensaje en la salida estándar

    ret

section .data
    hello_msg db "Función ensamblador llamada.", 10 ; Mensaje a imprimir


var asmModule = (function() {
    "use asm";   // Declaración del modo asm.js

    function myAssemblyFunction() {
        // Código ensamblador aquí
    }

    return {
        myAssemblyFunction: myAssemblyFunction
    };
})();

console.log("Antes de llamar a la función ensamblador.");
asmModule.myAssemblyFunction();  // Llamada a la función ensamblador
console.log("Después de llamar a la función ensamblador.");

4.6 Programación de puerto usb

La programación del puerto USB en lenguaje ensamblador puede ser bastante compleja debido a la naturaleza del protocolo USB y las capas de software involucradas en su funcionamiento. El lenguaje ensamblador generalmente se utiliza en combinación con bibliotecas o controladores específicos para interactuar con el hardware USB.

El estándar USB define una serie de comandos, transferencias y protocolos que se utilizan para enviar y recibir datos a través de los puertos USB. Para programar el puerto USB en ensamblador, necesitarías conocer y comprender estos aspectos del protocolo USB.

La programación del puerto USB ademas implica interactuar directamente con el controlador del bus USB y los registros de hardware para enviar y recibir datos a través del puerto USB. Sin embargo, la programación directa del puerto USB es una tarea compleja debido a la naturaleza del protocolo USB y las capas de software involucradas en su funcionamiento.

El protocolo USB se basa en una estructura jerárquica que consta de varios componentes, como host USB, concentradores, dispositivos y controladores de dispositivos. Cada componente tiene un rol y responsabilidades específicas en el proceso de comunicación.

Ejemplo de como enviar un solo byte con la biblioteca libusb

section .data
    device_handle dd 0

section .text
    extern printf
    extern libusb_init
    extern libusb_open_device_with_vid_pid
    extern libusb_close
    extern libusb_exit
    extern libusb_control_transfer

    global main

main:
    ; Inicializar libusb
    call libusb_init

    ; Abrir dispositivo USB con el Vendor ID (VID) y Product ID (PID) específicos
    push 0x1234 ; VID
    push 0x5678 ; PID
    call libusb_open_device_with_vid_pid
    mov [device_handle], eax

    ; Verificar si se pudo abrir el dispositivo
    cmp [device_handle], 0
    je error

    ; Byte a enviar
    section .data
        byte_to_send db 0xAB

    ; Enviar el byte a través de una transferencia de control
    push [device_handle]   ; Manejador del dispositivo
    push 0x40              ; Tipo de transferencia: Control OUT
    push 0x01              ; Request: Código específico de la aplicación
    push 0x00              ; Valor: 0x00
    push 0x00              ; Índice: 0x00
    push byte_to_send      ; Buffer de datos
    push 0x01              ; Longitud de datos (1 byte)
    push 1000              ; Timeout en milisegundos
    call libusb_control_transfer

    ; Verificar el resultado de la transferencia
    cmp eax, 1
    je success
    jmp error

success:
    ; Imprimir mensaje de éxito
    push success_message
    call printf
    jmp exit

error:
    ; Imprimir mensaje de error
    push error_message
    call printf

exit:
    ; Cerrar el dispositivo USB y finalizar libusb
    push [device_handle]
    call libusb_close
    call libusb_exit

    ; Salir del programa
    mov eax, 0x60
    xor edi, edi
    syscall

section .data
    success_message db "Byte enviado exitosamente.", 10, 0
    error_message db "Error al enviar el byte.", 10, 0