programacion en lenguaje ensamblador con nasm

66
Lenguaje Ensamblador: Guia práctica ...............................................................................................2 ¿QUÉ NECESITO? ...............................................................................................................................2 ¿QUÉ HAGO CON TODOS LOS RECURSOS QUE NECESITO? ..............................................................3 ¡A PROGRAMAR! ...............................................................................................................................7 1. Hola mundo ...............................................................................................................................7 2. Plantilla básica .........................................................................................................................10 3. Ensamblando y enlazando con C: ejemplo mcd ......................................................................12 4. Generando números aleatorios...............................................................................................16 5. Encontrando números primos .................................................................................................19 6. Manipulación de bits: desplazando y alternando ...................................................................33 7. Operaciones booleanas: and, or, xor, not ...............................................................................48 8. Elección sin árbol: escoger número más grande .....................................................................54 9. Arreglos: definiendo y manejando direcciones.......................................................................57 10. Punto flotante: ejemplo ecuación cuadrática .......................................................................61 FUENTES ANEXAS: ...........................................................................................................................65

Upload: jesus-antonio-ferrer-sanchez

Post on 07-Jul-2015

1.566 views

Category:

Software


10 download

DESCRIPTION

Guía práctica de programación en lenguaje ensamblador utilizando NASM bajo Windows y Linux

TRANSCRIPT

Lenguaje Ensamblador: Guia práctica ...............................................................................................2

¿QUÉ NECESITO? ...............................................................................................................................2

¿QUÉ HAGO CON TODOS LOS RECURSOS QUE NECESITO? ..............................................................3

¡A PROGRAMAR! ...............................................................................................................................7

1. Hola mundo ...............................................................................................................................7

2. Plantilla básica .........................................................................................................................10

3. Ensamblando y enlazando con C: ejemplo mcd ......................................................................12

4. Generando números aleatorios...............................................................................................16

5. Encontrando números primos .................................................................................................19

6. Manipulación de bits: desplazando y alternando ...................................................................33

7. Operaciones booleanas: and, or, xor, not ...............................................................................48

8. Elección sin árbol: escoger número más grande .....................................................................54

9. Arreglos: definiendo y manejando direcciones.......................................................................57

10. Punto flotante: ejemplo ecuación cuadrática .......................................................................61

FUENTES ANEXAS: ...........................................................................................................................65

Página 2 de 66

Materia: Lenguaje Ensamblador Clave: F1265

Lenguaje Ensamblador: Guia práctica

Jesús Antonio Ferrer Sánchez

Para programar en lenguaje ensamblador escogí la especificación NASM (Netwide Assembler) que

soporta las plataformas Windows y Unix (Linux), dejando aparte las que son conocidas por defecto

para cada sistema operativo (MASM para Windows, TSAM para Mac y GAS para Linux). Seguro

piensan ¿Cuál es la razón? La respuesta es que el propio nombre lo dice “Netwide Assembler”, es

decir, existe una comunidad que mantiene actualizada documentación y herramientas para

programar en lenguaje ensamblador.

Bueno… manos a la obra, para empezar necesitamos visitar el sitio Web donde se encuentra los más

importante que necesitaremos http://www.nasm.us/, hecho esto la siguiente cuestión es ¿Qué

vamos a utilizar de allí? Pues lo siguiente:

¿QUÉ NECESITO? 1. La documentación, que está aquí:

http://www.nasm.us/docs.php aunque realmente existe documentación más actualizada como en

su sitio de Sourceforge o Git, por ejemplo. Lo más recomendable es utilizar la versión estable.

2. El compilador e intérprete, que está aquí:

http://www.nasm.us/pub/nasm/releasebuilds/?C=M;O=D estando allí debemos abrir la primera

carpeta de arriba hacia abajo que no contenga la terminación rc, por ejemplo abriremos la carpeta

2.11.05 (fijate que no dice 2.11.05rc) estando dentro bajaremos el compilador e intérprete de

acuerdo a nuestro tipo sistema operativo especifico, que se identifican con los nombre de las

carpeta linux/, macosx/ y win32/ para los usuario Windows x64 no se espanten porque dice win32

pueden lograr mayor compatibilidad con DOSBox (http://www.dosbox.com/). Ahora hago una

distinción para Windows y Linux (para Mac no, porque soy super pobre).

2.1. Para los usuarios Windows recomiendo que descarguen el instalador (nasm-2.11.05-

installer.exe, por ejemplo) esto para su mayor comodidad.

2.2. Para los usuarios Linux no es necesario entrar a la carpeta linux/ puesto que lo

recomendable es trabajar con el archivo que se identifica con la terminación .tar.gz (nasm-

2.11.05.tar.gz, por ejemplo) ya verán porque más adelantito.

3. El enlazador para Windows OS (para Linux no es necesario):

UNIVERSIDAD JUÁREZ AUTÓNOMA DE TABASCO

DIVISIÓN ACADÉMICA DE INFORMÁTICA Y SISTEMAS

Página 3 de 66

Materia: Lenguaje Ensamblador Clave: F1265

Necesitamos solamente Alink el cual trabaja en conjunto con Nasm para la plataforma Windows,

este es un complemento totalmente necesario. Para descargarlo debemos ir a:

http://alink.sourceforge.net/download.html estando aquí seleccionar Download ALINK (Win32

version) el cual deberá mandarnos un archivo nombrado al_al.zip

4. Un editor en consola:

Ya sea Vi, Vim o nano, para mi comodidad elegí nano porque viene por defecto en Linux y funciona

igualito en Windows, ya saben para conseguirlo ir a:

http://www.nano-editor.org/ para conseguirlo para Windows navegar hasta: http://www.nano-

editor.org/dist/v2.2/NT/nano-2.2.6.zip y listo habremos descargado nano para Windows. Esto lo

hago para no perder la costumbre de usar la línea de comandos.

Ahora la siguiente cuestión es ¿Qué hago con todo esto… para empezar a volar programando en

Lenguaje ensamblador? Pues lo siguiente:

¿QUÉ HAGO CON TODOS LOS RECURSOS QUE NECESITO? Aquí hago distinción sobre qué hacer, primero en Windows y acto seguido en Linux, como sigue:

En Windows:

1. Ejecutamos el instalador (nasm-2.11.05-installer.exe, por ejemplo). Dejamos que se instale todo

por defecto. Por ejemplo, dejen que sea creado un acceso directo en el escritorio ya que nos va

ahorrar esfuerzo para hacer algo que explicare a continuación.

2. Una vez que está instalado recurrimos al acceso directo que había comentado o vamos a su

carpeta respectiva carpeta en el menú de inicio. Lo que vamos a hacer aquí es que por medio de la

opción Abrir la ubicación del archivo vamos a ubicarnos donde se encuentran todos los recursos de

instalación. Esta carpeta la mantendremos abierta nos será útil unos pasos más adelante.

Página 4 de 66

Materia: Lenguaje Ensamblador Clave: F1265

3. Se supone que todavía tenemos abierta la carpeta donde está instalado NASM, bueno lo siguiente

es extraer allí el archivo al_al.zip que yo nombré alinker.zip los archivos tal y como se muestran NO

deben ser extraídos en una carpeta dentro de la carpeta ..\AppData\Local\nasm deben estar en la

misma jerarquía.

4. Lo siguiente es copiar la ruta de instalación y agregarla a PATH en las variables de entorno de

Windows. Ustedes ya saben cómo, nos quedaría más o menos así:

5. El paso 4 o punto cuatro es para ahorranos chamba y que nasm sea accesible desde cualquier

parte de nuestro sistema operativo Windows. Lo que vamos a hacer ahora es que nasm y alinker se

casen para ello haremos lo siguiente:

5.1. Escribir desde la consola (CMD) lo siguiente alink y le daremos Enter a todo (--Press

Enter to continue--)

Página 5 de 66

Materia: Lenguaje Ensamblador Clave: F1265

Después de esto nos mandará fuera de ejecución de alink. Lo que sigue aquí mismo es

verificar que se conserva la armonía con el depurador nativo de Windows para lo que

escribiremos debug y después r damos Enter y luego salimos escribiendo q habiendo

obtenido el stock de registros. La imagen siguiente muestra lo que comente.

Nota: Para quienes trabajen con Windows x64 pueden con el DOSBox (antes mencionado)

para ello pueden hay video donde explican acerca de él. Enlace exacto:

https://www.youtube.com/watch?v=pMrh-ppGp1E además necesitarán el archivo

debug.exe el cual lo subí a GoogleDrive junto con MASM en el siguiente enlace:

https://drive.google.com/file/d/0BxC4ezWP4GyIeFp1T3pRanVQVFk/view?usp=sharing y

como ya saben, usarlo con variables de entorno.

6. Ahora lo que hago es por pura vanidad, vamos con el archivo comprimido que descargamos que

contiene al editor nano (nano-editor_2.2.6.zip) lo extraemos en una ubicación acorde a nuestro

gusto (C:\nano_2.2.6, por ejemplo) y lo agregamos a las variables de entorno.

Y listo ya tenemos todo listo para empezar con nasm desde Windows.

Página 6 de 66

Materia: Lenguaje Ensamblador Clave: F1265

En Linux:

1. Para instalar NASM en Linux hay dos vías una es por vía repositorio escribiendo sudo apt-get

install nasm lo cual nos instalará una versión sumamente antigua y la otra es por medio de la

compilación del archivo que descargamos (nasm-2.11.05.tar.gz). Si elegimos esta última debemos

hacer lo siguiente.

1.1. Extraer el archivo en un directorio con privilegios root en /usr/local/src por ejemplo

debemos conseguir que se nos cree la carpeta respectiva nasm-2.11.05 en mi caso, por

ejemplo. Luego nos ubicaremos dentro de dicha carpeta.

1.2. Lo que sigue es abrir la terminal y navegar hasta la carpeta que tenemos abierta. Luego

escribiremos sudo ./configure para ejecutar este script de unos 190 kb esperaremos

mientras se lleva a cabo el proceso una vez terminado tipeamos make para que se compilen

los archivos binarios de nasm, volvemos a esperar y ahora si a instalarlo con make install

que por defecto manda la instalación a /usr/local/bin luego comprobamos que

efectivamente tenemos instalado nasm como se ilustra en la siguiente imagen.

Debo mencionar que las ubicaciones simbólicas indican que en nuestro sistema instalo

correctamente a nasm.

Página 7 de 66

Materia: Lenguaje Ensamblador Clave: F1265

1.3. Tenemos la opción de agregar herramientas que complementan a nasm para ello

estando en /usr/local/src/nasm-2.11.05/rdoff desde terminal escribimos make rdf y luego

make rdf_install

1.4 Por ultimo eliminamos los archivos archivos de nasm de la ubicación /usr/local/src/ pues

ya no los necesitamos.

Y listo ya tenemos todo listo para empezar con NASM desde Linux. Al parecer fue más rollo para

Windows, disculpen...

¡A PROGRAMAR!

Para saber cómo trabajar con nasm consulte la documentación donde antes mencione, ya sea en

html o pdf.

Para estudiar los fundamentos hay 3 fuentes que recomiendo:

1. Abre los Ojos al Ensamblador: http://www.abreojosensamblador.net/Productos/AOE/Index.html

2. Assembly in youtube: https://www.youtube.com/playlist?list=PL001102C2DF1D0CE9

3. Intel® 64 and IA-32 Architectures Software:

http://www.intel.com/content/www/us/en/processors/architectures-software-developer-

manuals.html

1. Hola mundo La finalidad de este primer programa es seguir la tradición y para explicar la manera de trabajar que

consiste en editar un archivo .asm y compilarlo con nasm. Veamos cómo se hace:

En Windows:

Editamos nuestro archivo holawindows.asm desde nano. Una vez editado guardamos y nos

volvemos a ubicar desde consola en el directorio desde el cual estamos trabajando con el código.

Página 8 de 66

Materia: Lenguaje Ensamblador Clave: F1265

Para compilarlo escribimos nasm holawindows.asm -o holawindows.[com, exe] en muestro caso

exe con la instrucción de salida de nasm (-o). Después damos Enter, revisamos que efectivamente

ha sido creado y lo mandamos a ejecutar escribiendo el nombre del archivo sin extensión para

comprobar. Lo mismo pasaría si decidiéramos generar un ejecutable .com sólo que lo ejecutaríamos

con un tercer archivo que es generado por el propio nasm.

En Linux:

Primero nos aseguramos que el directorio en el que vamos a trabajar esta con propiedades de

lectura, escritura y ejecución (chmod 777). Entonces editamos nuestro archivo holalinux.asm desde

nano. Una vez editado guardamos y nos volvemos a ubicar desde terminal en el directorio desde el

cual estamos trabajando con el código.

Para enlazar escribimos nasm -f elf holalinux.asm damos Enter y para ensamblar escribimos ld -s -

o holalinux holalinux.o donde primero nos creará el script de ejecución y luego el archivo objeto

binario. Después damos Enter, revisamos que efectivamente 2 archivos han sido creados y lo

mandamos a ejecutar escribiendo ./holalinux el nombre del archivo sin extensión para comprobar.

Página 9 de 66

Materia: Lenguaje Ensamblador Clave: F1265

CÓDIGO:

holawindows.asm

org 100h

mov dx,string ; definimos la variable string

mov ah,9 ; 9 es copiado en el registro ah

int 21h ; colocamos una instrcción de interrupción

mov ah,4Ch

int 21h

string db 'Hola, Mundo!',0Dh,0Ah,'$' ; 0Dh es el caracter de retornar, 0Ah es el pie de

linea, el signo $ es para terminar la cadena

holalinux.asm

section .text

global _start

_start:

mov eax,4 ; ID de llamada al sistema: sys_write - escribir

mov ebx,1 ; descriptor de archivo para salida estandard

mov ecx,string ; dirección de string

mov edx,length ; string length

int 80h ; llamada al sistema

mov eax,1 ; ID de llamada al sistema: sys_exit - salida

mov ebx,0 ; codigo 0 de salida: no error

int 80h ; llamada al sistema

section .data

string: db 'Hola Mundo!',0Ah ; string de salida

Página 10 de 66

Materia: Lenguaje Ensamblador Clave: F1265

length: equ 13 ; longitud del string

2. Plantilla básica

Antes de empezar quiero hacer paréntesis. (Supongo que alrededor del 80% trabajará desde

Windows así que desde ahora voy a continuar desde el entorno Windows).

Esto con la finalidad de reducir el tamaño del documento con las demostraciones para ambos

sistemas operativos.

Ok… Este programa consiste en el esqueleto que tiene básicamente un programa en ensamblador

haciendo uso de declaraciones, comentarios, funciones y constantes. Editamos nuestro archivo

esqueleto.asm y guardamos.

Este código realmente no es funcional y nuestro resultado es que manda como salida mensajes de

error al momento de la compilación debido a que algunas instrucciones están incompletas, pues

solo han sido colocadas en su respectivo lugar pero no se están manejando con su sintaxis correcta.

En este caso es enter en la línea 12, push en la línea 13 y pop en la línea 17.

Página 11 de 66

Materia: Lenguaje Ensamblador Clave: F1265

CÓDIGO:

esqueleto.asm

segment .data

;

; data inicializado

;

segment .bss

;

; data unitilizado

;

segment .text

global _func

_func:

enter n,0 ; línea 12

push ; guardar registros línea 13

;

; cuerpo de la funcion

;

pop ; devolver registros línea 17

mov eax,0 ; retornar valor

leave

ret

Otra forma de tener nuestra plantilla sería como sigue:

esqueleto2.asm

segment .data

;

; data inicializado

;

segment .bss

;

; data unitilizado

;

segment .text

Página 12 de 66

Materia: Lenguaje Ensamblador Clave: F1265

global _func

_func:

push ebp ; si necesitamos que esta instrucción se ejecute antes

mov ebp,esp ; copiamos ebp en esp

sub esp,n ; sustituimos por enter

push ; guardar registros

;

; cuerpo de la funcion

;

pop ; devolver registros

mov eax,0 ; retornar valor

mov esp,ebp

pop ebp

ret ; devolvemos el valor de la rutina

3. Ensamblando y enlazando con C: ejemplo mcd

En este programa veremos cómo podemos trabajar desde ensamblador con código fuente del

lenguaje C. Para esto, el ejemplo consiste en encontrar el máximo común divisor con el modo

sencillo, aquí editamos el archivo mcd.asm con nuestro respectivo código. Lo guardamos.

Luego creamos nuestro código en C, en este caso lo nombré codigoprincipal.c en el cual solo se

reciben y envían valores pues el algoritmo se ejecuta en código ensamblador. Lo guardamos.

Página 13 de 66

Materia: Lenguaje Ensamblador Clave: F1265

Lo que sigue es hacer el constructor del ensamblado y enlazado, aquí el truco es por medio de un

archivo ejecutable por lotes el cual llamé construir.bat en el cual indicamos que sean limpiados los

archivos de salida que hayamos generado previamente con erase, luego establecemos variables de

recursos para el compilador Visual C/C++ (pues tengo instalado Visual Studio). Debo hacer énfasis

en que la línea marca @set BIN=C:\Program Files\Microsoft Visual Studio 12.0\VC\bin para que nos

funcione mejor la agreguemos al PATH en las variables de entorno, pues en esta ruta se encuentra

el ejecutable cl.exe (compilador de optimización x86). Luego análogamente a la opción -o de nasm

utilizamos -f para indicar que mande de salida ejecutable x86, luego utilizamos la opción --prefix

más _ para el argumento dado para todas las variables globales o externos, como en C. Lo cual va

de la mano con el compilador de optimización x86 que se encargará de codigoprincipal.c y mcd.obj,

y guardamos.

Acto seguido ejecutamos construir.bat desde consola damos Enter y esperamos a que el proceso

termine, luego revisamos los archivos de salida creados.

Página 14 de 66

Materia: Lenguaje Ensamblador Clave: F1265

Por ultimo verificamos que nuestro ejecutable .exe si funcione.

CÓDIGO:

mcd.asm

segment data

segment bss

Página 15 de 66

Materia: Lenguaje Ensamblador Clave: F1265

segment text

global mcd

mcd:

push ebp

mov ebp,esp

mov eax,[ebp+8] ; x

mov ebx,[ebp+12] ; y

looptop:

cmp eax,0 ; if (x == 0) hemos terminado

je goback

cmp eax,ebx ; hacer que cierto valor x sea un numero mas grande

jge modulo

xchg eax,ebx ; intercambiar x & y

modulo:

cdq ; setup para division

idiv ebx ; dividir edxeax por ebx

mov eax,edx ; el residuo esta en edx

jmp looptop

goback:

mov eax,ebx ; retornar y

mov esp,ebp

pop ebp

ret

codigoprincipal.c

#include <stdio.h>

int mcd(int a,int b);

int main() {

int result;

int a;

int b;

Página 16 de 66

Materia: Lenguaje Ensamblador Clave: F1265

a = 46;

b = 90;

printf("%d y %d tienen un mcd de %d\n",a,b,mcd(a,b));

a = 9863;

b = 41272;

printf("%d y %d tiene un mcd de %d\n",a,b,mcd(a,b));

}

construir.bat

erase *.obj

erase *.exe

@set INCLUDE=C:\Program Files\Microsoft Visual Studio 12.0\VC\include

@set LIB=C:\Program Files\Microsoft Visual Studio 12.0\VC\lib;C:\Program Files\Microsoft

SDKs\Windows\v7.1A\Lib

@set BIN=C:\Program Files\Microsoft Visual Studio 12.0\VC\bin

nasm -f win32 mcd.asm --prefix _

cl codigoprincipal.c mcd.obj

4. Generando números aleatorios

Este programa consiste en usar el algoritmo inorder para generar un número entero aleatorio entre

un rango especificado ya sea entre números positivos y negativos.

Suponemos que con los ejemplos anteriores ya tenemos claro cuál es nuestro patrón de producción

a código final, por lo que no entraremos en tanto detalle redundando en cosas que debemos hacer.

Ok… editamos nuestro código en C que llamaremos codigo_random.c, en ensamblador

enteros_random.asm y nuestro script de builder construir_random.bat y vemos nuestro resultado.

Página 17 de 66

Materia: Lenguaje Ensamblador Clave: F1265

CÓDIGO:

enteros_random.asm

segment .data

segment .bss

segment .text

global enterorandom ; definimos nuestra variable global

enterorandom:

push ebp

mov ebp,esp

mov eax,[ebp+8] ; primer argumento

cmp eax,[ebp+12] ; asegurarse de que el primer argumento es menor

jl inorder

xchg eax,[ebp+12] ; intercambiar primero y segundo

mov [ebp+8],eax

inorder: ; creamos la funcion inorder entre preorder y postorder

rdtsc ; leer contador de marca de tiempo

shr eax,2

mov ebx,[ebp+12] ; el valor más grande

add ebx,1 ; sumar uno

sub ebx,[ebp+8] ; subtracción del valor delta

cdq ; limpiar edx

idiv ebx ; dividir edxeax por ebx

add edx,[ebp+8]

goback:

mov eax,edx

mov esp,ebp

pop ebp

ret

Página 18 de 66

Materia: Lenguaje Ensamblador Clave: F1265

codigo_random.c

#include <stdio.h>

int enterorandom(int menor,int mayor);

int main() {

int i;

int a;

int b;

a = 1;

b = 18;

printf("Entero aleatorio entre %d y %d: %d\n",a,b,enterorandom(a,b));

a = 5500;

b = 100;

printf("Entero aleatorio entre %d y %d: %d\n",a,b,enterorandom(a,b));

a = -20;

b = 20;

printf("Entero aleatorio entre %d y %d: %d\n",a,b,enterorandom(a,b));

}

construir_random.bat

erase *.obj

erase *.exe

@set INCLUDE=C:\Program Files\Microsoft Visual Studio 12.0\VC\include

@set LIB=C:\Program Files\Microsoft Visual Studio 12.0\VC\lib;C:\Program Files\Microsoft SDKs\Windows\v7.1A\Lib

nasm -f win32 enteros_random.asm --prefix _

cl codigo_random.c enteros_random.obj

Página 19 de 66

Materia: Lenguaje Ensamblador Clave: F1265

5. Encontrando números primos Aquí trabajamos con el manejo de entrada y salida de datos definidos por el usuario por medio de

un programa que se encarga de encontrar los números primos entre una rango que debe ser

especificado al inicio de ejecución.

Para esto se codificaron los archivos codigo_primo.c, primo.asm, entrada.asm, salida.asm y

construir_primo.bat, nuestro resultado es como se muestra en la imagen.

CÓDIGO:

primo.asm

segment .data

inferior_prompt: db "Valor inferior a probar: ",0

superior_prompt: db "Valor superior a probar: ",0

newline: db 10,0

segment .bss

inferior: resd 1

superior: resd 1

recorrer: resd 1

factor: resd 1

segment .text

extern out_integer

extern in_integer

extern out_string

global encontrar_primos

encontrar_primos:

Página 20 de 66

Materia: Lenguaje Ensamblador Clave: F1265

enter 0,0

pushad

pushfd

; pedir límites superior e inferior

push dword inferior_prompt

call in_integer

pop ebx

mov [inferior],eax

or eax,0x00000001

mov [recorrer],eax

push dword superior_prompt

call in_integer

pop ebx

mov [superior],eax

mov dword [factor],2

; parte superior del bucle de prueba

factortest:

mov eax,[factor] ; prueba para el factor mas grande

imul eax,eax

cmp [recorrer],eax

jl encontrar

mov eax,[recorrer] ; prueba para el acarreo de división

mov ebx,[factor]

cdq

idiv ebx

cmp edx,0

je siguiente

add dword [factor],1 ; empujar factor y ciclar

jmp factortest

Página 21 de 66

Materia: Lenguaje Ensamblador Clave: F1265

; encontrar un primo

encontrar:

push dword [recorrer]

call out_integer

pop eax

push dword newline

call out_string

pop eax

; pasar al siguiente primo candidato

siguiente:

mov eax,[recorrer]

add eax,2

cmp eax,[superior]

jg terminado

mov [recorrer],eax

mov dword [factor],2

jmp factortest

terminado:

popfd

popad

mov eax,0

leave

ret

codigo_primo.c

void encontrar_primos(void);

int main()

{

encontrar_primos();

}

Página 22 de 66

Materia: Lenguaje Ensamblador Clave: F1265

entrada.asm

segment .data

segment .bss

char_hold: resd 1

str_hold: resb 20

str_len: equ $-str_hold-1

value: resd 1

segment .text

extern out_string

extern getchar

global in_char

in_char:

enter 0,0

pushad

pushfd

push dword [ebp+8]

call out_string

pop eax

mov byte [char_hold],' '

call getchar

cmp eax,10

jz .in_char_finish

mov [char_hold],al

Página 23 de 66

Materia: Lenguaje Ensamblador Clave: F1265

.in_char_flush:

call getchar

cmp eax,10

jnz .in_char_flush

.in_char_finish:

popfd

popad

mov al,[char_hold]

leave

ret

global in_string

in_string:

enter 0,0

pushad

pushfd

push dword [ebp+8]

call out_string

pop eax

mov ebx,str_hold ; dirección para almacenar cadena

mov byte [ebx],0

mov ecx,str_len ; longitud máxima de la cadena

.in_string_loop:

call getchar

Página 24 de 66

Materia: Lenguaje Ensamblador Clave: F1265

cmp eax,10

jz .in_string_finish

mov [ebx],al

add ebx,1

mov byte [ebx],0

sub ecx,1

jnz .in_string_loop

.in_string_flush:

call getchar

cmp eax,10

jnz .in_string_flush

.in_string_finish:

popfd

popad

mov eax,str_hold

leave

ret

global in_integer

in_integer:

enter 0,0

pushad

pushfd

Página 25 de 66

Materia: Lenguaje Ensamblador Clave: F1265

push dword [ebp+8]

call in_string

pop ebx

xor ecx,ecx

.in_integer_loop:

xor ebx,ebx

mov bl,[eax]

cmp bl,0x30

jl .in_integer_finish

cmp bl,0x39

jg .in_integer_finish

sub ebx,0x30

mov edx,ecx

shl edx,1

shl ecx,3

add ecx,edx

add ecx,ebx

add eax,1

jmp .in_integer_loop

.in_integer_finish:

mov [value],ecx

popfd

popad

mov eax,[value]

leave

Página 26 de 66

Materia: Lenguaje Ensamblador Clave: F1265

ret

salida.asm

%define CF_BIT 0x00000001

%define PF_BIT 0x00000004

%define AF_BIT 0x00000010

%define ZF_BIT 0x00000040

%define SF_BIT 0x00000080

%define DF_BIT 0x00000400

%define OF_BIT 0x00000800

; El segmento de datos ;;;;;;;;;;;;;;;;

segment .data

string_fmt: db "%s",0

integer_fmt: db "%d",0

flag_string: db "flags: ",0

cf_string: db "CF ",0

pf_string: db "PF ",0

af_string: db "AF ",0

zf_string: db "ZF ",0

sf_string: db "SF ",0

df_string: db "DF ",0

of_string: db "OF ",0

newline_string: db 10,0

hex_reg_fmt: db "eax: 0x%.8X ebx: 0x%.8X ecx: 0x%.8X edx: 0x%.8X",10

db 0

Página 27 de 66

Materia: Lenguaje Ensamblador Clave: F1265

dec_reg_fmt: db "eax: %d ebx: %d ecx: %d edx: %d",10

db 0

; El segmento bss ;;;;;;;;;;;;;;;;

segment .bss

flags: resd 1

; El segmento de texto ;;;;;;;;;;;;;;;;

segment .text

extern printf

global out_string

out_string:

enter 0,0

pushad

pushfd

push dword [ebp+8]

push dword string_fmt

call printf

pop ecx

pop ecx

popfd

popad

leave

ret

global out_flags

Página 28 de 66

Materia: Lenguaje Ensamblador Clave: F1265

out_flags:

enter 0,0

pushad

pushfd

push dword flag_string

call out_string

pop eax

mov eax,[esp] ; obtener una copia de las banderas

mov [flags],eax

; La bandera de acarreo (CF)

mov eax,[flags]

test eax,CF_BIT

jz cf_not

push cf_string

call out_string

pop eax

cf_not:

; La bandera de paridad (PF)

mov eax,[flags]

test eax,PF_BIT

jz pf_not

push pf_string

call out_string

pop eax

pf_not:

Página 29 de 66

Materia: Lenguaje Ensamblador Clave: F1265

; La bandera de acarreo auxiliar

mov eax,[flags]

test eax,AF_BIT

jz af_not

push af_string

call out_string

pop eax

af_not:

; La bandera de cero

mov eax,[flags]

test eax,ZF_BIT

jz zf_not

push zf_string

call out_string

pop eax

zf_not:

; La bandera de signo

mov eax,[flags]

test eax,SF_BIT

jz sf_not

push sf_string

call out_string

pop eax

sf_not:

; La bandera de dirección

mov eax,[flags]

test eax,DF_BIT

Página 30 de 66

Materia: Lenguaje Ensamblador Clave: F1265

jz df_not

push df_string

call out_string

pop eax

df_not:

; La bandera de desbordamiento

mov eax,[flags]

test eax,OF_BIT

jz of_not

push of_string

call out_string

pop eax

of_not:

; Un salto de línea

push dword newline_string

call out_string

pop eax

popfd

popad

leave

ret

; ----------------------------

global out_hex_registers

out_hex_registers:

enter 0,0

Página 31 de 66

Materia: Lenguaje Ensamblador Clave: F1265

pushad

pushfd

push edx

push ecx

push ebx

push eax

push dword hex_reg_fmt

call printf

add esp,20

popfd

popad

leave

ret

global out_integer

out_integer:

enter 0,0

pushad

pushfd

push dword [ebp+8]

push dword integer_fmt

call printf

pop ecx

pop ecx

Página 32 de 66

Materia: Lenguaje Ensamblador Clave: F1265

popfd

popad

leave

ret

global out_dec_registers

out_dec_registers:

enter 0,0

pushad

pushfd

push edx

push ecx

push ebx

push eax

push dword dec_reg_fmt

call printf

add esp,20

popfd

popad

leave

ret

construir_primo.bat

erase *.obj

erase *.exe

@set INCLUDE=C:\Program Files\Microsoft Visual Studio 12.0\VC\include

Página 33 de 66

Materia: Lenguaje Ensamblador Clave: F1265

@set LIB=C:\Program Files\Microsoft Visual Studio 12.0\VC\lib;C:\Program Files\Microsoft

SDKs\Windows\v7.1A\Lib

nasm -f win32 primo.asm --prefix _

nasm -f win32 entrada.asm --prefix _

nasm -f win32 salida.asm --prefix _

cl codigo_primo.c primo.obj entrada.obj salida.obj

Además, anexo el script constructor para Linux (por si las dudas). Para los Linuxeros.

construir_primo_linux

nasm -f elf primo.asm

nasm -f elf entrada.asm

nasm -f elf salida.asm

gcc codigo_primo.c primo.o entrada.o salida.o -o codigo_primo

6. Manipulación de bits: desplazando y alternando

Este programa es una colección de métodos para practicar con las variantes que podemos codificar

para mover bits con la bandera de acarreo (CF, con los 16 bits) tanto a la derecha como a la izquierda.

Para esto, se ha definido el archivo mover.asm que es la colección de métodos, los archivos:

aritmetica_izquierda.c, aritmetica_derecha.c, logica_izquierda.c, logica_derecha.c,

alternar_izquierda.c, alternar_derecha.c, acarreo_alternar_izquierda.c y

acarreo_alternar_derecha.c para llamar cada método por separado. Reutilizamos el archivo con el

código de salida.asm para no tener problemas con los caracteres de salida y mostrar.asm de donde

invocamos la función encargada de trabajar con las cadenas de bits a mostrar. Para compilarlo

reutilizamos el constructor del ejemplo anterior y lo adaptamos a los archivos de código creados

para la manipulación de bits, en nuestro caso podemos nombrarlo construir_mover_bits.bat, y una

vez creados nuestros ejecutables probamos uno por uno para ver el resultado por cada método.

Página 34 de 66

Materia: Lenguaje Ensamblador Clave: F1265

CÓDIGO:

mover.asm

segment .data

segment .bss

segment .text

extern mostrar_ax

global logica_izquierda

logica_izquierda:

enter 0,0

pushad

mov ax,0x8002

call mostrar_ax

shl ax,1

call mostrar_ax

shl ax,1

call mostrar_ax

popad

leave

ret

Página 35 de 66

Materia: Lenguaje Ensamblador Clave: F1265

global logica_derecha

logica_derecha:

enter 0,0

pushad

mov ax,0x8002

call mostrar_ax

shr ax,1

call mostrar_ax

shr ax,1

call mostrar_ax

popad

leave

ret

global aritmetica_izquierda

aritmetica_izquierda:

enter 0,0

pushad

mov ax,0x8002

call mostrar_ax

sal ax,1

call mostrar_ax

sal ax,1

call mostrar_ax

popad

leave

ret

global aritmetica_derecha

aritmetica_derecha:

Página 36 de 66

Materia: Lenguaje Ensamblador Clave: F1265

enter 0,0

pushad

mov ax,0x8002

call mostrar_ax

sar ax,1

call mostrar_ax

sar ax,1

call mostrar_ax

popad

leave

ret

global alternar_izquierda

alternar_izquierda:

enter 0,0

pushad

mov ax,0x8002

call mostrar_ax

rol ax,1

call mostrar_ax

rol ax,1

call mostrar_ax

popad

leave

ret

global alternar_derecha

alternar_derecha:

enter 0,0

pushad

Página 37 de 66

Materia: Lenguaje Ensamblador Clave: F1265

mov ax,0x8002

call mostrar_ax

ror ax,1

call mostrar_ax

ror ax,1

call mostrar_ax

popad

leave

ret

global acarreo_alternar_izquierda

acarreo_alternar_izquierda:

enter 0,0

pushad

mov ax,0x8002

call mostrar_ax

rcl ax,1

call mostrar_ax

rcl ax,1

call mostrar_ax

popad

leave

ret

global acarreo_alternar_derecha

acarreo_alternar_derecha:

enter 0,0

pushad

mov ax,0x8002

Página 38 de 66

Materia: Lenguaje Ensamblador Clave: F1265

call mostrar_ax

rcr ax,1

call mostrar_ax

rcr ax,1

call mostrar_ax

rcr ax,1

call mostrar_ax

popad

leave

ret

aritmetica_izquierda.c

#include <stdio.h>

void aritmetica_izquierda(void);

int main()

{

aritmetica_izquierda();

}

aritmetica_derecha.c

#include <stdio.h>

void aritmetica_derecha(void);

int main()

{

aritmetica_derecha();

}

logica_izquierda.c

#include <stdio.h>

Página 39 de 66

Materia: Lenguaje Ensamblador Clave: F1265

void logica_izquierda(void);

int main()

{

logica_izquierda();

}

logica_derecha.c

#include <stdio.h>

void logica_derecha(void);

int main()

{

logica_derecha();

}

alternar_izquierda.c

#include <stdio.h>

void alternar_izquierda(void);

int main()

{

alternar_izquierda();

}

alternar_derecha.c

#include <stdio.h>

void alternar_derecha(void);

int main()

{

Página 40 de 66

Materia: Lenguaje Ensamblador Clave: F1265

alternar_derecha();

}

acarreo_alternar_izquierda.c

#include <stdio.h>

void acarreo_alternar_izquierda(void);

int main()

{

acarreo_alternar_izquierda();

}

acarreo_alternar_derecha.c

#include <stdio.h>

void acarreo_alternar_derecha(void);

int main()

{

acarreo_alternar_derecha();

}

salida.asm

%define CF_BIT 0x00000001

%define PF_BIT 0x00000004

%define AF_BIT 0x00000010

%define ZF_BIT 0x00000040

%define SF_BIT 0x00000080

%define DF_BIT 0x00000400

%define OF_BIT 0x00000800

; El segmento de datos ;;;;;;;;;;;;;;;;

segment .data

Página 41 de 66

Materia: Lenguaje Ensamblador Clave: F1265

string_fmt: db "%s",0

integer_fmt: db "%d",0

flag_string: db "flags: ",0

cf_string: db "CF ",0

pf_string: db "PF ",0

af_string: db "AF ",0

zf_string: db "ZF ",0

sf_string: db "SF ",0

df_string: db "DF ",0

of_string: db "OF ",0

newline_string: db 10,0

hex_reg_fmt: db "eax: 0x%.8X ebx: 0x%.8X ecx: 0x%.8X edx: 0x%.8X",10

db 0

dec_reg_fmt: db "eax: %d ebx: %d ecx: %d edx: %d",10

db 0

; El segmento bss ;;;;;;;;;;;;;;;;

segment .bss

flags: resd 1

; El segmento de texto ;;;;;;;;;;;;;;;;

segment .text

extern printf

global out_string

out_string:

enter 0,0

pushad

pushfd

push dword [ebp+8]

push dword string_fmt

call printf

Página 42 de 66

Materia: Lenguaje Ensamblador Clave: F1265

pop ecx

pop ecx

popfd

popad

leave

ret

global out_flags

out_flags:

enter 0,0

pushad

pushfd

push dword flag_string

call out_string

pop eax

mov eax,[esp] ; obtener una copia de las banderas

mov [flags],eax

; La bandera de acarreo (CF)

mov eax,[flags]

test eax,CF_BIT

jz cf_not

push cf_string

call out_string

pop eax

cf_not:

; La bandera de paridad (PF)

mov eax,[flags]

test eax,PF_BIT

jz pf_not

push pf_string

call out_string

Página 43 de 66

Materia: Lenguaje Ensamblador Clave: F1265

pop eax

pf_not:

; La bandera de acarreo auxiliar

mov eax,[flags]

test eax,AF_BIT

jz af_not

push af_string

call out_string

pop eax

af_not:

; La bandera de cero

mov eax,[flags]

test eax,ZF_BIT

jz zf_not

push zf_string

call out_string

pop eax

zf_not:

; La bandera de signo

mov eax,[flags]

test eax,SF_BIT

jz sf_not

push sf_string

call out_string

pop eax

sf_not:

; La bandera de dirección

mov eax,[flags]

test eax,DF_BIT

jz df_not

push df_string

call out_string

pop eax

df_not:

Página 44 de 66

Materia: Lenguaje Ensamblador Clave: F1265

; La bandera de desbordamiento

mov eax,[flags]

test eax,OF_BIT

jz of_not

push of_string

call out_string

pop eax

of_not:

; Un salto de línea

push dword newline_string

call out_string

pop eax

popfd

popad

leave

ret

; ----------------------------

global out_hex_registers

out_hex_registers:

enter 0,0

pushad

pushfd

push edx

push ecx

push ebx

push eax

push dword hex_reg_fmt

call printf

add esp,20

popfd

Página 45 de 66

Materia: Lenguaje Ensamblador Clave: F1265

popad

leave

ret

global out_integer

out_integer:

enter 0,0

pushad

pushfd

push dword [ebp+8]

push dword integer_fmt

call printf

pop ecx

pop ecx

popfd

popad

leave

ret

global out_dec_registers

out_dec_registers:

enter 0,0

pushad

pushfd

push edx

push ecx

push ebx

push eax

push dword dec_reg_fmt

call printf

add esp,20

Página 46 de 66

Materia: Lenguaje Ensamblador Clave: F1265

popfd

popad

leave

ret

mostrar.asm

segment .data

string_ax: db " "

db " CF="

string_cf: db 0,10,0

segment .bss

segment .text

extern out_string

global mostrar_ax

mostrar_ax:

enter 0,0

pushad

pushfd

mov byte [string_cf],'1'

jc acarreo

mov byte [string_cf],'0'

acarreo:

mov ebx,0

looptop:

rol ax,1

jc uno

mov byte [string_ax+ebx],'0'

jmp siguiente

uno:

mov byte [string_ax+ebx],'1'

Página 47 de 66

Materia: Lenguaje Ensamblador Clave: F1265

siguiente:

inc ebx

cmp ebx,16

jne looptop

push string_ax

call out_string

pop ebx

popfd

popad

leave

ret

construir_mover_bits.bat

erase *.obj

erase *.exe

@set INCLUDE=C:\Program Files\Microsoft Visual Studio 12.0\VC\include

@set LIB=C:\Program Files\Microsoft Visual Studio 12.0\VC\lib;C:\Program Files\Microsoft

SDKs\Windows\v7.1A\Lib

nasm -f win32 mostrar.asm --prefix _

nasm -f win32 salida.asm --prefix _

nasm -f win32 mover.asm --prefix _

cl logica_izquierda.c mostrar.obj salida.obj mover.obj

cl logica_derecha.c mostrar.obj salida.obj mover.obj

cl aritmetica_izquierda.c mostrar.obj salida.obj mover.obj

cl aritmetica_derecha.c mostrar.obj salida.obj mover.obj

cl alternar_izquierda.c mostrar.obj salida.obj mover.obj

cl alternar_derecha.c mostrar.obj salida.obj mover.obj

cl acarreo_alternar_izquierda.c mostrar.obj salida.obj mover.obj

cl acarreo_alternar_derecha.c mostrar.obj salida.obj mover.obj

Para construirlo en Linux aplicaríamos la misma lógica, y la sintaxis del ejemplo anterior.

Página 48 de 66

Materia: Lenguaje Ensamblador Clave: F1265

7. Operaciones booleanas: and, or, xor, not

En este programa se implementan las operaciones booleanas and, or, xor y not, codificando

funciones específicas para cada tipo de operación, accediendo a las banderas de paridad, zero y

signo. Teniendo esta idea necesitamos código de prueba para mostrar los bits originales sobre los

cuales se harán las operaciones. Entonces hacemos lo siguiente.

Como en el ejemplo anterior, creamos en este caso nuestra colección de las funciones que realizan

cada tipo de operación booleana y anexamente nuestro código de prueba que genera los bits

originales que se utilizan como prueba con las banderas. Nuestros recursos son modos_boolean.asm

que es nuestra colección de funciones, los archivos de código C que son: and.c, or.c, xor.c, not.c y

test.c que implementan cada función, reutilizamos mostrar.asm, salida.asm y nuestro constructor

para nuestros recursos de código como en el ejemplo anterior. Ahora vemos nuestro resultado.

CÓDIGO:

modos_boolean.asm

segment .data

segment .bss

segment .text

Prueba original

con las banderas.

Implementando

las funciones.

Página 49 de 66

Materia: Lenguaje Ensamblador Clave: F1265

extern showal

extern out_flags

; funcion operacion and

global andbits

andbits:

enter 0,0

pushad

mov al,11110000b

call showal

mov al,00110011b

call showal

mov al,00110011b

and al,11110000b

call showal

popad

leave

ret

; funcion operacion or

global orbits

orbits:

enter 0,0

pushad

mov al,11110000b

call showal

mov al,00110011b

call showal

mov al,00110011b

or al,11110000b

call showal

popad

Página 50 de 66

Materia: Lenguaje Ensamblador Clave: F1265

leave

ret

; funcion operacion xor

global xorbits

xorbits:

enter 0,0

pushad

mov al,11110000b

call showal

mov al,00110011b

call showal

mov al,00110011b

xor al,11110000b

call showal

popad

leave

ret

; funcion operacion not

global notbits

notbits:

enter 0,0

pushad

mov al,00110011b

call showal

mov al,00110011b

not al

call showal

popad

leave

ret

Página 51 de 66

Materia: Lenguaje Ensamblador Clave: F1265

; funcion de prueba, bits originales

global testbits

testbits:

enter 0,0

pushad

mov al,11001100b

call showal

mov al,00110011b

call showal

mov al,00110011b

test al,11001100b

call out_flags

mov al,11100011b

call showal

mov al,11101100b

call showal

mov al,11100011b

test al,11101100b

call out_flags

popad

leave

ret

test.c

#include <stdio.h>

void testbits(void);

int main(){

testbits();

}

Página 52 de 66

Materia: Lenguaje Ensamblador Clave: F1265

and.c

#include <stdio.h>

void andbits(void);

int main() {

andbits();

}

or.c

#include <stdio.h>

void orbits(void);

int main(){

orbits();

}

xor.c

#include <stdio.h>

void xorbits(void);

int main(){

xorbits();

}

not.c

#include <stdio.h>

void notbits(void);

int main(){

notbits();

}

Página 53 de 66

Materia: Lenguaje Ensamblador Clave: F1265

salida.asm

“reutilizamos el del ejemplo anterior”

mostrar.asm

“reutilizamos el del ejemplo anterior”

construir_modos_boolean.bat

erase *.obj

erase *.exe

@set INCLUDE=C:\Program Files\Microsoft Visual Studio 12.0\VC\include

@set LIB=C:\Program Files\Microsoft Visual Studio 12.0\VC\lib;C:\Program Files\Microsoft

SDKs\Windows\v7.1A\Lib

nasm -f win32 mostrar.asm --prefix _

nasm -f win32 salida.asm --prefix _

nasm -f win32 modos_boolean.asm --prefix _

cl and.c modos_boolean.obj mostrar.obj salida.obj

cl or.c modos_boolean.obj mostrar.obj salida.obj

cl xor.c modos_boolean.obj mostrar.obj salida.obj

cl not.c modos_boolean.obj mostrar.obj salida.obj

cl test.c modos_boolean.obj mostrar.obj salida.obj

y para Linux.

construir_modos_boolean_linux

rm -f *.o

rm -f and

rm -f or

rm -f xor

rm -f not

Página 54 de 66

Materia: Lenguaje Ensamblador Clave: F1265

rm -f test

nasm -f elf salida.asm

nasm -f elf mostrar.asm

nasm -f elf modos_boolean.asm

gcc and.c salida.o modos_boolean.o mostrar.o -o and

gcc or.c salida.o modos_boolean.o mostrar.o -o or

gcc xor.c salida.o modos_boolean.o mostrar.o -o xor

gcc not.c salida.o modos_boolean.o mostrar.o -o not

gcc test.c salida.o modos_boolean.o mostrar.o -o test

8. Elección sin árbol: escoger número más grande

En este programa hacemos uso del algoritmo de búsqueda de una pasada para encontrar el número

más grandes entre dos valores ingresados al inicio de ejecución (sin importar orden y tamaño de

número). En este ejemplo podemos revisar cómo trabajar con simples estructuras de control para

producir resultados en base a valores de entrada.

Para esto codificamos escoger.asm que contiene el algoritmo y las variables, codigo_escoger.c para

utilizar nuestra función, enlazar y compilar nuestro ejecutable, reutilizamos entrada.asm y

salida.asm de ejemplos anteriores y adaptamos nuestro constructor (construir_escoger.bat) de

acuerdo a nuestros recursos de código. Nuestro resultado es el siguiente.

CÓDIGO:

escoger.asm

segment .data

Página 55 de 66

Materia: Lenguaje Ensamblador Clave: F1265

ask1: db "Ingrese primer numero: ",0

ask2: db "Ingrese segundo numero: ",0

tell db "El numero mas grande es: ",0

newline db 10,0

segment .bss

valor1: resd 1

segment .text

extern in_integer

extern out_integer

extern out_string

global escoger

escoger:

enter 0,0

push dword ask1

call in_integer

pop ebx

mov [valor1],eax

push dword ask2

call in_integer

pop ebx

xor ebx,ebx ; zero ebx

cmp eax,[valor1] ; comparar los dos valores

setg bl ; establecer bl=1 si valor2 > valor1, sino cero

not ebx ; cumplimiento del primero

Página 56 de 66

Materia: Lenguaje Ensamblador Clave: F1265

inc ebx ; cumplimiento del segundo

mov ecx,ebx ; copiar en ecx

and ecx,eax ; ecx es: o segundo valor, o cero

not ebx ; ebx es cero o todos

and ebx,[valor1] ; ebx es cero o primer de valor

or ecx,ebx ; ecx es ya sea primer o segundo valor

push dword tell

call out_string

pop ebx

push ecx

call out_integer

pop ebx

push dword newline

call out_string

pop ebx

leave

ret

codigo_escoger.c

#include <stdio.h>

void escoger(void);

int main() {

escoger();

}

entrada.asm

Página 57 de 66

Materia: Lenguaje Ensamblador Clave: F1265

“reutilizamos de un ejemplo anterior”

salida.asm

“reutilizamos el del ejemplo anterior”

construir_escoger.c

erase *.obj

erase *.exe

@set INCLUDE=C:\Program Files\Microsoft Visual Studio 12.0\VC\include

@set LIB=C:\Program Files\Microsoft Visual Studio 12.0\VC\lib;C:\Program Files\Microsoft

SDKs\Windows\v7.1A\Lib

nasm -f win32 escoger.asm --prefix _

nasm -f win32 salida.asm --prefix _

nasm -f win32 entrada.asm --prefix _

cl codigo_escoger.c entrada.obj salida.obj escoger.obj

Y para Linux, pues ya saben...

9. Arreglos: definiendo y manejando direcciones

Este programa depende más de código C que de ensamblador. En este último solo definimos el

manejo de las direcciones en memoria y en lenguaje C codificamos el comportamiento de los

arreglos con valores preestablecidos y la orden de salida. Para que se perciba como podemos

trabajar con ellos se han creado 2 variantes la primera es un arreglo simple donde multiplicamos

sus valores y la segunda es un arreglo multidimensional donde los valores son ordenados por el

método bubble sort, aunque en la salida no se pueda apreciar en primera instancia.

Versión 1: Aquí los recursos de código son codigo_por_cuatro.c, por_cuatro.asm y

construir_arreglos.bat con lo cual obtendremos el siguiente resultado.

Página 58 de 66

Materia: Lenguaje Ensamblador Clave: F1265

Versión 2:

Aquí los recursos de código son codigo_ordenar.c, ordenar.asm y construir_arreglos.bat con lo cual

obtendremos el siguiente resultado. Aquí los valores de cada posición han sido ordenados por el

método bubble sort (ordenamiento burbuja).

CÓDIGO:

codigo_por_cuatro.c

#include <stdio.h>

void por_cuatro(int tamanio,int arr[]);

int main()

{

int i;

int tamanio=10;

int array[10];

for(i=0; i<tamanio; i++) {

array[i] = i;

printf("%d ",array[i]);

}

printf("\n");

por_cuatro(tamanio,array);

for(i=0; i<tamanio; i++) {

printf("%d ",array[i]);

}

Página 59 de 66

Materia: Lenguaje Ensamblador Clave: F1265

printf("\n");

}

por_cuatro.asm

segment .data

segment .bss

segment .text

global por_cuatro

por_cuatro:

push ebp

mov ebp,esp

mov ebx,[ebp+12] ; direccion del arreglo

mov ecx,[ebp+8] ; tamaño del arreglo

top:

mov eax,[ebx]

shl eax,2

mov [ebx],eax

add ebx,4

loop top

leave

ret

codigo_ordenar.c

#include <stdio.h>

void a_ordenar(int tamanio,int arr[]);

int array[] = { 5,32,87,4,92,11,34,3,84,60,17 };

int main()

{

Página 60 de 66

Materia: Lenguaje Ensamblador Clave: F1265

int i;

int tamanio = sizeof(array) / sizeof(int);

for(i=0; i<tamanio; i++) {

printf("%d ",array[i]);

}

printf("\n");

a_ordenar(tamanio,array);

for(i=0; i<tamanio; i++) {

printf("%d ",array[i]);

}

printf("\n");

}

ordenar.asm

segment .data

segment .bss

segment .text

global a_ordenar

a_ordenar:

push ebp

mov ebp,esp

reiniciar:

mov ebx,[ebp+12] ; direccion del arreglo

mov ecx,[ebp+8] ; tamaño del arreglo

sub ecx,1

top:

mov eax,[ebx]

cmp eax,[ebx+4]

Página 61 de 66

Materia: Lenguaje Ensamblador Clave: F1265

jle noswap

xchg eax,[ebx+4]

mov [ebx],eax

jmp reiniciar

noswap:

add ebx,4

loop top

leave

ret

construir_arreglos.bat

erase *.obj

erase *.exe

@set INCLUDE=C:\Program Files\Microsoft Visual Studio 12.0\VC\include

@set LIB=C:\Program Files\Microsoft Visual Studio 12.0\VC\lib;C:\Program Files\Microsoft SDKs\Windows\v7.1A\Lib

nasm -f win32 por_cuatro.asm --prefix _

nasm -f win32 ordenar.asm --prefix _

cl codigo_por_cuatro.c por_cuatro.obj

cl codigo_ordenar.c ordenar.obj

10. Punto flotante: ejemplo ecuación cuadrática

En este programa tratamos con números de punto flotante para que de acuerdo a este tipo de valor

llevemos a cabo instrucciones condicionales. El ejemplo elegido es el cálculo de la ecuación

cuadrática donde una solución puede ser positiva y otra negativa, enteras o de punto flotante,

infinito negativo e infinito positivo, etc. Digamos que, tratamos con una cuestión práctica donde se

requiere exactitud en los cálculos.

Para este caso los recursos de código creados son codigo_cuadratica.c, cuadratica.asm y

construir_cuadratica.bat, y el comportamiento que obtenemos es el siguiente.

Página 62 de 66

Materia: Lenguaje Ensamblador Clave: F1265

CÓDIGO:

cuadratica.asm

%define a qword [ebp+8]

%define b qword [ebp+16]

%define c qword [ebp+24]

%define solucion1 dword [ebp+32]

%define solucion2 dword [ebp+36]

%define rad qword [ebp-8]

%define recip_2a qword [ebp-16]

segment .data

menoscuatro: dw -4

segment .bss

segment .text

global cuadratica

cuadratica:

push ebp

mov ebp,esp

sub esp,16 ; dos espacios de trabajo double

Página 63 de 66

Materia: Lenguaje Ensamblador Clave: F1265

push ebx

fild word [menoscuatro] ; st: -4

fld a ; st: a, -4

fld c ; st: c, a, -4

fmulp st1 ; st: a*c, -4

fmulp st1 ; st: -4*a*c

fld b ; st: b, -4*a*c

fld b ; st: b, b, -4*a*c

fmulp st1 ; st: b*b, -4*a*c

faddp st1 ; st: b*b - 4*a*c

ftst ; comparar st0 a 0

fstsw ax ; ax = palabra de estado

sahf ; banderas = ah

jb no_solucion_real

fsqrt ; st: sqrt(b*b - 4*a*c)

fstp rad ; st: vacio, y radical almacenado

fld1 ; st: 1

fld a ; st: a, 1

fscale ; st: 2*a, 1

fdivp st1 ; st: 1/(2*a)

fst recip_2a ; st: 1/(2*a)

fld b ; st: b, 1/(2*a)

fld rad ; st: rad , b, 1/(2*a)

fsubrp st1 ; st: rad - b, 1/(2*a)

fmulp st1 ; st: (-b + rad )/(2*a)

mov ebx,solucion1

fstp qword [ebx] ; resultado en solucion1

fld b ; st: b

fld rad ; st: rad , b

fchs ; st: -rad , b

fsubrp st1 ; st: -rad - b

fmul recip_2a ; st: (-rad - b)/(2*a)

Página 64 de 66

Materia: Lenguaje Ensamblador Clave: F1265

mov ebx,solucion2

fstp qword [ebx] ; resultado en solucion2

mov eax,1 ; retornar valor

jmp quit

no_solucion_real:

mov eax,0

quit:

pop ebx

mov esp,ebp

pop ebp

ret

codigo_cuadratica.c

#include <stdio.h>

int cuadratica(double,double,double,double *,double *);

int main()

{

double a;

double b;

double c;

double solucion1;

double solucion2;

int cond;

do {

printf("\na: ");

scanf("%lf",&a);

printf("b: ");

scanf("%lf",&b);

printf("c: ");

Página 65 de 66

Materia: Lenguaje Ensamblador Clave: F1265

scanf("%lf",&c);

cond = cuadratica(a,b,c,&solucion1,&solucion2);

if(cond == 0) {

printf("Sin solucion real.\n");

} else {

printf("%g and %g\n",solucion1,solucion2);

}

} while(1);

}

construir_cuadratica.bat

erase *.obj

erase *.exe

@set INCLUDE=C:\Program Files\Microsoft Visual Studio 12.0\VC\include

@set LIB=C:\Program Files\Microsoft Visual Studio 12.0\VC\lib;C:\Program Files\Microsoft SDKs\Windows\v7.1A\Lib

nasm -f win32 cuadratica.asm --prefix _

cl codigo_cuadratica.c cuadratica.obj

FUENTES ANEXAS:

Las siguientes fuentes de información hacen referencia a documentos (e-books) publicados que son

de utilidad para estudiar la programación en lenguaje ensamblador, unas son mejores que otras

pero todas se complementan.

1. Richard Blum. Professional Assembly Language. Wiley Publishing, Inc.

2. Peter Abel. Lenguaje ensamblador y programación para IBM PC y compatibles. Pearson

Education, Inc.

3. Randall Hyde. The Art Of Assembly Language. No Starch Press, Inc.

4. Jeff Duntemann. Assembly Language Step-by-Step: Programming with Linux. Wiley

Publishing, Inc.

Página 66 de 66

Materia: Lenguaje Ensamblador Clave: F1265

5. Kip R. Irvine. Lenguaje ensamblador para computadoras basadas en Intel. Pearson

Education, Inc.

6. Joseph Cavanagh. X86 Assembly Language and C Fundamentals. CRC Press by Taylor &

Francis Group