Unidad 2 Programación Básica - JosueGGC/Lenguajes-de-Interfaz GitHub Wiki
2.1 Ensamblador (y ligador) a utilizar
Turbo Assembler
Turbo Assembler o TASM es un ensamblador desarrollado por Borland el cual además de permitir ensamblar código MASM (Microsoft Macro Assembler) en su modo de compatibilidad, es capaz de soportar programación orientada a objetos desde la versión 3.0 y de generar código para 16 o 32 bits. La característica más importante de Turbo Assembler es que es compatible con lenguajes de alto nivel, por ejemplo: Turbo Pascal, Turbo Basic, Turbo C, Turbo C++.
Turbo Linker
Turbo Linker o T-Link es el enlazador (ligador) incluido con Turbo Assembler, el cual se encarga de generar el código ejecutable a partir del código objeto generado por TASM.
2.2 Ciclos numéricos
La arquitectura de los procesadores x86 obliga al uso de segmentos de memoria para manejar la información, el tamaño de estos segmentos es de 64kb. La razón de ser de estos segmentos es que, considerando que el tamaño máximo de un número que puede manejar el procesador esta dado por una palabra de 16 bits o registro, no sería posible accesar a más de 65536 localidades de memoria utilizando uno solo de estos registros, ahora, si se divide la memoria de la pc en grupos o segmentos, cada uno de 65536 localidades, y utilizamos una dirección en un registro exclusivo para localizar cada segmento, y entonces cada dirección de una casilla específica la formamos con dos registros, nos es posible acceder a una cantidad de 4294967296 bytes de memoria, lo cual es, en la actualidad, más memoria de la que veremos instalada en una PC. Para que el ensamblador pueda manejar los datos es necesario que cada dato o instrucción se encuentren localizados en el área que corresponde a sus respectivos segmentos. El ensamblador accede a esta información tomando en cuenta la localización del segmento, dada por los registros DS, ES, SS y CS, y dentro de dicho registro la dirección del dato específico
2.3 Captura básica de cadenas
Dentro del lenguaje ensamblador no existe el tipo de dato cadena (string en otros lenguajes), por lo que para utilizarla es necesario tratar a las cadenas como un conjunto de caracteres reservados bajo el nombre de una sola variable.
Aquí los métodos para emplear cadenas en lenguaje ensamblador
- MOVSB: Mueve un byte desde una localidad de memoria hasta otra.
- MOVSW: Mueve una palabra desde una localidad de memoria hasta otra.
- LODSB: Carga en la parte baja del registro acumulador (AL) el valor de la localidad de memoria determinada por DS:SI.
- LODSW: Mueve un byte desde una localidad de memoria hasta otra.
2.4 Comparación y prueba
La instrucción CMP se utiliza para comparar dos campos de datos, uno de los cuales está contenido en un registro. Por otro lado, la instrucción CMPS compara el contenido de una localidad de memoria, incrementando o disminuyendo los registros SI y DI según la bandera de dirección. CMPS también establece las banderas AF, CF, OF, PF, SF y ZF. Con un prefijo REP y una longitud en CX, CMPS puede comparar cadenas de cualquier longitud. Sin embargo, CMPS realiza una comparación alfanumérica según los valores ASCII. Hay derivaciones de CMPS, como CMPSB para comparar bytes, CMPSD para palabras dobles y CMPSW para palabras.
2.5 Salto
Los saltos son instrucciones que permiten al programador cambiar el orden de ejecución del programa según sea necesario, dentro de ensamblador existen dos tipos de salto principales: condicionales e incondicionales.
Saltos Incondicionales:
Los saltos incondicionales se utilizan mediante la instrucción JMP, la cual transfiere el control a la línea especificada después de la palabra JMP, la cual puede ser un valor directo o una etiqueta.
También se puede contar como un salto incondicional la instrucción CALL, la cual llama una procedimiento y al terminarla devuelve el control a la línea siguiente de donde se inicio la llamada a procedimiento, pero eso se ve con más detalle en la sección 3.1.
Ejemplos:
-
Salto: Etiqueta a la que se hará referencia para el salto incondicional. JMP Salto: Instrucción que indica que el flujo del programa continuara desde la ubicación de la etiqueta Salto.
-
Saltos Condicionales: Los saltos condicionales transfieren el control del programa a la ubicación que se les dé como parámetro si al hacer una comparación se cumple la condición establecida en el salto, los saltos condicionales son los siguientes:
-
JA (Jump if Above): Salta cuando el valor es superior, su condición es equivalente al salto JNBE (Jump if Not Below or Equal).
-
JAE (Jump if Above or Equal): Salta cuando el valor es superior o igual, su condición es equivalente al salto JNB (Jump if Not Below).
-
JB (Jump if Below): Salta cuando el valor es menor, su condición es equivalente al salto JNAE (Jump if Not Above or Equal).
-
JBE (Jump if Below or Equal): Salta cuando el valor es menor o igual, su condición es equivalente al salto JNA (Jump if Not Above).
-
JE (Jump if Equal): Salta cuando el valor es igual.
-
JZ (Jump if Zero): Salta cuando el valor es cero.
-
JNE (Jump if Not Equal): Salta cuando el valor no es igual.
-
JNZ (Jump if Not Zero): Salta cuando el valor no es cero.
-
JG (Jump if Greater): Salta cuando el valor es mayor, su condición es equivalente al salto JNLE (Jump if Not Less or Equal).
-
JGE (Jump if Greater or Equal): Salta cuando el valor es mayor o igual, su condición es equivalente al salto JNL (Jump if Not Less).
-
JL (Jump if Less): Salta cuando el valor es menor, su condición es equivalente al salto JNGE (Jump if Not Greater or Equal).
-
JLE (Jump if Less or Equal): Salta cuando el valor es menor o igual, su condición es equivalente al salto JNG (Jump if Not Greater).
2.6 Ciclos condicionales
Dentro de la programación existen ocasiones en la que es necesario ejecutar una misma instrucción un cierto número de veces, el cual no siempre es conocido por el programador o puede cambiar durante la ejecución del programa, para lo que existen los ciclos condicionales, los cuales una vez se cumpla la condición que tienen establecida, dejaran de ejecutarse como ciclo y permitirán que el programa continúe con su flujo normal.
En ensamblador no existen de forma predefinida estos ciclos, pero pueden crearse haciendo uso de los saltos incondicionales, generando ciclos que se repetirán hasta que se cumpla la condición definida por el programador. El programador es responsable de crear la lógica para verificar la condición de ciclo y definir cuándo se debe salir del ciclo.
2.7 Incremento y decremento
En ensamblador, el incremento y el decremento se refieren a la operación de aumentar o disminuir en una unidad el valor almacenado en un registro o en una dirección de memoria. La instrucción de incremento es INC y la instrucción de decremento es DEC. Ambas instrucciones aceptan un solo operando que puede ser un registro o una dirección de memoria. Por ejemplo, para incrementar en una unidad el valor almacenado en el registro eax, se puede utilizar la siguiente instrucción: INC eax Esta instrucción suma 1 al valor almacenado en eax. De manera similar, para decrementar en una unidad el valor almacenado en el registro ebx, se puede utilizar la siguiente instrucción: DEC ebx Esta instrucción resta 1 al valor almacenado en ebx. El incremento y el decremento son operaciones comunes en ensamblador y se utilizan con frecuencia en la implementación de ciclos y en la manipulación de punteros y contadores.
2.8 Captura de cadenas con formato
El capturar cadenas con formato permite el movimiento, comparación o búsqueda rápida entre bloques de datos, las instrucciones son las siguientes:
-
MOVC: Esta instrucción permite transferir un carácter de una cadena.
-
MOVW: Esta instrucción permite transferir una palabra de una cadena.
-
CMPC: Este comando es utilizado para comparar un carácter de una cadena.
-
CMPW: Esta instrucción es utilizada para comparar una palabra de una cadena.
-
SCAC: Esta instrucción permite buscar un carácter de una cadena.
-
SCAW: Esta instrucción se utiliza para buscar una palabra de una cadena.
-
LODC: Esta instrucción permite cargar un carácter de una cadena.
-
LODW: Esta instrucción es utilizada para cargar una palabra de una cadena.
-
STOC: Esta instrucción permite guardar un carácter de una cadena.
-
STOW: Esta instrucción es utilizada para guardar una palabra de una cadena.
2.9 Instrucciones aritméticas
Las instrucciones aritméticas son un conjunto de instrucciones que permiten realizar operaciones matemáticas en los registros y la memoria. Estas instrucciones son fundamentales para el procesamiento de datos en lenguaje ensamblador y se utilizan en una amplia variedad de aplicaciones Algunas de las instrucciones aritméticas más comunes son:
-
ADD: Esta instrucción se utiliza para sumar dos valores y almacenar el resultado en un registro o en la memoria.
-
SUB: Esta instrucción se utiliza para restar dos valores y almacenar el resultado en un registro o en la memoria.
-
MUL: Esta instrucción se utiliza para multiplicar dos valores y almacenar el resultado en un registro.
-
DIV: Esta instrucción se utiliza para dividir dos valores y almacenar el resultado en un registro.
2.10 Manipulación de la pila
La pila es una estructura de datos en la que los elementos se agregan y eliminan siguiendo el principio LIFO (Last In, First Out). En lenguaje ensamblador, la pila se utiliza para almacenar temporalmente los valores de los registros y las variables en la memoria, lo que permite ahorrar espacio en los registros y facilita la transferencia de datos entre diferentes partes del programa
Para manipular la pila en lenguaje ensamblador con sintaxis Intel, se utilizan las siguientes instrucciones:
-
PUSH Esta instrucción se utiliza para insertar un valor en la pila.
-
POP Esta instrucción se utiliza para eliminar un valor de la pila.
2.11 Obtención de cadena con representación decimal
El tema de Obtención de cadena con representación decimal en lenguaje ensamblador se refiere a la técnica para convertir un número entero en una cadena de caracteres que representan su valor en formato decimal. Esta técnica es muy común en la programación de bajo nivel, y es necesaria para mostrar valores numéricos en formato legible para el usuario en interfaces de usuario y en registros de archivo de registro.
En lenguaje ensamblador, la obtención de cadena con representación decimal se logra a través de una serie de operaciones aritméticas y de conversión de datos. El algoritmo típico consiste en dividir el número por 10 repetidamente y almacenar el resto de cada división en una variable de caracteres. Luego, los caracteres se invierten y se convierten en una cadena que representa el número en formato decimal.
El proceso comienza dividiendo el número original por 10 para obtener el primer dígito del número. Luego, el resto de la división se almacena en una variable de caracteres. El proceso se repite para obtener los dígitos restantes del número, cada vez dividiendo el resultado anterior por 10 y almacenando el resto. Una vez que se han obtenido todos los dígitos, se invierte el orden de los caracteres para que la cadena represente correctamente el número en formato decimal.
2.12 Instrucciones lógicas
Las instrucciones lógicas son un tipo de instrucciones de programación que se utilizan para realizar operaciones lógicas en los datos que se encuentran en la memoria del ordenador. Estas instrucciones se utilizan para tomar decisiones y controlar el flujo de un programa.
Entre las instrucciones lógicas más comunes se encuentran:
-
AND: esta instrucción realiza una operación lógica AND bit a bit entre dos valores. Si ambos valores son iguales a 1, el resultado es 1, de lo contrario, el resultado es 0.
-
OR: esta instrucción realiza una operación lógica OR bit a bit entre dos valores. Si al menos uno de los valores es igual a 1, el resultado es 1, de lo contrario, el resultado es 0.
-
NOT: esta instrucción realiza una operación lógica NOT bit a bit sobre un valor. Si el valor es igual a 0, el resultado es 1, de lo contrario, el resultado es 0.
-
XOR: esta instrucción realiza una operación lógica XOR bit a bit entre dos valores. Si los valores son diferentes, el resultado es 1, de lo contrario, el resultado es 0.
Estas instrucciones son fundamentales en la programación de sistemas y en la programación de microcontroladores, ya que permiten tomar decisiones y realizar operaciones lógicas sobre los datos que se manejan.
2.13 Desplazamiento y rotación
Los desplazamientos y rotaciones son operaciones muy comunes en el lenguaje ensamblador. Estas operaciones se utilizan para mover los bits de un registro o memoria en una dirección determinada.
En la operación de desplazamiento, los bits se mueven a la izquierda o a la derecha, según la dirección indicada. Los bits que se mueven fuera del registro se pierden. En la operación de rotación, los bits se mueven a la izquierda o a la derecha, pero los bits que se mueven fuera del registro se colocan en el otro extremo del registro.
-
SHL (Shift Left): Esta instrucción toma dos operandos: el registro o memoria que se va a desplazar y la cantidad de bits que se van a mover. Por ejemplo, la instrucción shl eax, 1 desplaza los bits del registro eax una posición a la izquierda, moviendo el bit más significativo al bit de acarreo y poniendo un cero en el bit menos significativo.
-
SHR (Shift Right): Al igual que la instrucción SHL, SHR toma dos operandos: el registro o memoria que se va a desplazar y la cantidad de bits que se van a mover. Por ejemplo, la instrucción shr ebx, 2 desplaza los bits del registro ebx dos posiciones a la derecha, moviendo los dos bits menos significativos al bit de acarreo y poniendo dos ceros en los bits más significativos.
-
ROL (Rotate Left): Esta instrucción toma dos operandos: el registro o memoria que se va a rotar y la cantidad de bits que se van a mover. Por ejemplo, la instrucción rol ecx, 4 rota los bits del registro ecx cuatro posiciones a la izquierda, moviendo los cuatro bits más significativos al bit de acarreo y colocando los cuatro bits menos significativos al final del registro.
-
ROR (Rotate Right): Esta instrucción toma dos operandos: el registro o memoria que se va a rotar y la cantidad de bits que se van a mover. Por ejemplo, la instrucción ror edx, 8 rota los bits del registro edx ocho posiciones a la derecha, moviendo los ocho bits menos significativos al bit de acarreo y colocando los ocho bits más significativos al final del registro
2.14 Obtención de una cadena con la representación hexadecimal
Para obtener una cadena con la representación hexadecimal de un número en lenguaje ensamblador NASM, se puede seguir el siguiente proceso:
-
Cargar el número en un registro. En este caso, se utilizará el registro eax para almacenar el número.
-
Definir una cadena en la sección .data para almacenar la representación hexadecimal del número. Esta cadena se define como una secuencia de bytes utilizando la directiva db.
-
Utilizar una serie de instrucciones para convertir el número a su representación hexadecimal. Esto implica dividir sucesivamente el número por 16 y almacenar los restos en la cadena. El proceso se detiene cuando el cociente es cero.
-
Invertir el orden de los caracteres en la cadena, para obtener la representación correcta de la cifra hexadecimal.
-
Imprimir la cadena utilizando la función de sistema correspondiente.
2.15 Captura y almacenamiento de datos numéricos
Las variables numéricas son de gran utilidad ya que permiten al programador hacer operaciones aritméticas con datos que se desconocen al momento de la compilación. Esta representación esta basada en la notación científica, esto es, representar un número en dos partes: su mantisa y su exponente.
La utilización de datos numéricos es similar a la de cadenas, con la diferencia de que en vez de declarar las variables como db, se declaran como dw, lo cual significa que son variables numéricas.
2.16 Operaciones básicas sobre archivos de disco
Las operaciones básicas sobre archivos de disco en programación de bajo nivel y ensamblador incluyen la apertura, lectura, escritura y cierre de archivos en el sistema de archivos del sistema operativo.
Estas operaciones se realizan mediante interrupciones del sistema operativo que permiten acceder a las funciones de la biblioteca de archivos. Estas funciones se encargan de manejar la comunicación con el sistema de archivos y realizar las operaciones requeridas en el archivo especificado. Algunas funciones son:
- Función 00h: Lee un carácter. Esta función maneja las teclas del teclado de 83 teclas, pero no acepta entrada de las teclas adicionales en el teclado ampliado de 101 teclas. Retorna en al el carácter, ah el código de rastreo si al=0 es una tecla de función extendida.
- Función 01h: Determina si un carácter esta presente.
- Función 02h: Regresa el estado actual de las teclas shift.
- Función 10h: Lectura de un carácter del teclado.
- Función 11h: Determina si esta presente un carácter.
- MOVS: Mueve un byte, palabra o palabra doble desde una localidad en memoria direccionada por SI a otra localidad direccionada por DI.
- LODS: Carga desde una localidad de memoria direccionada por SI un byte en AL, una palabra en AX o una palabra doble en EAX.
- STOS: Almacena el contenido de los registros AL, AX, o EAX en la memoria direccionada por SI.
- CMPS: Compara localidades de memoria de un byte, palabra o palabra doble direccionadas por SI, DI.
- SCAS: Compara el contenido de AL, AX o EAX con el contenido de una localidad de memoria direccionada por SI.