lunes, 17 de diciembre de 2018

NASM

NASM(The Netwide Assembler)

Es un  ensamblador libre  x80x86 y x86-64 diseñado para tener potabilidad, modularidad, es potable para cualquier sistema operativo y de fácil uso, debido a que esta diseñado para ser simple de usar.

Ejemplo de código ensamblador para obtener los números primos de un rango especifico

%include "asm_io.inc"
segment .data
Message db "Halle primos hasta: ", 0

segment .bss
Limit resd 1 ; halle primos hasta este l´ımite
Guess resd 1 ; la conjetura actual para el primo

segment .text
 global _asm_main
 _asm_main:
 enter 0,0 ; rutina de inicio
 pusha

 mov eax, Message
 call print_string
 call read_int ; scanf("%u", & limit );
 mov [Limit], eax

 mov eax, 2 ; printf("2\n");
 call print_int
 call print_nl
 mov eax, 3 ; printf("3\n");
 call print_int
 call print_nl

 mov dword [Guess], 5 ; Guess = 5;
 while_limit: ; while ( Guess <= Limit )
 mov eax,[Guess]
 cmp eax, [Limit]
 jnbe end_while_limit ; use jnbe ya que los n´umeros son sin signo

 mov ebx, 3 ; ebx is factor = 3;
 while_factor:
 mov eax,ebx
 mul eax ; edx:eax = eax*eax
 jo end_while_factor ; Si la respuesta no cabe en eax
 cmp eax, [Guess]
 jnb end_while_factor ; if !(factor*factor < guess)
 mov eax,[Guess]
 mov edx,0
 div ebx ; edx = edx:eax % ebx
 cmp edx, 0
 je end_while_factor ; if !(guess % factor != 0)

 add ebx,2 ; factor += 2;
 jmp while_factor
 end_while_factor:
 je end_if ; if !(guess % factor != 0)
 mov eax,[Guess] ; printf("%u\n")

 call print_int
 call print_nl
 end_if:
 add dword [Guess], 2 ; guess += 2
 jmp while_limit
 end_while_limit:

 popa
 mov eax, 0 ; retorna a C
 leave
 ret

Para compilar en windows haga uso de los siguientes comandos:
nasm -f prime.asm  
gcc -o prime prime.obj driver.c asm_io.obj 
prime.exe

El primer comando generara el archivo objeto en formato .obj para windows en caso de ser linux use -coff
El segundo comando enlaza los objetos para generar un ejecutable, note que antes de ejecutar el comando debe ya contar con el archivo drivers.c y asm_io.obj, los cuales se obtienen de los links mencionados en las referencias.


referencias:
https://es.wikipedia.org/wiki/Netwide_Assembler
Libro Lenguaje Ensamblador para PC
Paul A. Carter
18 de octubre de 2006
Recursos en Internet mencionados en el libro
Pagina del autor http://www.drpaulcarter.com/
Pagina de NASM en SourceForge http://sourceforge.net/projects/nasm/
DJGPP http://www.delorie.com/djgpp
Ensamblador con Linux http://www.linuxassembly.org/
The Art of Assembly http://webster.cs.ucr.edu/
USENET comp.lang.asm.x86
Documentación de Intel http://developer.intel.com/design/Pentium4/documentation.htm

Gas(GNU) Assembler


El gas, o GNU Assembler, es el ensamblador del proyecto GNU. Es el back end por defecto del GNU Compiler Collection y es usado para compilar Linux y otros sistemas operativos como el sistema operativo GNU
El gas puede ejecutar como también generar ensamblados para un número diferente de arquitecturas. Inicialmente utilizaba únicamente la sintaxis de AT&T en lugar de la sintaxis de Intel usada en muchos otros ensambladores, sin embargo, las últimas versiones soportan dicha sintaxis.

Ejemplo calculadora de dos números(suma, resta, multiplicación y división).

.def ___main; .scl 2; .type 32; .endef
.section .rdata,"dr"
LC2:
.ascii "Ingrese numero uno\0"
LC3:
.ascii "%f\0"
LC4:
.ascii "Ingrese numero dos \0"
LC5:
.ascii "cls\0"
.align 4
LC6:
.ascii "1.- Para sumar los dos numeros \0"
.align 4
LC7:
.ascii "2.- Para restar los dos numeros \0"
.align 4
LC8:
.ascii "3.- Para multiplicar los dos numeros \0"
.align 4
LC9:
.ascii "4.- Para dividir los dos numeros \0"
LC10:
.ascii "5.- salir\0"
LC11:
.ascii "%d\0"
LC12:
.ascii "La suma es: %f\0"
LC13:
.ascii "La resta es: %f\0"
LC14:
.ascii "La multiplicacion  es: %f\0"
LC15:
.ascii "La division es: %f\0"
LC16:
.ascii "Opcion no valida \0"
.text
.globl _main
.def _main; .scl 2; .type 32; .endef
_main:
pushl %ebp
movl %esp, %ebp
andl $-16, %esp
subl $48, %esp
call ___main
movl $0x00000000, %eax
movl %eax, 36(%esp)
movl $0x00000000, %eax
movl %eax, 32(%esp)
movl $0, 28(%esp)
movl $0, %eax
movl $0, %edx
movl %eax, 40(%esp)
movl %edx, 44(%esp)
movl $LC2, (%esp)
call _puts
leal 36(%esp), %eax
movl %eax, 4(%esp)
movl $LC3, (%esp)
call _scanf
movl $LC4, (%esp)
call _puts
leal 32(%esp), %eax
movl %eax, 4(%esp)
movl $LC3, (%esp)
call _scanf
L10:
movl $LC5, (%esp)
call _system
movl $LC6, (%esp)
call _puts
movl $LC7, (%esp)
call _puts
movl $LC8, (%esp)
call _puts
movl $LC9, (%esp)
call _puts
movl $LC10, (%esp)
call _puts
leal 28(%esp), %eax
movl %eax, 4(%esp)
movl $LC11, (%esp)
call _scanf
movl 28(%esp), %eax
cmpl $5, %eax
ja L2
movl L8(,%eax,4), %eax
jmp *%eax
.section .rdata,"dr"
.align 4
L8:
.long L2
.long L3
.long L4
.long L5
.long L6
.long L7
.text
L3:
movl 32(%esp), %edx
movl 36(%esp), %eax
movl %edx, 4(%esp)
movl %eax, (%esp)
call _suma
fstpl 40(%esp)
movl 40(%esp), %eax
movl 44(%esp), %edx
movl %eax, 4(%esp)
movl %edx, 8(%esp)
movl $LC12, (%esp)
call _printf
call _getch
jmp L9
L4:
movl 32(%esp), %edx
movl 36(%esp), %eax
movl %edx, 4(%esp)
movl %eax, (%esp)
call _resta
fstpl 40(%esp)
movl 40(%esp), %eax
movl 44(%esp), %edx
movl %eax, 4(%esp)
movl %edx, 8(%esp)
movl $LC13, (%esp)
call _printf
call _getch
jmp L9
L5:
movl 32(%esp), %edx
movl 36(%esp), %eax
movl %edx, 4(%esp)
movl %eax, (%esp)
call _multiplicacion
fstpl 40(%esp)
movl 40(%esp), %eax
movl 44(%esp), %edx
movl %eax, 4(%esp)
movl %edx, 8(%esp)
movl $LC14, (%esp)
call _printf
call _getch
jmp L9
L6:
movl 32(%esp), %edx
movl 36(%esp), %eax
movl %edx, 4(%esp)
movl %eax, (%esp)
call _division
fstpl 40(%esp)
movl 40(%esp), %eax
movl 44(%esp), %edx
movl %eax, 4(%esp)
movl %edx, 8(%esp)
movl $LC15, (%esp)
call _printf
call _getch
jmp L9
L7:
movl $1, (%esp)
call _exit
L2:
movl $LC16, (%esp)
call _puts
L9:
movl 28(%esp), %eax
cmpl $5, %eax
jne L10
movl $0, %eax
leave
ret
.globl _suma
.def _suma; .scl 2; .type 32; .endef
_suma:
pushl %ebp
movl %esp, %ebp
flds 8(%ebp)
fadds 12(%ebp)
popl %ebp
ret
.globl _resta
.def _resta; .scl 2; .type 32; .endef
_resta:
pushl %ebp
movl %esp, %ebp
flds 8(%ebp)
fsubs 12(%ebp)
popl %ebp
ret
.globl _multiplicacion
.def _multiplicacion; .scl 2; .type 32; .endef
_multiplicacion:
pushl %ebp
movl %esp, %ebp
flds 8(%ebp)
fmuls 12(%ebp)
popl %ebp
ret
.globl _division
.def _division; .scl 2; .type 32; .endef
_division:
pushl %ebp
movl %esp, %ebp
flds 8(%ebp)
fdivs 12(%ebp)
popl %ebp
ret
.def _puts; .scl 2; .type 32; .endef
.def _scanf; .scl 2; .type 32; .endef
.def _system; .scl 2; .type 32; .endef
.def _printf; .scl 2; .type 32; .endef
.def _getch; .scl 2; .type 32; .endef
.def _exit; .scl 2; .type 32; .endef




A continuación para compilarlo usar:
gcc -o calculadora -m32 calcauladora.s

Generara un ejecutable windows .exe y a continuación ingresar dos números y proceder con las operaciones.



Referencias:
https://es.wikipedia.org/wiki/GNU_Assembler
GAS Manual