0% encontró este documento útil (0 votos)
14 vistas18 páginas

Estudien Muchachos

El documento describe un programa en ensamblador que realiza la suma y multiplicación de dos números ingresados por el usuario. Se detallan las secciones de código, la reserva de memoria y las instrucciones para leer, procesar y mostrar los resultados. Además, se explican las conversiones necesarias entre caracteres y números para realizar las operaciones correctamente.

Cargado por

El Chuy
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
14 vistas18 páginas

Estudien Muchachos

El documento describe un programa en ensamblador que realiza la suma y multiplicación de dos números ingresados por el usuario. Se detallan las secciones de código, la reserva de memoria y las instrucciones para leer, procesar y mostrar los resultados. Además, se explican las conversiones necesarias entre caracteres y números para realizar las operaciones correctamente.

Cargado por

El Chuy
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd

PROGRAMA SUMA RICHI CHINGON ES UNA VRGA

section .bss

Esto le dice al programa:


➡️ “Voy a definir variables sin valor inicial. Solo reserva espacio en memoria.”
.bss significa Block Started by Symbol, una sección para reservar memoria que
estará vacía al inicio.

a resb 2

Aquí estás diciendo:


➡️ “Reserva 2 bytes de memoria para una variable llamada a.”
¿Por qué 2 bytes? Porque cuando el usuario escribe un número y presiona ENTER, se
registran dos caracteres: el número (ej. '4') y el ENTER ('\n' o 0x0A en ASCII).

b resb 2

Igual que con a, reservas 2 bytes para guardar lo que escriba el usuario como
segundo número.

r resb 1

Ahora reservas 1 solo byte para la variable r, donde se va a guardar el resultado de la


suma (en forma de carácter).

section .text

Le estás diciendo al ensamblador:


➡️ “A partir de aquí viene el código que se va a ejecutar.”
Es la sección donde empieza la acción real del programa.

global _start

Le estás diciendo:
➡️ “Este es el punto de inicio del programa.”
Cuando Linux arranque tu programa, va a empezar desde donde diga _start:.
_start:

Es una etiqueta (como un punto de referencia).


No hace nada por sí sola, pero marca el lugar exacto donde empieza a ejecutarse el
código.

mov eax, 3

Esto es una instrucción para el sistema operativo. Le estás diciendo:


➡️ “Quiero usar la función número 3 del sistema Linux, que sirve para leer del
teclado (entrada estándar).”
EAX es un registro del procesador que guarda qué función vas a usar.

mov ebx, 0

EBX es otro registro. Al ponerle 0, estás diciendo:


➡️ “Quiero leer desde el teclado (stdin, entrada estándar).”
En Linux:

• 0 = teclado

• 1 = pantalla

• 2 = errores

mov ecx, a

ECX es el registro que le dice al sistema:


➡️ “Guarda lo que el usuario escriba en la dirección de memoria de la variable a.”

mov edx, 2

EDX dice:
➡️ “Quiero leer 2 bytes.” Uno será el número, y el otro el ENTER que el usuario va a
presionar.
int 0x80

Este es el momento mágico.


➡️ “Ejecuta todo lo que pedí arriba.”
El sistema operativo ve que quieres usar la función 3, con origen 0, destino a, y
longitud 2. Entonces espera que el usuario escriba algo y guarda eso en la variable
a.

mov eax, 3

Otra vez estás diciendo:


➡️ “Quiero leer otro dato del teclado.”

mov ebx, 0

Otra vez:
➡️ “La entrada vendrá del teclado (stdin).”

mov ecx, b

➡️ “Guarda lo que escriba el usuario en la variable b.”

mov edx, 2

➡️ “Voy a leer 2 bytes de nuevo (número + ENTER).”

int 0x80

➡️ “Hazlo.”
El sistema espera que escribas el segundo número, y lo guarda en b.

mov al, [a]

Aquí sacas de memoria lo que estaba guardado en a (el primer número que
escribiste) y lo guardas en el registro AL.
AL es la parte baja del registro EAX. Solo guarda 1 byte. Usamos AL porque cada
número es solo un carácter.

sub al, '0'

Aquí estás haciendo algo clave:


➡️ “Convierte el carácter a número real.”

Por ejemplo:

• '4' en ASCII = 52

• '0' en ASCII = 48

• 52 - 48 = 4

Así conviertes '4' → 4 para que puedas sumarlo como número.

mov bl, [b]

Lo mismo, pero con el segundo número. Lo sacas de la variable b y lo metes en BL


(parte baja de EBX).

sub bl, '0'

Otra conversión de carácter a número.

Si escribiste '5', se convierte en 5 restándole '0'.

add al, bl

Ahora sí:
➡️ “Suma el primer número con el segundo.”
Ambos están ya convertidos a números reales, así que puedes sumarlos
directamente.

add al, '0'


Ahora conviertes el número resultado de nuevo a carácter.
Si la suma fue 9, haces 9 + 48 = 57, que es el carácter '9'.

Esto es porque solo puedes mostrar caracteres en pantalla, no números crudos.

mov [r], al

Guarda el carácter del resultado (por ejemplo '9') en la variable r.

mov eax, 4

➡️ “Quiero usar la función número 4 del sistema: escribir en pantalla (stdout).”

mov ebx, 1

➡️ “Escribe en la pantalla (stdout = 1).”

mov ecx, r

➡️ “Lo que quiero mostrar está en la variable r.”

mov edx, 1

➡️ “Muestra solo 1 byte (un carácter).”

int 0x80

➡️ “Hazlo.”
El carácter que representa la suma se muestra en la pantalla.

mov eax, 1

➡️ “Quiero usar la función número 1: salir del programa.”


xor ebx, ebx

Esto pone el registro EBX en 0.


El valor 0 significa que el programa terminó sin errores.
Se usa xor ebx, ebx en vez de mov ebx, 0 porque es un poco más eficiente en
ensamblador.

int 0x80

➡️ “Finaliza el programa.”
El sistema operativo cierra tu programa y todo terminó.

section .bss

a resb 2

b resb 2

r resb 1

section .text

global _start

_start:

mov eax, 3

mov ebx, 0

mov ecx, a

mov edx, 2

int 0x80

mov eax, 3

mov ebx, 0
mov ecx, b

mov edx, 2

int 0x80

mov al, [a]

sub al, '0'

mov bl, [b]

sub bl, '0'

add al, bl

add al, '0'

mov [r], al

mov eax, 4

mov ebx, 1

mov ecx, r

mov edx, 1

int 0x80

mov eax, 1

xor ebx, ebx

int 0x80
CODIGO MULTIPLICACION RICHI NO LE SABE A ESTE

section .data

Esta sección contiene datos definidos desde el inicio, es decir, variables con valores
fijos.

X dd 3

Define una variable llamada X y le asigna el valor 3.


dd = define double word (4 bytes = 32 bits). Este es el multiplicando.

Y dd 2

Define Y con el valor 2 (multiplicador).


También usa 4 bytes para poder hacer desplazamientos sin errores.

msg_result db "El resultado es: ", 0

Aquí guardas un texto que vas a mostrar antes de imprimir el número.


El , 0 al final es un terminador null (\0) para fines de seguridad (aunque no obligatorio
aquí).

len_result equ $ - msg_result

Calcula cuántos bytes tiene el texto "El resultado es: " automáticamente.
$ representa la posición actual y msg_result la inicial → la resta da la longitud.

newline db 10

El valor 10 en decimal es el salto de línea (\n en ASCII).


Se usará para bajar de línea al final.

section .bss
Sección para variables sin valor inicial, pero que vamos a usar más adelante.

P resd 1

Reserva 4 bytes (1 dword) para la variable P, que va a guardar el resultado de la


multiplicación.

ascii_buf resb 10

Reserva 10 bytes para el buffer de conversión a texto.


Ahí se va a ir armando el número carácter por carácter (máximo 10 dígitos en base
10).

section .text

Empieza la sección donde se escribe el código real que se va a ejecutar.

global _start

Declara el punto de entrada del programa.


Linux sabrá que el programa comienza en _start.

_start:

Etiqueta que marca el inicio del programa.

mov ecx, 8

ECX se usará como contador del ciclo de multiplicación.


Vamos a revisar 8 bits del multiplicador (Y), de derecha a izquierda.

multiplicar:

Etiqueta para el inicio del bucle de multiplicación binaria.


mov eax, [Y]

Carga el valor actual del multiplicador en EAX.

and eax, 1

Hace una operación lógica AND con el bit menos significativo (el de la derecha).
Sirve para saber si el bit actual de Y es 1 o 0.

jz no_sumar

Si el bit es 0, salta a la parte donde no se suma.


jz = Jump if Zero (si el resultado anterior fue 0).

mov eax, [X]

Si no se brincó, significa que el bit era 1.


Entonces carga el multiplicando X en EAX.

add [P], eax

Suma EAX (el multiplicando) al acumulador P, que guarda el resultado final.

no_sumar:

Etiqueta a la que se salta si el bit de Y era 0 (y por lo tanto no se hace suma en esta
vuelta).

mov eax, [X]

Vuelve a cargar el valor actual de X en EAX.

shl eax, 1

Hace un corrimiento a la izquierda: multiplica X por 2.


Esto equivale a avanzar una posición binaria para el siguiente bit.
mov [X], eax

Guarda el nuevo valor de X en la variable original.


Ahora X está duplicado y listo para la próxima iteración.

mov eax, [Y]

Carga de nuevo el valor del multiplicador.

shr eax, 1

Hace un corrimiento a la derecha: divide Y entre 2.


Esto elimina el bit que ya revisamos y avanza al siguiente.

mov [Y], eax

Guarda el nuevo valor de Y actualizado en su variable.

dec ecx

Resta 1 al contador del ciclo.

jnz multiplicar

Si ECX todavía no es 0, salta de nuevo a multiplicar: para repetir el proceso.

mov eax, [P]

Ya terminó el ciclo. Ahora P tiene el resultado de la multiplicación.


Se lo carga en EAX para comenzar la conversión a texto.

lea edi, [ascii_buf + 9]


EDI será un puntero que apunta al final del buffer.
Vamos a construir el número de derecha a izquierda.

mov byte [edi], 0

Pone un terminador null (\0) al final de la cadena para seguridad (aunque en este caso
no es necesario, es buena práctica).

mov ebx, 10

Queremos dividir en base 10 (para convertir a texto), así que ponemos el número 10
en EBX.

convertir:

Etiqueta para el inicio del bucle de conversión numérica a caracteres ASCII.

dec edi

Retrocede 1 byte en el buffer. Vamos a poner el próximo carácter ahí.

xor edx, edx

Pone EDX en cero para que no interfiera con la división.


En divisiones de 32 bits: EDX:EAX / EBX → por eso hay que asegurarse de que EDX = 0.

div ebx

Divide EAX entre 10 (que está en EBX).

• El cociente queda en EAX

• El residuo queda en EDX

add dl, '0'


Convierte el residuo (resto de la división) a carácter ASCII.
Ejemplo: 8 → 56 ('8' en ASCII)

mov [edi], dl

Guarda ese carácter en el buffer en la posición actual.

test eax, eax

Verifica si EAX (el cociente) llegó a cero.

jnz convertir

Si no es cero todavía, vuelve a dividir el número siguiente (sigue convirtiendo).

mov eax, 4

Función del sistema para escribir (sys_write).

mov ebx, 1

1 = salida estándar → la pantalla.

mov ecx, msg_result

ECX apunta al texto "El resultado es: ".

mov edx, len_result

EDX indica cuántos caracteres se van a mostrar del mensaje.

int 0x80

Ejecuta la instrucción de escribir el mensaje en pantalla.


mov eax, 4

Otra vez, función para escribir.

mov ebx, 1

Salida: pantalla.

mov ecx, edi

ECX apunta a la parte del buffer donde está el primer dígito del número
convertido.

mov edx, ascii_buf + 10

EDX se llena con la dirección final del buffer.

sub edx, edi

Calcula la cantidad de caracteres reales que tiene el número convertido.

int 0x80

Imprime el número como texto.

mov eax, 4

Otra vez, llamada a sys_write.

mov ebx, 1

Pantalla.
mov ecx, newline

ECX apunta a un carácter de salto de línea.

mov edx, 1

Se va a escribir solo 1 byte.

int 0x80

Escribe un salto de línea en pantalla.

mov eax, 1

Función del sistema para terminar el programa (sys_exit).

xor ebx, ebx

Código de salida = 0 (todo bien).

int 0x80

Termina el programa.

section .data

X dd 3 ; Multiplicando (15 = 0x0F)

Y dd 2 ; Multiplicador (11 = 0x0B)

msg_result db "El resultado es: ", 0

len_result equ $ - msg_result

newline db 10

section .bss

P resd 1 ; Producto (32 bits)


ascii_buf resb 10 ; Buffer para conversión ASCII

section .text

global _start

_start:

mov ecx, 8

multiplicar:

mov eax, [Y]

and eax, 1

jz no_sumar

mov eax, [X]

add [P], eax

no_sumar:

mov eax, [X]

shl eax, 1

mov [X], eax

mov eax, [Y]

shr eax, 1

mov [Y], eax

dec ecx
jnz multiplicar

mov eax, [P]

lea edi, [ascii_buf + 9] ; Apuntar al final del buffer

mov byte [edi], 0 ; Null-terminator

mov ebx, 10 ; Base 10

convertir:

dec edi

xor edx, edx

div ebx ; eax/10 -> eax (cociente), edx (resto)

add dl, '0' ; Convertir resto a ASCII

mov [edi], dl

test eax, eax

jnz convertir

mov eax, 4 ; sys_write

mov ebx, 1 ; stdout

mov ecx, msg_result

mov edx, len_result

int 0x80

mov eax, 4

mov ebx, 1

mov ecx, edi ; Puntero al inicio del número ASCII

mov edx, ascii_buf + 10 ; Longitud máxima


sub edx, edi ; Calcular longitud real

int 0x80

mov eax, 4

mov ebx, 1

mov ecx, newline

mov edx, 1

int 0x80

mov eax, 1 ; sys_exit

xor ebx, ebx ; Código 0

int 0x80

También podría gustarte