Examen de Ensamblador [Ayuda]

Iniciado por Alpha1020, 27 Octubre 2009, 06:24 AM

0 Miembros y 1 Visitante están viendo este tema.

Alpha1020

Bueno me han pedido que desarrolle un programa en Ensamblador que haga lo siguiente:

1.- Desarrolle una macro llamada lenstr que tenga como argumento la etiqueta a un arreglo de bytes, la macro deberá contar el número de caracteres que tiene el arreglo hasta encontrar un CTRL/D, la macro deb regresar el número de caracteres del registro DX.


2.- Crear dos arreglo myarreglo que contenga "este arreglo tiene 20 caracteresª" y el arreglo cuenta que contenga "ejemplo de arregloª", a donde ª es el carácter CTRL/D:
Dada la macro anterior contar los caracteres del arreglo myarreglo y cuenta y sumar la longitud de los dos arreglos en AX.

3.- Desarrollar el punto 1 como un procedimiento al cual se le pasa en el stack la dirección del arreglo y regresa BX la cuenta de caracteres.

4.- De acuerdo al punto 2 llamar la función lentsr y sumar la longitud del arreglo myarreglo y cuenta en el registro DX.


He desarrollado el siguiente código:
.ASM
.386
.model flat,stdcall
option casemap:none
.stack

include examen.inc
include \MASM32\macros\macros.asm

lenstr macro

LOCAL myarreglo


endm

.code
inicio:
invoke lstrcat,addr myarreglo ,addr cuenta
invoke lstrlen,addr myarreglo
invoke wsprintf,addr buffer,addr fmo,eax
mov edx , eax
invoke MessageBox,NULL,addr buffer,addr MsgTitulo,MB_OK + MB_ICONINFORMATION
invoke ExitProcess,0
mov ebx , edx

add edx , ebx

end inicio


.INC
include windows.inc
include user32.inc
include kernel32.inc

includelib user32.lib
includelib kernel32.lib

.data
myarreglo db "este arreglo tiene 20 caracteresª",0
cuenta db "ejemplo de arregloª",0

MsgTitulo db "Programa en Assembler",0

fmo db "la longitud de nuestra cadena es %d caracteres",0
.data?
buffer db 100 dup (?)


No he podido colocar el codigo dentro de la macro como es requerido...realiza la suma de las cadenas de caracteres pero necesito ayuda con la forma de introducir las instrucciones en la MACRO.

Y un poco de orientación en el enlace con un lenguaje de alto nivel de estas mismas funciones.

Eternal Idol

Hasta ahora se podria decir que no tenes nada, excepto el punto dos y la logica del cuatro, ojo que aca no se hacen tareas asi que unicamente te daremos orientacion. ¿Estas seguro de que lo tenes que hacer en 32 bits? Leyendo los registros mencionados apostaria que tenes que hacer un programa para MS-DOS (16 bits).

Obviamente NO podes usar lstrlen, tenes que escribir el codigo para que se recorra la cadena hasta encontar el caracter mencionado. Primero en una macro y despues como una funcion.
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón

Alpha1020

Agradezco la ayuda, la verdad ensamblador no es lo mio, se hace lo que se puede con lo que he leido por ahi xD. Hasta ahora usando el lstrlen, porqe ha sido la unica forma que masomenos entendi para sumar los caracteres por eso la utilize, conforme al punto 3 creo que se puede resolver utilizando un "PUSH" y la dirección del arreglo... lo de regresar el valor de BX con otro MOV...mi mas grande problema ahora viene siendo la forma de definir la macro y otra forma de contar caracteres distinta a la qe tengo ahora X_x y al maestro me dijo qe no le importa si es en 16,32,64 bits...si qe si pueden ayudarme unicamente con esa parte con algun ejemplo de otra forma de resolver esa bendita Macro se los agradecere mucho xd

Eternal Idol

La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón

Alpha1020

Ya logre resolver todos los puntos del examen, gracias por el apoyo. Ahora me gustaria consultar sobre un poco de orientacion con respecto a llamar las funciones de ensamblador en un lenguaje de alto nivel

Eternal Idol

Tenes que hacer coincidir la convencion de llamada (stdcall, cdecl, etc.) en tu codigo y en la declaracion en el lenguaje de alto nivel. Podes enlazar a nivel de codigo objeto (.obj) y usar librerias estaticas (.lib de codigo)  o dinamicas (.dll y .lib de importacion).


Lo siguiente es un articulo/tutorial/lo que sea que escribi hace ya un poco mas de 5 años:



Bueno supongo que todos saben que la mayoria de los compiladores de C++ permiten incluir instrucciones de ensamblador dentro del codigo fuente y estas son ensambladas directamente en el codigo objeto. A esto se le llama inline assembler generalmente.

Pero eso no es siquiera interesante; lo que si es muy interesante es la capacidad de escribir librerias (estaticas y dinamicas) tanto en ensamblador como en C++ (MASM y VC++) y linkearlas en ambos lenguajes.

Osea, que por ejemplo podemos crear una libreria en ensamblador y linkearla estaticamente en un programa de C++. Vamos a ver el ejemplo.

Codigo de la libreria de ensamblador:


Código (asm) [Seleccionar]
.386
.model stdcall,flat

include windows.inc
include kernel32.inc
include user32.inc

includelib kernel32.lib
includelib user32.lib

CTEXT MACRO text:VARARG
LOCAL TxtName
.data
TxtName BYTE text,0
.code
EXITM <OFFSET TxtName>
ENDM

SayLong PROTO number:DWORD

.code

SayLong PROC number:DWORD
LOCAL pointer:DWORD
invoke GetProcessHeap
invoke HeapAlloc,eax,HEAP_ZERO_MEMORY or HEAP_GENERATE_EXCEPTIONS,1024
mov pointer,eax
invoke wsprintf,pointer,CTEXT("%d"),number
invoke MessageBox,0,pointer,pointer,0
invoke GetProcessHeap
invoke HeapFree,eax,0,pointer
ret
SayLong ENDP

End




Tranquilidad que ahora paso a explicar el codigo anterior.

.386 es una directiva que le indica a MASM que nuestro codigo va optimizado para la arquitectura 386

.model stdcall,flat es una directiva que le indica a MASM que nuestro codigo usa stdcall (convencion de funciones que utiliza la API de Windows) y un modelo de memoria plano (el unico posible en Windows).

Los includes justamente incluyen bibliotecas al estilo de los .H de C++, para conseguir estas bibliotecas hay que tener MASM32 MASM32 instalado y con el path configurado.

Los includelib nos ahorran pasarle en la linea de comandos parametros de librerias que vamos a linkear, tambien hay que tener el MASM32 o sino crearlas (eso lo dejamos para otro tutorial).

El macro CTEXT nos permite utilizar texto al modo de C++ usando CTEXT("TEXTO") cosa que no es posible directamente en ensamblador.

La funcion SayLong simplemente muestra un MessageBox con el numero que hayamos especificado como parametro.

Ustedes diran que carajo hacemos con este codigo, bueno aca esta la respuesta, ensamblamos y linkeamos con MASM:

ml /c /Cp /coff asm_called.asm
lib asm_called.obj

Con eso conseguimos el archivo asm_called.obj que es el codigo objeto y el archivo asm_called.lib que es el codigo ejecutable que vamos a linkear desde C++.

Ahora el codigo de C++ que llama a la funcion de ensamblador:

Código (cpp) [Seleccionar]
#include <windows.h>
extern "C" void __stdcall SayLong(DWORD number);

void main()
{
 SayLong(50);
}




Muy simple este codigo, muy simple. Declara la funcion externa SayLong con el paso de paremetros de stdcall (la misma que usamos en ensamblador). Y la llama desde un main con un parametro de 50.

Compilamos y linkeamos con VC++:

cl -c calling_asm.cpp
link calling_asm.obj asm_called.lib kernel32.lib user32.lib

Ahora obtenemos un archivo objeto calling_asm.obj y un archivo ejecutable calling_asm.exe.

Ejecuten el archivo calling_asm.exe y veran que aparece un MessageBox con el numero 50, la rutina SayLong (programa en ensamblador) fue llamada desde C++.

Espero que les haya gustado el tutorial y hayan aprendido algo nuevo.
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón

Alpha1020

Al momento de construir el EXE en C++, ocurre un problema que no he podido resolver por mas que le muevo es este.

Error:  Error: Unresolved external 'lenstr' referenced from C:\DOCUMENTS AND SETTINGS...\PROGRAMA.OBJ



tomando en cuenta que lenstr es la funcion que yo quiero llamar, el *.Obj ya lo coloque en la carpeta del proyecto junto con las *.Lib, si que no comprendo el porque del problema.

Eternal Idol

¿Se lo estas pasando al enlazador? Como en este caso:
link calling_asm.obj asm_called.lib kernel32.lib user32.lib

Fijate en las opciones del proyecto, ahi podes ver la linea de comandos del enlazador y las opciones.
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón