Академический Документы
Профессиональный Документы
Культура Документы
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
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):
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:
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.
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.
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--)
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.
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.
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.
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.
Pgina 9 de 66
CDIGO:
holawindows.asm
org 100h
mov dx,string
mov ah,9
; 9 es copiado en el registro ah
int 21h
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
mov ebx,1
mov ecx,string
; direccin de string
mov edx,length
; string length
int 80h
; llamada al sistema
mov eax,1
mov ebx,0
int 80h
; llamada al sistema
section .data
string:
Pgina 10 de 66
length: equ 13
2. Plantilla bsica
parntesis. (Supongo que
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.
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
;
; cuerpo de la funcion
;
pop
mov eax,0
; retornar valor
leave
ret
Pgina 12 de 66
global _func
_func:
push ebp
mov
sub
esp,n
push
;
; cuerpo de la funcion
;
pop
; devolver registros
mov
eax,0
mov
esp,ebp
pop
ebp
ret
; retornar valor
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.
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.
Pgina 14 de 66
CDIGO:
mcd.asm
segment data
segment bss
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
; intercambiar x & y
modulo:
cdq
idiv ebx
mov
eax,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;
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
--prefix _
cl codigoprincipal.c mcd.obj
Pgina 17 de 66
CDIGO:
enteros_random.asm
segment .data
segment .bss
segment .text
global enterorandom
enterorandom:
push ebp
mov
ebp,esp
mov
eax,[ebp+8]
; primer argumento
cmp
eax,[ebp+12]
jl
inorder
xchg eax,[ebp+12]
mov
[ebp+8],eax
inorder:
rdtsc
shr
eax,2
mov
ebx,[ebp+12]
; el valor ms grande
add
ebx,1
sub
ebx,[ebp+8]
sumar uno
cdq
; limpiar edx
idiv ebx
add
edx,[ebp+8]
goback:
mov
eax,edx
mov
esp,ebp
pop
ebp
ret
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
--prefix _
cl codigo_random.c enteros_random.obj
Pgina 19 de 66
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:
Pgina 20 de 66
enter
0,0
pushad
pushfd
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
eax,[factor]
imul
eax,eax
cmp
[recorrer],eax
jl
encontrar
mov
eax,[recorrer]
mov
ebx,[factor]
cdq
idiv
ebx
cmp
edx,0
je
siguiente
add
dword [factor],1
jmp
factortest
Pgina 21 de 66
; encontrar un primo
encontrar:
push
dword [recorrer]
call
out_integer
pop
eax
push
dword newline
call
out_string
pop
eax
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();
}
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
call
getchar
cmp
eax,10
jz
.in_char_finish
mov
[char_hold],al
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
.in_string_loop:
call
getchar
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
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
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
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
Pgina 27 de 66
dec_reg_fmt:
db "eax: %d
db
ebx: %d
ecx: %d
edx: %d",10
resd 1
push
dword [ebp+8]
push
dword string_fmt
call
printf
pop
ecx
pop
ecx
popfd
popad
leave
ret
global out_flags
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
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:
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
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
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
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
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
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
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:
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
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
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>
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()
{
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
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
resd 1
push
dword [ebp+8]
push
dword string_fmt
call
printf
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
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
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:
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
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
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:
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
--prefix _
--prefix _
--prefix _
Para construirlo en Linux aplicaramos la misma lgica, y la sintaxis del ejemplo anterior.
Pgina 48 de 66
Prueba original
con las banderas.
Implementando
las funciones.
CDIGO:
modos_boolean.asm
segment .data
segment .bss
segment .text
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
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
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();
}
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();
}
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
--prefix _
--prefix _
--prefix _
construir_modos_boolean_linux
rm -f *.o
rm -f and
rm -f or
rm -f xor
rm -f not
Pgina 54 de 66
rm -f test
CDIGO:
escoger.asm
segment .data
Pgina 55 de 66
ask1:
db
ask2:
db
tell
db
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]
setg
bl
not
ebx
Pgina 56 de 66
inc
ebx
mov
ecx,ebx
; copiar en ecx
and
ecx,eax
not
ebx
and
ebx,[valor1]
or
ecx,ebx
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
--prefix _
--prefix _
--prefix _
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>
int main()
{
int i;
int tamanio=10;
int array[10];
por_cuatro(tamanio,array);
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]
mov
ecx,[ebp+8]
mov
eax,[ebx]
shl
eax,2
mov
[ebx],eax
add
ebx,4
loop
top
top:
leave
ret
codigo_ordenar.c
#include <stdio.h>
int main()
{
Pgina 60 de 66
int i;
int tamanio = sizeof(array) / sizeof(int);
a_ordenar(tamanio,array);
ordenar.asm
segment .data
segment .bss
segment .text
global a_ordenar
a_ordenar:
push
ebp
mov
ebp,esp
reiniciar:
mov
ebx,[ebp+12]
mov
ecx,[ebp+8]
sub
ecx,1
mov
eax,[ebx]
cmp
eax,[ebx+4]
top:
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
--prefix _
--prefix _
cl codigo_por_cuatro.c por_cuatro.obj
cl codigo_ordenar.c ordenar.obj
Pgina 62 de 66
CDIGO:
cuadratica.asm
%define a
qword [ebp+8]
%define b
qword [ebp+16]
%define c
qword [ebp+24]
%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
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
faddp
st1
ftst
fstsw
; comparar st0 a 0
ax
sahf
jb
no_solucion_real
fld1
fld
; ax = palabra de estado
; banderas = ah
fsqrt
fstp
; st: -4
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
fsubrp st1
; st: rad
- b, 1/(2*a)
fmulp
st1
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)
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 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: ");
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
--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.
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