Вы находитесь на странице: 1из 66

Lenguaje Ensamblador: Guia prctica ...............................................................................................

2
QU NECESITO? ...............................................................................................................................2
QU HAGO CON TODOS LOS RECURSOS QUE NECESITO? ..............................................................3
A PROGRAMAR! ...............................................................................................................................7
1. Hola mundo ...............................................................................................................................7
2. Plantilla bsica .........................................................................................................................10
3. Ensamblando y enlazando con C: ejemplo mcd ......................................................................12
4. Generando nmeros aleatorios...............................................................................................16
5. Encontrando nmeros primos .................................................................................................19
6. Manipulacin de bits: desplazando y alternando ...................................................................33
7. Operaciones booleanas: and, or, xor, not ...............................................................................48
8. Eleccin sin rbol: escoger nmero ms grande .....................................................................54
9. Arreglos: definiendo y manejando direcciones.......................................................................57
10. Punto flotante: ejemplo ecuacin cuadrtica .......................................................................61
FUENTES ANEXAS: ...........................................................................................................................65

Pgina 2 de 66
UNIVERSIDAD JUREZ AUTNOMA DE TABASCO
DIVISIN ACADMICA DE INFORMTICA Y SISTEMAS

Lenguaje Ensamblador: Guia prctica


Jess Antonio Ferrer Snchez
Para programar en lenguaje ensamblador escog la especificacin 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 Cul es la az ? La espuesta es ue el p opio o
e lo di e Net ide Asse le , es
decir, existe una comunidad que mantiene actualizada documentacin y herramientas para
programar en lenguaje ensamblador.
Bue o a os a la o a, pa a e peza e esita os visitar el sitio Web donde se encuentra los ms
importante que necesitaremos http://www.nasm.us/, hecho esto la siguiente cuestin es Qu
vamos a utilizar de all? Pues lo siguiente:

QU NECESITO?
1. La documentacin, que est aqu:
http://www.nasm.us/docs.php aunque realmente existe documentacin ms actualizada como en
su sitio de Sourceforge o Git, por ejemplo. Lo ms recomendable es utilizar la versin estable.
2. El compilador e intrprete, 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 terminacin rc, por ejemplo abriremos la carpeta
2.11.05 (fijate que no dice 2.11.05rc) estando dentro bajaremos el compilador e intrprete 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
distincin 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.05installer.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 terminacin .tar.gz (nasm2.11.05.tar.gz, por ejemplo) ya vern porque ms adelantito.
3. El enlazador para Windows OS (para Linux no es necesario):

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 3 de 66
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.nanoeditor.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 lnea de comandos.
Aho a la siguie te uesti es Qu hago o todo esto pa a e peza a ola p og a a do e
Lenguaje ensamblador? Pues lo siguiente:

QU HAGO CON TODOS LOS RECURSOS QUE NECESITO?


Aqu hago distincin 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 continuacin.

2. Una vez que est instalado recurrimos al acceso directo que haba 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
opcin Abrir la ubicacin del archivo vamos a ubicarnos donde se encuentran todos los recursos de
instalacin. Esta carpeta la mantendremos abierta nos ser til unos pasos ms adelante.

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 4 de 66
3. Se supone que todava 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 extrados en una carpeta dentro de la carpeta ..\AppData\Local\nasm deben estar en la
misma jerarqua.

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


Windows. Ustedes ya saben cmo, nos quedara ms 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--)

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 5 de 66

Despus de esto nos mandar fuera de ejecucin de alink. Lo que sigue aqu mismo es
verificar que se conserva la armona con el depurador nativo de Windows para lo que
escribiremos debug y despus 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 adems necesitarn 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 ubicacin 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.

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 6 de 66
En Linux:
1. Para instalar NASM en Linux hay dos vas una es por va repositorio escribiendo sudo apt-get
install nasm lo cual nos instalar una versin sumamente antigua y la otra es por medio de la
compilacin 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 instalacin a /usr/local/bin luego comprobamos que
efectivamente tenemos instalado nasm como se ilustra en la siguiente imagen.

Debo mencionar que las ubicaciones simblicas indican que en nuestro sistema instalo
correctamente a nasm.

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 7 de 66
1.3. Tenemos la opcin 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 ubicacin /usr/local/src/ pues
ya no los necesitamos.
Y listo ya tenemos todo listo para empezar con NASM desde Linux. Al parecer fue ms rollo para
Windows, disculpen...

A PROGRAMAR!
Para saber cmo trabajar con nasm consulte la documentacin 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-developermanuals.html

1. Hola mundo
La finalidad de este primer programa es seguir la tradicin y para explicar la manera de trabajar que
consiste en editar un archivo .asm y compilarlo con nasm. Veamos cmo 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 cdigo.

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 8 de 66
Para compilarlo escribimos nasm holawindows.asm -o holawindows.[com, exe] en muestro caso
exe con la instruccin de salida de nasm (-o). Despus damos Enter, revisamos que efectivamente
ha sido creado y lo mandamos a ejecutar escribiendo el nombre del archivo sin extensin para
comprobar. Lo mismo pasara si decidiramos generar un ejecutable .com slo que lo ejecutaramos
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 ejecucin (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 cdigo.

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 ejecucin y luego el archivo objeto
binario. Despus damos Enter, revisamos que efectivamente 2 archivos han sido creados y lo
mandamos a ejecutar escribiendo ./holalinux el nombre del archivo sin extensin para comprobar.

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 9 de 66

CDIGO:
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 instrccin de interrupcin

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

; direccin 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

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 10 de 66
length: equ 13

; longitud del string

Antes de empezar quiero hacer

2. Plantilla bsica
parntesis. (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 tamao del documento con las demostraciones para ambos
sistemas operativos.
Ok Este p og a a o siste e el es ueleto ue tie e si a e te u p og a a e e sa lado
haciendo uso de declaraciones, comentarios, funciones y constantes. Editamos nuestro archivo
esqueleto.asm y guardamos.

Este cdigo realmente no es funcional y nuestro resultado es que manda como salida mensajes de
error al momento de la compilacin debido a que algunas instrucciones estn incompletas, pues
solo han sido colocadas en su respectivo lugar pero no se estn manejando con su sintaxis correcta.
En este caso es enter en la lnea 12, push en la lnea 13 y pop en la lnea 17.

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 11 de 66
CDIGO:
esqueleto.asm
segment .data
;
; data inicializado
;
segment .bss
;
; data unitilizado
;
segment .text
global _func
_func:
enter n,0

; lnea 12

push

; guardar registros lnea 13

;
; cuerpo de la funcion
;
pop

; devolver registros lnea 17

mov eax,0

; retornar valor

leave
ret

Otra forma de tener nuestra plantilla sera como sigue:


esqueleto2.asm
segment .data
;
; data inicializado
;
segment .bss
;
; data unitilizado
;
segment .text

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 12 de 66
global _func
_func:
push ebp

; si necesitamos que esta instruccin se ejecute antes

mov

ebp,esp ; copiamos ebp en esp

sub

esp,n

push

; sustituimos por enter


; guardar registros

;
; cuerpo de la funcion
;
pop

; devolver registros

mov

eax,0

mov

esp,ebp

pop

ebp

ret

; retornar valor

; devolvemos el valor de la rutina

3. Ensamblando y enlazando con C: ejemplo mcd


En este programa veremos cmo podemos trabajar desde ensamblador con cdigo fuente del
lenguaje C. Para esto, el ejemplo consiste en encontrar el mximo comn divisor con el modo
sencillo, aqu editamos el archivo mcd.asm con nuestro respectivo cdigo. Lo guardamos.

Luego creamos nuestro cdigo en C, en este caso lo nombr codigoprincipal.c en el cual solo se
reciben y envan valores pues el algoritmo se ejecuta en cdigo ensamblador. Lo guardamos.

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 13 de 66

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 lnea 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 optimizacin x86). Luego anlogamente a la opcin -o de nasm
utilizamos -f para indicar que mande de salida ejecutable x86, luego utilizamos la opcin --prefix
ms _ para el argumento dado para todas las variables globales o externos, como en C. Lo cual va
de la mano con el compilador de optimizacin 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.

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 14 de 66

Por ultimo verificamos que nuestro ejecutable .exe si funcione.

CDIGO:
mcd.asm
segment data

segment bss

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 15 de 66

segment text
global mcd
mcd:
push ebp
mov

ebp,esp

mov

eax,[ebp+8]

; x

mov

ebx,[ebp+12]

; y

cmp

eax,0

; if (x == 0) hemos terminado

je

goback

cmp

eax,ebx

jge

modulo

looptop:

xchg eax,ebx

; hacer que cierto valor x sea un numero mas grande

; 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

mov

esp,ebp

pop

ebp

; retornar y

ret

codigoprincipal.c
#include <stdio.h>
int mcd(int a,int b);
int main() {
int result;
int a;
int b;

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 16 de 66
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 nmeros aleatorios


Este programa consiste en usar el algoritmo inorder para generar un nmero entero aleatorio entre
un rango especificado ya sea entre nmeros positivos y negativos.
Suponemos que con los ejemplos anteriores ya tenemos claro cul es nuestro patrn de produccin
a cdigo final, por lo que no entraremos en tanto detalle redundando en cosas que debemos hacer.
Ok edita os uest o digo e C ue lla a e os codigo_random.c, en ensamblador
enteros_random.asm y nuestro script de builder construir_random.bat y vemos nuestro resultado.

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 17 de 66
CDIGO:
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]
mov

; intercambiar primero y segundo

[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 ms grande

add

ebx,1

sub

ebx,[ebp+8]

; subtraccin del valor delta

sumar uno

cdq

; limpiar edx

idiv ebx

; dividir edxeax por ebx

add

edx,[ebp+8]

goback:
mov

eax,edx

mov

esp,ebp

pop

ebp

ret

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 18 de 66
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

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 19 de 66

5. Encontrando nmeros 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 nmeros primos entre una rango que debe ser
especificado al inicio de ejecucin.
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.

CDIGO:
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

superior:

resd

recorrer:

resd

factor: resd

segment .text

extern out_integer
extern in_integer
extern out_string

global encontrar_primos
encontrar_primos:

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 20 de 66
enter

0,0

pushad
pushfd

; pedir lmites 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]

imul

eax,eax

cmp

[recorrer],eax

jl

encontrar

mov

eax,[recorrer]

mov

ebx,[factor]

; prueba para el factor mas grande

; prueba para el acarreo de divisin

cdq
idiv

ebx

cmp

edx,0

je

siguiente

add

dword [factor],1

jmp

factortest

; empujar factor y ciclar

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 21 de 66
; 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();
}

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 22 de 66
entrada.asm
segment .data

segment .bss
char_hold:

resd 1

str_hold:

resb 20

str_len:

equ

value:

resd 1

$-str_hold-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

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 23 de 66
.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

mov

byte [ebx],0

mov

ecx,str_len

; direccin para almacenar cadena

; longitud mxima de la cadena

.in_string_loop:
call

getchar

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 24 de 66
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

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 25 de 66
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

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 26 de 66
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
db

ebx: 0x%.8X

ecx: 0x%.8X

edx: 0x%.8X",10

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 27 de 66
dec_reg_fmt:

db "eax: %d
db

ebx: %d

ecx: %d

edx: %d",10

; 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

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 28 de 66
out_flags:
enter

0,0

pushad
pushfd

push

dword flag_string

call

out_string

pop

eax

mov

eax,[esp]

mov

[flags],eax

; obtener una copia de las banderas

; 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:

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 29 de 66
; 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 direccin
mov

eax,[flags]

test

eax,DF_BIT

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 30 de 66
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 lnea
push

dword newline_string

call

out_string

pop

eax

popfd
popad
leave
ret

; ---------------------------global out_hex_registers
out_hex_registers:
enter 0,0

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 31 de 66
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

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 32 de 66
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

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 33 de 66
@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

Adems, 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. Manipulacin de bits: desplazando y alternando


Este programa es una coleccin de mtodos 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 coleccin de mtodos, 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 mtodo por separado. Reutilizamos el archivo con el
cdigo de salida.asm para no tener problemas con los caracteres de salida y mostrar.asm de donde
invocamos la funcin 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 cdigo creados
para la manipulacin 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 mtodo.

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 34 de 66

CDIGO:
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

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 35 de 66
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:

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 36 de 66
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

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 37 de 66

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

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 38 de 66
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>

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 39 de 66

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()
{

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 40 de 66
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

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 41 de 66
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
db

dec_reg_fmt:

ecx: 0x%.8X

edx: 0x%.8X",10

db "eax: %d
db

ebx: 0x%.8X

ebx: %d

ecx: %d

edx: %d",10

; 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

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 42 de 66
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]

mov

[flags],eax

; obtener una copia de las banderas

; 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

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 43 de 66
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 direccin
mov

eax,[flags]

test

eax,DF_BIT

jz

df_not

push

df_string

call

out_string

pop

eax

df_not:

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 44 de 66
; 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 lnea
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

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 45 de 66
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

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 46 de 66

popfd
popad
leave
ret

mostrar.asm

segment .data
string_ax:

string_cf:

db

"

"

db

"

db

0,10,0

CF="

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

mov

byte [string_ax+ebx],'1'

uno:

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 47 de 66
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


nasm -f win32 salida.asm
nasm -f win32 mover.asm

--prefix _
--prefix _

--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 aplicaramos la misma lgica, y la sintaxis del ejemplo anterior.

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 48 de 66

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


En este programa se implementan las operaciones booleanas and, or, xor y not, codificando
funciones especficas para cada tipo de operacin, accediendo a las banderas de paridad, zero y
signo. Teniendo esta idea necesitamos cdigo de prueba para mostrar los bits originales sobre los
cuales se harn las operaciones. Entonces hacemos lo siguiente.
Como en el ejemplo anterior, creamos en este caso nuestra coleccin de las funciones que realizan
cada tipo de operacin booleana y anexamente nuestro cdigo de prueba que genera los bits
originales que se utilizan como prueba con las banderas. Nuestros recursos son modos_boolean.asm
que es nuestra coleccin de funciones, los archivos de cdigo C que son: and.c, or.c, xor.c, not.c y
test.c que implementan cada funcin, reutilizamos mostrar.asm, salida.asm y nuestro constructor
para nuestros recursos de cdigo como en el ejemplo anterior. Ahora vemos nuestro resultado.

Prueba original
con las banderas.

Implementando
las funciones.

CDIGO:
modos_boolean.asm
segment .data
segment .bss
segment .text

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 49 de 66
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

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 50 de 66
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

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 51 de 66
; 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();
}

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 52 de 66
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();
}

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 53 de 66
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


nasm -f win32 salida.asm

--prefix _
--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

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 54 de 66
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. Eleccin sin rbol: escoger nmero ms grande


En este programa hacemos uso del algoritmo de bsqueda de una pasada para encontrar el nmero
ms grandes entre dos valores ingresados al inicio de ejecucin (sin importar orden y tamao de
nmero). En este ejemplo podemos revisar cmo 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 funcin, 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 cdigo. Nuestro resultado es el siguiente.

CDIGO:
escoger.asm
segment .data

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 55 de 66
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

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

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 56 de 66
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
Materia: Lenguaje Ensamblador Clave: F1265

Pgina 57 de 66
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


nasm -f win32 salida.asm

--prefix _
--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 ms de cdigo 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
mtodo bubble sort, aunque en la salida no se pueda apreciar en primera instancia.
Versin 1: Aqu los recursos de cdigo son codigo_por_cuatro.c, por_cuatro.asm y
construir_arreglos.bat con lo cual obtendremos el siguiente resultado.

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 58 de 66
Versin 2:
Aqu los recursos de cdigo son codigo_ordenar.c, ordenar.asm y construir_arreglos.bat con lo cual
obtendremos el siguiente resultado. Aqu los valores de cada posicin han sido ordenados por el
mtodo bubble sort (ordenamiento burbuja).

CDIGO:
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]);
}

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 59 de 66
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]

; tamao del arreglo

mov

eax,[ebx]

shl

eax,2

mov

[ebx],eax

add

ebx,4

loop

top

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()
{

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 60 de 66
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]

; tamao del arreglo

sub

ecx,1

mov

eax,[ebx]

cmp

eax,[ebx+4]

top:

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 61 de 66
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


nasm -f win32 ordenar.asm

--prefix _

--prefix _

cl codigo_por_cuatro.c por_cuatro.obj
cl codigo_ordenar.c ordenar.obj

10. Punto flotante: ejemplo ecuacin cuadrtica


En este programa tratamos con nmeros de punto flotante para que de acuerdo a este tipo de valor
llevemos a cabo instrucciones condicionales. El ejemplo elegido es el clculo de la ecuacin
cuadrtica donde una solucin puede ser positiva y otra negativa, enteras o de punto flotante,
infinito negativo e infinito positivo, etc. Digamos que, tratamos con una cuestin prctica donde se
requiere exactitud en los clculos.
Para este caso los recursos de cdigo creados son codigo_cuadratica.c, cuadratica.asm y
construir_cuadratica.bat, y el comportamiento que obtenemos es el siguiente.

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 62 de 66

CDIGO:
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

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 63 de 66
push

ebx

fild

word [menoscuatro]

fld

; st: a, -4

fld

; st: c, a, -4

fmulp

st1

; st: a*c, -4

fmulp

st1

; st: -4*a*c

fld

; st: b, -4*a*c

fld

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

fmulp

st1

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

faddp

st1

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

ftst
fstsw

; comparar st0 a 0
ax

sahf
jb

no_solucion_real

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


rad

fld1
fld

; ax = palabra de estado
; banderas = ah

fsqrt
fstp

; st: -4

; st: vacio, y radical almacenado


; st: 1

fscale

; st: a, 1
; st: 2*a, 1

fdivp

st1

; st: 1/(2*a)

fst

recip_2a

; st: 1/(2*a)

fld

; 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

; st: b

fld

rad

; st: rad , b

fchs

; st: -rad , b

fsubrp st1

; st: -rad

fmul

; st: (-rad

recip_2a

- b
- b)/(2*a)

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 64 de 66
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: ");

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 65 de 66
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 informacin hacen referencia a documentos (e-books) publicados que son
de utilidad para estudiar la programacin 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 programacin 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.

Materia: Lenguaje Ensamblador Clave: F1265

Pgina 66 de 66
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

Materia: Lenguaje Ensamblador Clave: F1265

Вам также может понравиться