Practicas Unidad 2 - JoseCorreaMorales/lenguajes-de-interfaz GitHub Wiki
Practica 1 - Programa "Hola Mundo" en ensamblador.
En términos generales se pretende adentrarse mas al tema analizando un código predefinido, es este sentido el fin es profundiza mas en los temas, esto mediante una análisis mas profundo que se realizara paso a paso y línea por línea de un código relativamente corto
Comprender el funcionamiento del lenguaje ensamblador haciendo zoom a cada una de las instrucciones para reforzar el conocimiento teórico
El objetivo del programa es imprimir en pantalla la cadena "Hola mundo", y lo logra a través de la llamada al sistema "write" que se encuentra en la librería estándar del sistema operativo
El código es relativamente corto y fácil de entender, lo que lo convierte en un buen punto para empezar a entender el lenguaje ensamblador
A continuación una explicación detallada del siguiente código en ensamblador haciendo zoom a cada una de sus líneas
section .data
msg db 'Hola mundo', 0
section .text
global _start
_start:
mov eax, 4 ; código de función para "write"
mov ebx, 1 ; descriptor de archivo para la salida estándar
mov ecx, msg
mov edx, 13
int 0x80
mov eax, 1
xor ebx, ebx
int 0x80
section .data
msg db 'Hola mundo', 0
En términos generales se define una sección de datos y se crea una variable llamada msg, que contiene una cadena de texto de 'Hola mundo' y un byte nulo
Pero yendo mas a fondo tenemos tres partes esenciales:
- Una sección
- Definición de variable
- Byte nulo
En lenguaje ensamblador, las secciones son áreas del código fuente que se utilizan para separar y organizar diferentes tipos de información y código
Algunas secciones comunes son:
Sección | Descripción |
---|---|
Sección de datos | Esta sección se utiliza para declarar y definir las variables y constantes utilizadas en el programa |
Sección de código: | Esta sección contiene el código ejecutable del programa. |
Sección de inicio: | Esta sección contiene el código que se ejecuta al inicio del programa. |
Sección de texto: | Esta sección contiene el código que no se puede modificar durante la ejecución del programa |
Es por ello se utiliza una sección de datos
Cada sección tiene su propio propósito y sintaxis en el lenguaje ensamblador, y la organización adecuada de estas secciones puede hacer que el código sea más legible y fácil de mantener.
En ensamblador, las variables se definen utilizando una directiva de asignación de memoria que reserva un espacio en la memoria para almacenar el valor de la variable.
El el condigo en cuestión se usa la directiva db
para reservar un byte de memoria para la variable msg.
El valor Hola mundo
se asigna a esa posición de memoria.
Un byte nulo en ensamblador, también conocido como byte de terminación nulo o byte null, es un byte que tiene un valor de cero (0x00 en hexadecimal). en este caso a presencia de un byte nulo indica el final de la cadena o estructura de datos en este caso del mensaje Hola mundo
.
section .text
global_start
Aquí se define una sección de texto y se declara una etiqueta global _start que funciona como el método `Main`
de Java, por ejemplo
La sección de texto en lenguaje ensamblador es una sección que contiene el código ejecutable del programa. Esta sección es la más importante del codigo, ya que contiene las instrucciones que se ejecutan primero en el programa
global_start
una etiqueta que se usa para indicar el punto de inicio del programa
Mirando mas de cerca tenemos la conbinacion de dos directivas global
y start
Se utiliza la etiqueta start
para definir de manera mas puntual donde se quiere que comience el programa, aunque realmente sino se define esta etiqueta el punto de inicio será el predeterminado
La etiqueta global
funciona como complemento a la de start
pues en combinación nos aseguramos de que el programa sea visible desde fuera del archivo objeto y se pueda utilizar para vincular el programa con algunos otros módulos o bibliotecas externas.
3. Inicio, llamada al sistema, escritura en consola, dirección de la cadena, longitud de la cadena e interrupción
_start:
mov eax, 4
mov abx, 1
mov ecx, msg
mov edx 13
int 0x80
Esencialmente _start
es realmente donde se especifica el comienzo del programa
_start
vs global_start
: "_start"
se utiliza para indicar el punto de entrada del programa y la instrucción "global _start"
se utiliza para hacer que esta etiqueta sea visible desde otros módulos del programa.
La instrucción "mov" es una abreviación de "move" (mover), y su sintaxis general es "mov destino, origen". En este caso, "eax" es el destino y "4" es el origen.
Es decir, en principio "MOV eax, 4 "
se puede definir como: Mover el valor de 4 al "lugar" eax
Sin embargo, es este contexto no tiene sertido, pues no tiene relación alguna con el fin del programa que es simplemente mostrar una cadena
La respuesta es que "MOV eax, 4 "
en este contexto y en términos simples quiere decir:
"MOV eax, 4 "
= Llama a la función `write()`
mas no el significado literal de mover el valor de 4 al "lugar" eax
Simplemente se esta especificando que se utiliza como parte de la llamada al sistema para imprimir el mensaje "Hola, mundo!" en pantalla. La instrucción carga el valor 4 en el registro EAX, que es el código de función para la llamada al sistema "write" en sistemas Linux.
De manera idéntica a la lineal anterior mov ebx, 1
es simplemente un código para especificar algo sobre la funcionalidad o formato del programa
En este caso la instrucción "mov ebx, 1"
se utiliza para especificar que el resultado de la llamada al sistema "write" se escribirá en la salida estándar
Es decir, el descriptor de archivo 1 representa la salida estándar, o esa, el flujo de salida que se muestra en la consola.
La línea "mov ecx, msg"
se utiliza para mover la dirección del mensaje "Hola mundo" a imprimir a la posición de memoria del registro ECX. En otras palabras, esta instrucción carga la dirección de la cadena "Hola, mundo!" en el registro ECX.
En resumen La instrucción "mov ecx, msg"
asume que se ha definido una sección de datos (".data") en el programa donde se ha definido la cadena "Hola mundo" utilizando la directiva "db" para reservar una sección de memoria y almacenar la cadena.
la línea "mov edx, 13"
se utiliza para mover el tamaño de la cadena "Hola mundo" a imprimir a la posición de memoria del registro EDX. En otras palabras, esta instrucción carga el tamaño de la cadena "Hola, mundo!" en el registro EDX.
"mov edx, 13"
asume que se ha definido una sección de datos (".data") en el programa donde se ha definido la cadena "Hola mundo" utilizando la directiva "db" para reservar una sección de memoria y almacenar la cadena. El valor 13 en esta línea es el tamaño de la cadena "Hola mundo" incluyendo el carácter nulo al final de la cadena.
Hasta este punto los argumentos de la llamada al sistema write son los siguientes:
-
El primer argumento es el descriptor de archivo, que se carga en el registro EAX con el valor 1. Este valor indica que se debe escribir en la salida estándar
-
El segundo argumento es un puntero que contiene los datos que se van a escribir en el archivo. En este ejemplo, el puntero se carga en el registro EBX con la dirección de memoria de la cadena "Hola mundo"
-
El tercer argumento es el número de bytes que se van a escribir en el archivo. En este ejemplo, el valor se carga en el registro ECX con el valor 13, que es el número de bytes de la cadena msg
La interrupción "int 0x80" es una llamada al sistema que se utiliza en los sistemas operativos basados en UNIX y Linux para solicitar un servicio del kernel del sistema operativo
La interrupción "int 0x80" puede variar entre diferentes sistemas operativos y arquitecturas de procesador.
Es resumen interrumpe La EJECUCION
mov eax, 1
xor ebx, ebx
int 0x80
De las misma manera que MOV eax, 4
hace una llamada al sistema para escribir mov eax, 1
hace una llamada al sistema
para salir, es decir para salir del programa
La instrucción xor ebx, ebx se utiliza comúnmente para establecer un registro en cero, ya que la operación XOR con el mismo valor siempre devuelve cero. Esta es una forma eficiente de establecer un registro en cero en lenguaje ensamblador
En resumen, la línea xor ebx, ebx
se utiliza en este ejemplo para establecer el valor de retorno en cero, lo que indica que el programa ha finalizado correctamente
El términos simples la ultima lineal sirve para interrumpir la ejecución del programa y se realiza la llamada al sistema para salir del programa.
Sin embargo no queda del todo lo siguiente
Resumiendo, en el ejemplo del código se utiliza dos llamadas al sistema int 0x80
, una para escribir un mensaje en la salida estándar y otra para finalizar el programa. En cada llamada, se establece un valor diferente en el registro EAX para indicar qué llamada al sistema se va a realizar.
Al ejecutar el código, se imprimirá "Hola mundo" en la salida estándar y luego se finalizará el programa.
Este código demuestra cómo se pueden utilizar las llamadas al sistema del kernel en un sistema operativo Linix para imprimir texto en la salida estándar.
A través de este ejemplo, se puede apreciar la complejidad y la precisión que se requiere al programar en lenguaje ensamblador.
El código muestra la estructura básica de un programa en ensamblador, con secciones definidas para datos y texto. También se muestra cómo se pueden utilizar las funciones del sistema operativo a través de interrupciones.
También es importante mencionar que existen diferentes sintaxis de ensamblador como la AT&T, HLA o NASM es este caso este ejemplo este hecho con la sintaxis de Intel
En conclusión, el código presentado es un ejemplo básico de programación en lenguaje ensamblador x86 para sistemas Linux. El programa imprime "Hola mundo" en la consola utilizando la función del sistema operativo write y luego sale del programa.
el aprendizaje obtenido a través de este ejemplo es la comprensión básica de la estructura de un programa en ensamblador, la forma de interactuar con las funciones del sistema operativo a través de interrupciones
Assembly Programming Tutorial. (s. f.). https://www.tutorialspoint.com/assembly_programming/index.htm
Practica 2 - Medio sumador en Minecraft
Básicamente con el fin de realizar un medio sumando se expondrá los pasos mas importante para realizarse en Minecraft comentando el plan para realizarse, mostrando el resultados del funcionamiento y comentar las particularidad del los materiales de Minecraft para obtener el medio sumando
Implementar un medio sumador utilizando los elementos que Minecraft proporciona, este medio sumador debe tener la capacidad de realizar la suma de dos dígitos binarios y de salida debemos observar la suma de ambos bits así como el acarreo, para esto se utilizara el modo creativo que proporciona el juego.
El fin de realizar este práctica recae en asimilar como es que funciona la arquitectura de un procesador en base a puertas lógicas y su relación con el lenguaje ensamblador
Para lograr un medio sumador en Minecraft es necesario seguir el siguiente esquema el cual esta formado por dos partes:
- Una pueta lógica XOR
- Una pueta lógica AND
Materiales |
---|
Bloques cualquiera |
Palancas |
Polvo de redstone |
Lampara de redstone |
Antorcha de redstone |
El objetivo es replicar el diagrama anterior, para ello se usara el polvo de restone como las líneas conductoras de energía por donde puede o no pasar energia, es decir un 0 o un 1, esto emulara ese efecto de el paso o no de corriente lo que lleva al siguiente punto.
El diagrama consta de dos entradas de energía, para lograr esto en Minecraft se emplearan las palancas de Minecraft, estas funcionan como un especia de Switch lo que resulta útil para emular el poder encender o apagar el paso de energía
Ya se tiene los caminos, se necesita trasportar y direccionar esa "corriente" por todos los caminos, para esto serán necesarias las antorchas de redstone ya que en Minecraft la manera en la que se transportara esta "corriente" que se se quiere emular es dicho de manera sencilla como si incendiáramos el polvo de redstone y nos ayudáramos de darle dirección a ese fuego ("corriente") con las antorchas de redstone
La idea es conseguir las salidas de las tablas de verdad de cada puerta lógica
Para la AND
A | B | Q |
---|---|---|
0 | 0 | 0 |
0 | 1 | 0 |
1 | 0 | 0 |
1 | 1 | 1 |
Para la XOR
A | B | Q |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 1 |
Es decir se quiere que se incendie al accionar el switch y al hacer lo contrario "apagar" el incendio, realmente ya se tiene todo lo que se necesita lo única que hace falta es colocar las antorchas de redstone de manera estratégica
La antorcha de redstone funciona a priori como un inversos de la señal y pueta NOT en base a esto se deberán colocar estratégicamente
Es cuestión de seguir las "líneas" representadas del diagrama y para ayudarnos a dirigir la corriente y emular la decisión empleando las antorchas
Para la compuerta and quedaría de la siguiente manera:
Como se puede observar en la imagen interior se le a dado "corriente" en los switch pero tomando en cuenta la nota previa al ser inversor de la señal ambas han sido invertidas, esto da como resultado que la salida sea una antorcha encendida, en otras palabras se a conseguido hacer la decisión lógica 1 y 1 = 1, es decir ¡se ha hecho una puerta AND a base inversión de la señal ósea un "NOT"!
Para la compuerta XOR se sigue exactamente el mismo razonamiento, esta quedaría de la siguiente manera:
El funcionamiento es este caso:
Del lado A se le a dado corriente y del B no, pero a pesar de que se vea la antorcha del lado derecho iluminada la que realmente hace accionar la rampara de redstone es la del lado B
En resumen, se realizo una cadena de inversiones de señales entre varias antorchas en el camino.
Se obtuvo un medio sumador a base de usar redstone en Minecraft
Las puertas lógicas y el lenguaje ensamblador están muy relacionados en el funcionamiento de los procesadores pues as puertas lógicas son la base fundamental de la arquitectura del procesador, mientras que el lenguaje ensamblador es la herramienta que permite aprovechar al máximo su potencial, en este caso se realizaron dos de esas compuertas lógicas que forman parte de la arquitectura del procesador
Las puertas lógicas resultan ser componentes fundamentales en un procesador, ya que permiten realizar operaciones lógicas y aritméticas a nivel de 0 y 1, lo que a su vez permite la ejecución de programas y procesamiento de datos. Cada puerta lógica tiene una función específica
En conjunto, las puertas lógicas forman los circuitos digitales que procesan la información dentro del procesador. La combinación de estas puertas en circuitos más complejos permite realizar operaciones más sofisticadas, como sumas, restas, multiplicaciones y divisiones.
Esto es al final donde terminan las instrucciones no solo de lenguajes de alto nivel sino también las instrucciones de lenguaje ensamblador incluso este ultimo con una relación mas intima ya que es un lenguaje de bajo nivel que su principal función es programar procesadores. A diferencia de los lenguajes de programación de alto nivel, el lenguaje ensamblador trabaja directamente con las instrucciones que ejecuta el procesador, y por lo tanto requiere un conocimiento detallado de la arquitectura y funcionamiento del procesador y esto se traduce una vez mas en puertas lógicas como las construidas en esta practica.
J. (2022, 29 noviembre). Guide to Redstone. Microsoft Learn. https://learn.microsoft.com/en-us/minecraft/creator/documents/redstoneguide
Cordeiro, J. (2021, 5 octubre). Engineering with Redstone in Minecraft. dummies. https://www.dummies.com/article/home-auto-hobbies/games/online-games/minecraft/engineering-with-redstone-in-minecraft-168907/
Practica 3 - Suma
Se hace un explicación detallada sobre la operación básica suma en ensamblador
Realizar la operación aritmética suma en lenguaje ensamblador
A continuación el desglose del código en ensamblador necesario para realizar sumas en ensamblador, con el objetivo de aprender una de las operaciones aritméticas básica que además es vital conocer el proceso ya que las operaciones aritméticas básicas (suma) son recurrentes en el mundo del desarrollo de software
Comencemos desglosando el siguiente código paso a paso:
section .data
resultado db '0' ; Define un Byte, que se inicializa en 0
section .text
global _start
_start:
MOV eax, 2 ;eax = 2
MOV ebx, 3 ; ebx = 3
add eax, ebx ; el resultado se guarda en eax, (el primero) aquí eax vale 5
add eax, 48 ; 48 es 0 en ASCCI
MOV [resultado], eax ;sobre escribiendo el valor tal cual de registro
; Escribiendo el resultado
MOV eax, 4
MOV ebx, 1
MOV edx, resultado
MOV edx, 1 ; cuantos bytes vamos a imprimir
int 0x80
; Terminado el programa, un return 0
mov eax, 1
MOV ebx, 0
int 0x80
En la sección .data, se define una variable 'resultado' que se inicializa en 0.
En la sección .text, el punto de entrada del programa se define como '_start', que es un símbolo global.
El primer bloque de código dentro de '_start' mueve el valor 2 al registro EAX y el valor 3 al registro EBX.
Luego, se agrega el valor en EBX al valor en EAX y se almacena el resultado nuevamente en EAX. En este punto, EAX contiene el valor 5.
Luego, se agrega 48 al valor en EAX, lo que representa el carácter '0' en ASCII. Esto se hace para convertir el valor numérico en un carácter ASCII para que se pueda imprimir.
El resultado final se almacena en la variable 'resultado' que se define en la sección .data.
Luego, se usa la llamada al sistema de Linux para imprimir el resultado almacenado en 'resultado'. Primero, se mueve el valor 4 al registro EAX para indicar que la llamada al sistema es para escribir en la salida estándar. Luego, se mueve el valor 1 al registro EBX para indicar que la salida se escribirá en stdout. A continuación, se mueve la dirección de memoria de la variable 'resultado' al registro EDX y se mueve el valor 1 al registro ECX para indicar que se imprimirá solo un byte. Finalmente, se realiza la llamada al sistema con 'int 0x80', lo que desencadena la impresión del resultado en la salida estándar.
Por último, se utiliza una llamada al sistema para terminar el programa. Se mueve el valor 1 al registro EAX para indicar que la llamada al sistema es para salir del programa. Luego, se mueve el valor 0 al registro EBX para indicar que el programa terminó sin errores. Finalmente, se realiza la llamada al sistema con 'int 0x80', lo que termina el programa.
Este código en ensamblador muestra una forma básica de realizar operaciones aritméticas simples y escribir el resultado en la salida estándar del sistema.
En primer lugar, se inicializa una variable 'resultado' en 0 en la sección de datos. Luego, en la sección de texto, se suman los valores 2 y 3, se agrega 48 (valor ASCII de 0) para convertir el número en un carácter ASCII y se guarda en la variable 'resultado'. Posteriormente, se utiliza la llamada al sistema para imprimir el resultado en la pantalla. Finalmente, se utiliza la llamada al sistema para terminar el programa.
En conclusión, este código puede ser utilizado como base para programas más complejos que realizan cálculos aritméticos y entrada/salida de datos, es importante tomar en cuenta la posición de cada numero en la tabla de números ASCII para que la operación arroje el resultado correcto.
Assembly Programming Tutorial. (s. f.). https://www.tutorialspoint.com/assembly_programming/index.htm
Practica 4 - Resta
Se hace un explicación detallada sobre la operación básica resta en ensamblador
Realizar la operación aritmética resta en lenguaje ensamblador
A continuación el desglose del código en ensamblador necesario para realizar resta en ensamblador, con el objetivo de aprender una de las operaciones aritméticas básica que además es vital conocer el proceso ya que las operaciones aritméticas básicas (resta) son recurrentes en el mundo del desarrollo de software
Comencemos desglosando el siguiente código paso a paso:
section .data
resultado db "El resultado es: ", 10, 0
num1 db 5
mun2 db 20
section .text
global _start
_start:
mov al, mun1
sub al, num2
add al, 48
mov edx, 17
mov ecx, resultado
mov ebx, 1
mov eax, 4
int 0x80
mov eax, 1
xor ebx, abx
int 0x80
Primero, se definen las variables de datos en la sección .data. La variable resultado es una cadena de caracteres que se utilizará para imprimir el resultado en la pantalla, mientras que las variables num1 y num2 son variables que contienen los valores 5 y 20, respectivamente.
En la sección .text, se define el punto de entrada _start, que marca el comienzo del código del programa. El código en sí comienza moviendo el valor de num1 a al, el registro más bajo de 8 bits en la CPU, y luego se resta el valor de num2 a al. Esto se hace para realizar la operación matemática de sustracción.
Luego, se agrega 48 a al. Esto se hace para convertir el resultado de la operación en un valor ASCII que se puede imprimir en la pantalla.
Luego se mueven los valores de las variables resultado, 1 y 17 a los registros ecx, ebx y edx, respectivamente. La variable resultado se mueve a ecx para que se pueda imprimir en la pantalla, mientras que 1 se mueve a ebx para indicar que la salida se enviará a la pantalla. 17 se mueve a edx para indicar la longitud de la cadena que se va a imprimir.
Finalmente, se realiza una llamada al sistema (int 0x80) para imprimir la cadena en la pantalla. Luego, el programa sale del programa llamando a la función exit del sistema.
Este código en ensamblador muestra una forma básica de realizar operaciones aritméticas simples y escribir el resultado en la salida estándar del sistema.
El código realiza una operación matemática simple y muestra el resultado en la pantalla. En el código se definen las variables de datos, se realiza la operación de resta, luego se convierte el resultado en un valor ASCII, se mueven los valores de las variables a los registros correspondientes y se llama a la función del sistema para imprimir la cadena en la pantalla. El programa luego sale llamando a la función exit del sistema.
En conclusión, este código puede ser utilizado como base para programas más complejos que realizan cálculos aritméticos y entrada/salida de datos, es importante tomar en cuenta la posición de cada numero en la tabla de números ASCII para que la operación arroje el resultado correcto.
Assembly Programming Tutorial. (s. f.). https://www.tutorialspoint.com/assembly_programming/index.htm
Practica 5 - Multiplicación
Se hace un explicación detallada sobre la operación básica multiplicación en ensamblador
Realizar la operación aritmética multiplicación en lenguaje ensamblador
A continuación el desglose del código en ensamblador necesario para realizar multiplicación en ensamblador, con el objetivo de aprender una de las operaciones aritméticas básica que además es vital conocer el proceso pues las operaciones aritméticas básicas (multiplicación) son recurrentes en el mundo del desarrollo de software
Comencemos desglosando el siguiente código paso a paso:
section .bss ;
resultado resb 1 ; reservamos un byte
section .text
global _start
_start:
mov ax, 3
mov bx, 2
mul cx ; el resultado se guarda en ax
add ax, 48
mov [resultado], ax
mov eax, 4
mov ebx, 1
mov ecx, resultado
mov edx, 1
int 0x80
mov eax, 1
mov ebx, 0
int 0x80
Para comenzar, se declara una sección de variables no inicializadas utilizando la sintaxis ".bss". Dentro de esta sección, se reserva un byte de memoria utilizando la directiva "resb" y se le asigna el nombre "resultado".
A continuación, se declara la sección de código utilizando la sintaxis ".text" y se define el punto de entrada global "_start".
En la sección "_start", se realizan algunas operaciones matemáticas. En primer lugar, se mueve el valor 3 al registro "ax" y el valor 2 al registro "bx". Luego, se utiliza la instrucción "mul" para multiplicar los valores en "ax" y "bx" y guardar el resultado en "ax".
Después, se le suma el valor 48 al registro "ax". Este valor se utiliza para convertir el resultado en un carácter ASCII.
A continuación, se almacena el valor de "ax" en la ubicación de memoria reservada anteriormente para "resultado" utilizando la instrucción "mov".
Se utiliza la función de sistema "write" para mostrar el valor almacenado en "resultado" en la pantalla. Para ello, se asigna el valor 4 al registro "eax", el valor 1 al registro "ebx", la dirección de memoria de "resultado" al registro "ecx" y el valor 1 al registro "edx". La instrucción "int 0x80" se utiliza para llamar al servicio de interrupción del kernel para realizar la acción de escritura en pantalla.
Finalmente, se utiliza la función de sistema "exit" para salir del programa. Esto se logra moviendo el valor 1 al registro "eax", el valor 0 al registro "ebx" y llamando a la interrupción del kernel "int 0x80".
Este código en ensamblador muestra una forma básica de realizar operaciones aritméticas simples y escribir el resultado en la salida estándar del sistema.
El código reserva un byte de memoria y utiliza instrucciones propias de ensamblador para realizar una multiplicación y convertir el resultado en un carácter ASCII. Luego, el valor se muestra en la pantalla utilizando la función de sistema "write". Finalmente, el programa finaliza utilizando la función de sistema "exit".
En resumen, el código de esta practica realiza una operación matemática simple y muestra el resultado en la pantalla. Es un ejemplo básico de como realizar una multiplicación
Assembly Programming Tutorial. (s. f.). https://www.tutorialspoint.com/assembly_programming/index.htm
Practica 6 - División
Se hace un explicación detallada sobre la operación básica división en ensamblador
Realizar la operación aritmética división en lenguaje ensamblador
A continuación el desglose del código en ensamblador necesario para realizar división en ensamblador, con el objetivo de aprender una de las operaciones aritméticas básica que además es vital conocer el proceso pues las operaciones aritméticas básicas (división) son recurrentes en el mundo del desarrollo de software
Como primer paso se reserva un byte de memoria utilizando la directiva "resb" y se le asigna el nombre "resultado" en la sección ".bss".
Después, se declara la sección de código utilizando la sintaxis ".text" y se define el punto de entrada global "_start".
En la sección "_start", se realizan algunas operaciones matemáticas. En primer lugar, se mueve el valor 2 al registro "bx" y el valor 8 al registro "ax". Luego, se utiliza la instrucción "div" para dividir los valores en "ax" y "bx". El cociente se almacena en "ax" y el resto en "dx".
Luego, se le suma el valor 48 al registro "ax". Este valor se utiliza para convertir el resultado en un carácter ASCII.
Además se almacena el valor de "ax" en la ubicación de memoria reservada anteriormente para "resultado" utilizando la instrucción "mov".
Se utiliza la función de sistema "write" para mostrar el valor almacenado en "resultado" en la pantalla. Para esto, se asigna el valor 4 al registro "eax", el valor 1 al registro "ebx", la dirección de memoria de "resultado" al registro "ecx" y el valor 1 al registro "edx"
Para finalizar, se utiliza la función de sistema "exit" para salir del programa. Esto se logra moviendo el valor 1 al registro "eax", el valor 0 al registro "ebx" y llamando a la interrupción del kernel "int 0x80".
En terminos simples, el código reserva un byte de memoria y utiliza instrucciones de ensamblador para realizar una operación matemática y convertir el resultado en un carácter ASCII. Luego, el valor se muestra en la pantalla utilizando la función de sistema "write". Finalmente, el programa finaliza utilizando la función de sistema "exit"
En resumen, el código de esta practica realiza una operación matemática simple y muestra el resultado en la pantalla. Es un ejemplo básico de como realizar una división
Assembly Programming Tutorial. (s. f.). https://www.tutorialspoint.com/assembly_programming/index.htm
Practica 7 - Desplazamiento a la izquierda
Se estudio el tema desplazamiento de bits en lenguaje ensamblador
El objetivo de este programa es demostrar el uso de registros, desplazamientos y operaciones aritméticas en lenguaje ensamblador para realizar operaciones simples y mostrar el resultado en la salida estándar.
En esta practica se ha hablado sobre el código de un programa en lenguaje ensamblador para mostrar en la salida estándar el valor ASCII de un número multiplicado por dos y sumado a 48, así como sobre el tema de desplazamiento en lenguaje ensamblador.
Descripción paso a paso del desarrollo de la práctica de el siguiente código:
section .text
global _start
_start:
mov ebx, 2
shl ebx, 1 ; desplazamiento a la izquierda de un bit
add ebx, 48
mov [resultado], abx
mov eax, 4
mov ebx, 1
mov ecx, resultados
mov edx, 1
int 0x80
mov eax, 1
mov ebx, 0
int 0x80
La sección .bss se utiliza para declarar una variable llamada "resultado" que es de un byte de longitud. Esta variable será utilizada para almacenar el resultado final del programa.
La sección .text contiene el código ejecutable del programa. La etiqueta "_start" indica el punto de entrada del programa.
En la primera línea del código, se carga el valor 2 en el registro ebx y se realiza un desplazamiento a la izquierda de un bit. Esto multiplica el valor de ebx por dos, lo que significa que el valor de ebx es ahora 4.
En la línea siguiente, se le suma 48 al valor de ebx. 48 es el valor ASCII del carácter '0'. Esto convierte el valor de ebx en su representación ASCII.
A continuación, se almacena el valor de ebx en la variable "resultado".
Las siguientes cuatro líneas de código utilizan la función de sistema "write" para imprimir el valor de la variable "resultado" en la salida estándar. Primero se carga el valor 4 en el registro eax para indicar que se utilizará la función "write". Luego se carga el valor 1 en el registro ebx para indicar que la salida estándar se utilizará como destino. En el registro ecx se carga la dirección de memoria de la variable "resultado" y en edx se carga el valor 1 para indicar que se imprimirá un solo byte.
Finalmente, se utiliza la función de sistema "exit" para salir del programa. Se carga el valor 1 en el registro eax para indicar que se utilizará la función "exit", se carga el valor 0 en el registro ebx para indicar que el programa terminó sin errores y se llama a la función de sistema con la instrucción "int 0x80".
La salida del código sería un solo byte que representa el valor ASCII del número 4 multiplicado por dos y sumado a 48, que es el resultado de la operación realizada en la línea 6 del código.
En particular, la salida sería el carácter '8', ya que 4 multiplicado por 2 es 8 y su valor ASCII es 56 (48 + 8). Como la variable "resultado" es de un solo byte, solo se imprime el valor menos significativo de 56, que es el carácter '8'.
La línea "shl ebx, 1" es una instrucción en lenguaje ensamblador que realiza una operación de desplazamiento a la izquierda (shift left) en el valor del registro EBX.
La operación de desplazamiento a la izquierda mueve los bits de un valor hacia la izquierda en una cantidad determinada de posiciones, y rellena los bits menos significativos con ceros. En este caso, se está desplazando el valor del registro EBX en una posición a la izquierda, lo que equivale a multiplicar el valor de EBX por dos.
Después de ejecutar esta instrucción, el valor del registro EBX se ha multiplicado por dos y se ha almacenado en el registro EBX nuevamente. En otras palabras, el resultado de la operación "shl ebx, 1" es que el registro EBX contiene ahora el valor original multiplicado por dos.
En conclusión, el desplazamiento en lenguaje ensamblador es una operación fundamental que permite mover bits en un registro o memoria en una o varias posiciones hacia la izquierda o derecha.
Esta operación es útil para realizar multiplicaciones o divisiones rápidas por potencias de dos, así como para acceder a secciones específicas de registros o memoria.
Sin embargo, es importante tener en cuenta que el desplazamiento también puede causar la pérdida de bits, por lo que es necesario considerar el tamaño y la precisión de los datos. Además, el uso excesivo de desplazamientos puede dificultar la legibilidad del código, por lo que se recomienda utilizarlos con moderación y en situaciones apropiadas.
Assembly Programming Tutorial. (s. f.). https://www.tutorialspoint.com/assembly_programming/index.htm
Practica 8 - Desplazamiento a la derecha
Se estudio el tema desplazamiento de bits en lenguaje ensamblador
El objetivo de este programa es demostrar el uso de registros, desplazamientos y operaciones aritméticas en lenguaje ensamblador para realizar operaciones simples y mostrar el resultado en la salida estándar.
El programa realiza la operación básica de dividir un número por 2 utilizando una instrucción de desplazamiento hacia la derecha y convierte el resultado en su representación ASCII para imprimirlo en la pantalla
Descripción paso a paso del desarrollo de la práctica de el siguiente código:
section .text
global _start
_start:
mov ebx, 2
shr ebx, 1 ; desplazamiento a la derecha de un bit
add ebx, 48
mov [resultado], abx
mov eax, 4
mov ebx, 1
mov ecx, resultados
mov edx, 1
int 0x80
mov eax, 1
mov ebx, 0
int 0x80
El código en cuestión es un programa en ensamblador que utiliza las interrupciones del sistema de Linux para imprimir el número 1 en la pantalla. El programa comienza por definir una variable "resultado" en la sección .bss, luego usa la instrucción shr para dividir el valor de 2 en ebx por 2, lo que resulta en el valor 1. Luego, se suma 48 a ebx para convertir el valor en el código ASCII del carácter '1'. Finalmente, se utiliza la interrupción del sistema de Linux 0x80 para imprimir el valor almacenado en la variable "resultado" en la pantalla y salir del programa. Este programa es un ejemplo simple de cómo utilizar interrupciones del sistema en ensamblador para interactuar con el sistema operativo subyacente.
se define una variable "resultado" de un byte en la sección .bss. Luego, en la sección .text, el registro ebx se establece en 2 y se desplaza a la derecha en un bit para obtener el valor 1. Luego, se suma 48 para convertir el valor en el código ASCII del carácter '1' y se almacena en la variable "resultado".
En el código en cuestión, la instrucción shr ebx, 1 se utiliza para dividir el valor de 2 en ebx por 2, lo que resulta en el valor 1. Esto se debe a que la división por 2 se puede realizar mediante un desplazamiento hacia la derecha de un bit, lo que es más rápido que la división por medio de una operación de división aritmética. Luego, se suma 48 a ebx para convertir el valor en el código ASCII del carácter '1'.
La instrucción shr en ensamblador (abreviatura de "shift right") desplaza los bits de un registro hacia la derecha y coloca un 0 en el bit más significativo. La cantidad de bits que se desplazan se especifica mediante un operando inmediato o un registro. En este caso, la instrucción shr ebx, 1 desplaza los bits del registro ebx hacia la derecha en una posición, lo que es equivalente a dividir el valor de ebx por 2.
En conclusión, el desplazamiento en lenguaje ensamblador es una operación fundamental que permite mover bits en un registro o memoria en una o varias posiciones hacia la izquierda o derecha.
Esta operación es útil para realizar multiplicaciones o divisiones rápidas por potencias de dos, así como para acceder a secciones específicas de registros o memoria.
Sin embargo, es importante tener en cuenta que el desplazamiento también puede causar la pérdida de bits, por lo que es necesario considerar el tamaño y la precisión de los datos. Además, el uso excesivo de desplazamientos puede dificultar la legibilidad del código, por lo que se recomienda utilizarlos con moderación y en situaciones apropiadas.
Assembly Programming Tutorial. (s. f.). https://www.tutorialspoint.com/assembly_programming/index.htm
Practica 9 - Rotación a la izquierda
El siguiente código es un programa escrito en lenguaje ensamblador que imprime en la salida estándar (stdout) el resultado de rotar un bit en un byte y agrega un salto de línea al final.
El objetivo principal del programa es demostrar cómo usar las instrucciones de rotación de bits y las funciones de interrupción en lenguaje ensamblador.
El código en cuestión es un programa escrito en lenguaje ensamblador que muestra cómo rotar un bit en un byte y cómo imprimir el resultado en la salida estándar. El programa utiliza instrucciones de rotación de bits y funciones de interrupción para realizar estas operaciones.
Descripción del comportamiento de los registros correspondientes sobre el siguiente código:
; salto de linea
section .data
msg db 'El resultado es: '
ln db 10, 13
lonln equ 2
section .bss
resultado resb 1
section .text
global _start
_start:
; 128 64 32 16 8 4 2 1
;| 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
;| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
mov bl, 128
rol bl, 1 ; rotacion a la izq
mov eax, 4
mov ebx, 1
mov ecx, msg
mov edx, 13
int 0x80
add bl, 48
mov [resultado], bl
mov eax, 4
mov ebx, 1
mov ecx, resultado
mov edx, 1
int 0x80
; salto de linea
mov eax, 4
mov ebx, 1
mov ecx, ln
mov edx, lonln
int 0x80
mov eax, 1
mov ebx, 0
int 0x80
La sección .data define dos variables, msg y ln. Msg es una cadena de caracteres que contiene "El resultado es: " y ln es una cadena de dos caracteres que representa un salto de línea en ASCII.
La sección .bss define la variable resultado, que es un byte reservado en memoria para almacenar el resultado de la rotación de bits.
La sección .text es donde se define la función principal _start. Dentro de esta función, se realiza una rotación de bits en un byte utilizando la instrucción rol. El byte se inicializa con el valor 128, que es 10000000 en binario. La rotación mueve los bits a la izquierda, lo que produce el resultado 00000001, que es 1 en decimal.
Después de la rotación, el programa utiliza la función de interrupción 0x80 para imprimir el mensaje "El resultado es: " en la salida estándar. Luego se agrega el valor del byte resultante de la rotación (1) a la cadena de caracteres resultado y se imprime en la salida estándar utilizando otra llamada a la función de interrupción 0x80.
Finalmente, se agrega un salto de línea a la salida estándar utilizando una tercera llamada a la función de interrupción 0x80 y el programa termina con otra llamada a la función de interrupción 0x80 para salir.
El resultado de la ejecución del programa dependerá de si se usa la instrucción rol o ror para rotar el bit en el byte.
Si se usa la instrucción rol, que rota los bits hacia la izquierda, el resultado será 1, ya que el bit más significativo se moverá al bit menos significativo y se establecerá en 1.
En cualquier caso, el resultado se imprimirá en la salida estándar como "El resultado es: X", donde X es el valor resultante de la rotación de bits. Luego se agregará un salto de línea al final.
La línea "rol bl, 1" es una instrucción de rotación de bits que se utiliza para rotar los bits de un byte hacia la izquierda (o hacia la derecha, según la instrucción ror) en lenguaje ensamblador. La instrucción "rol" es un mnemónico que representa "rotate left", que en español se traduce como "rotar hacia la izquierda".
El código en cuestión es un programa simple en lenguaje ensamblador que realiza una rotación de bits en un byte y muestra el resultado en la salida estándar mediante una llamada a la función de interrupción 0x80. El objetivo del programa es demostrar cómo usar las instrucciones de rotación de bits y las funciones de interrupción en lenguaje ensamblador.
Assembly Programming Tutorial. (s. f.). https://www.tutorialspoint.com/assembly_programming/index.htm
Practica 10 - Rotación a la derecha
El siguiente código es un programa escrito en lenguaje ensamblador que imprime en la salida estándar (stdout) el resultado de rotar un bit en un byte y agrega un salto de línea al final.
El objetivo principal del programa es demostrar cómo usar las instrucciones de rotación de bits y las funciones de interrupción en lenguaje ensamblador.
El código en cuestión es un programa escrito en lenguaje ensamblador que muestra cómo rotar un bit en un byte y cómo imprimir el resultado en la salida estándar. El programa utiliza instrucciones de rotación de bits y funciones de interrupción para realizar estas operaciones.
Descripción del comportamiento de los registros correspondientes sobre el siguiente código:
; salto de linea
section .data
msg db 'El resultado es: '
ln db 10, 13
lonln equ 2
section .bss
resultado resb 1
section .text
global _start
_start:
; 128 64 32 16 8 4 2 1
;| 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
;| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
mov bl, 128
ror bl, 1 ; rotación a la der
mov eax, 4
mov ebx, 1
mov ecx, msg
mov edx, 13
int 0x80
add bl, 48
mov [resultado], bl
mov eax, 4
mov ebx, 1
mov ecx, resultado
mov edx, 1
int 0x80
; salto de linea
mov eax, 4
mov ebx, 1
mov ecx, ln
mov edx, lonln
int 0x80
mov eax, 1
mov ebx, 0
int 0x80
La sección .data contiene dos variables: msg y ln. msg es una cadena de texto que contiene el mensaje "El resultado es: ", y ln es una secuencia de bytes que representan un salto de línea. lonln es una constante que define la longitud de ln.
La sección .bss declara una variable llamada resultado como un byte reservado.
La sección .text es donde se encuentra el código del programa en sí. global _start indica que el punto de entrada del programa es la etiqueta _start.
La primera instrucción del programa es una tabla de bits que representa el número binario 10000000. Luego, el registro bl se mueve a la derecha una posición usando la instrucción ror bl, 1. Como resultado, bl contiene ahora el valor binario 01000000, que es el número 64 en decimal.
La siguiente sección del programa utiliza la llamada al sistema int 0x80 para mostrar el mensaje de texto almacenado en msg en la consola. Se cargan los valores apropiados en los registros eax, ebx, ecx y edx antes de la llamada al sistema.
A continuación, se agrega el valor decimal 48 al registro bl, que contiene el valor 64. Este número ahora se convierte en el valor decimal 112, que es el carácter ASCII correspondiente al número 0.
El valor actual de bl se almacena en la variable resultado, que es un byte reservado. Se utiliza nuevamente la llamada al sistema int 0x80 para mostrar este valor en la consola.
El programa continúa con una llamada al sistema para imprimir un salto de línea en la consola.
Por último, se utiliza otra llamada al sistema para salir del programa. Se cargan los valores apropiados en los registros eax y ebx antes de la llamada al sistema.
Corresponde a los datos obtenidos experimentalmente y tratados estadísticamente. Lo ideal es que utilices tablas para organizar y resumir.
La línea ror bl, 1 realiza una rotación hacia la derecha de un bit en el registro bl. La instrucción ror (Rotate Right) desplaza los bits de un operando hacia la derecha, desplazando el bit más a la derecha a la posición más a la izquierda, mientras que el bit más a la izquierda se desplaza a la posición más a la derecha. El bit que se desplaza fuera del registro se coloca en la posición más a la derecha del registro.
En este caso, la instrucción ror bl, 1 rota el bit más a la derecha del registro bl a la posición más a la izquierda, y el bit más a la izquierda se coloca en la posición más a la derecha del registro. Como resultado, el valor binario de bl cambia de 10000000 a 01000000, lo que equivale al número decimal 64.
La línea ln db 10, 13 define una variable llamada ln en la sección .data. La variable ln es una secuencia de dos bytes que representan un salto de línea en la consola. El valor decimal 10 corresponde al carácter de avance de línea (line feed) y el valor decimal 13 corresponde al carácter de retorno de carro (carriage return). Juntos, estos caracteres indican a la consola que se debe avanzar una línea y volver al principio de la línea.
La línea lonln equ 2 define una constante llamada lonln en la sección .data. La constante lonln se define utilizando la directiva equ (equivalencia) y se establece en el valor 2. La constante lonln se utiliza para indicar la longitud de la secuencia de bytes ln. Como ln consta de dos bytes, lonln se establece en 2. Esto permite que el programa sepa cuántos bytes deben ser impresos en la consola cuando se llama a la función de impresión de ln.
El resultado de la ejecución del programa dependerá de si se usa la instrucción rol o ror para rotar el bit en el byte.
Si se usa la instrucción ror, que rota los bits hacia la derecha, el resultado será 64, ya que el bit menos significativo se moverá al bit más significativo y se establecerá en 1.
En cualquier caso, el resultado se imprimirá en la salida estándar como "El resultado es: X", donde X es el valor resultante de la rotación de bits. Luego se agregará un salto de línea al final.
Assembly Programming Tutorial. (s. f.). https://www.tutorialspoint.com/assembly_programming/index.htm
Practica 11 - Input
Se estudia el tema del manejo de input por medio de la llama al sistema Read()
El objetivo de este programa es demostrar el uso de la entrada (input), por medio de la terminal combinando esto con temas como el salto de línea y demás
El fin de esta practica consiste en estudiar la entrada y salida de datos en lenguaje ensamblador
A continuación la descripción del comportamiento de los registros correspondientes del siguiente código
section .data
Msg1 db "Introduce un numero ", 10
Msg1Len equ $-Msg1
Msg2 db "El numero que ingresaste es: "
Msg3 db 10
Numero db " "
section .bss
section .text
global _start
_start:
mov eax, 4
mov ebx, 1
mov ecx, Msg1
mov edx, Msg1Len
int 0x80
mov eax, 3
mov ebx, 1
mov ecx, Numero
mov edx, 2
int 0x80
mov eax, 4
mov ebx, 1
mov ecx, Msg2
mov edx, Msg2Len
int 0x80
mov eax, 4
mov ebx, 1
mov ecx, numero
mov edx, 2
int 0x80
mov eax, 4
mov ebx, 1
mov ecx, Msg3
mov ecx, edx, 1
int 0x80
mov eax, 1
mov ebx, 0
int 0x80
section .data
Msg1 db "Introduce un numero ", 10
Msg1Len equ $-Msg1
Msg2 db "El numero que ingresaste es: "
Msg3 db 10
Numero db " "
En el bloque de código anterior de define la *variable*
Msg1 con el mensaje para indicar que se introduzca un numero seguido de un 10 que indica un salto de línea, después se define Msg1Len y haciendo uso de *equ $Msg1*
se define la longitud del mensaje para no tener que contar los caracteres del mensaje anterior, a continuación Msg2 que funciona de la misma manera que Msg1, Msg3 funciona como un salto de línea al asignarle el valor de 10 y por ultimo se define Numero
que servirá para almacenar la entrada desde la terminal
mov eax, 4
mov ebx, 1
mov ecx, Msg1
mov edx, Msg1Len
int 0x80
Simplemente se muestra la cadena que contiene Msg1
para esperar a recibir datos es el 3, y el 1 para recibir de la terminal y lo vamos a guardar en la variable numero
mov eax, 3
mov ebx, 1
mov ecx, Numero
mov edx, 2
int 0x80
En este caso mov eax, 3 funciona de manera similar a mov eax, 4 ya que con este ultimo se establece que se mostrara un mensaje, mientras que en el caso de mov eax, 3 se establece que se van a recibir datos (input) y con el mov ebx, 1 que estos datos se recibirán por medio de la consola además que los datos que se recibieron se almacenaran en Numero y finalmente que con mov edx, 2 que podemos recibir números de hasta dos dígitos
mov eax, 4
mov ebx, 1
mov ecx, Msg2
mov edx, Msg2Len
int 0x80
mov eax, 4
mov ebx, 1
mov ecx, numero
mov edx, 2
int 0x80
mov eax, 4
mov ebx, 1
mov ecx, Msg3
mov ecx, edx, 1
int 0x80
Se realiza un salto de línea ya que Msg contiene que valor de 10
Este programa muestra un mensaje pidiendo al usuario que ingrese un número y luego muestra el número ingresado. La salida del programa dependerá del número que el usuario ingrese.
Algo a resaltar es que en esta ocasión se hizo uso no solo de la llamada al sistema Write() sino también la llamada al sistema Read() para leer un numero del usuario con una entrada estándar (terminal)
En términos generales, este ejemplo muestra cómo se pueden utilizar diferentes llamadas al sistema para realizar tareas de entrada y salida de datos en lenguaje ensamblador
Assembly Programming Tutorial. (s. f.). https://www.tutorialspoint.com/assembly_programming/index.htm