Cadenas en FASM

Iniciado por Yuki, 1 Mayo 2016, 18:37 PM

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

Yuki

Hola, estoy desarrollando un compilador en Basic 6.0 y hasta ahora he logrado superar muchos obstaculos (procesamiento y traducción de ecuaciones matematicas + funciones a ensamblador, adición de APIS y otras cosas) pero tengo un problema con las cadenas.

Para que se hagan una idea con lo que estoy tratando les doy el siguiente código de ejemplo de mi compilador.

API MessageBox(Opcional hWnd:Entero,Texto:Cadena = "Hola soy una cadenita",Título:Cadena = "Soy un sexual título",Opcional Bandera:Entero = 48):Entero, "User32.dll" "MessageBoxA"

Var Cadenita:Cadena
Var OtroParametro:Entero
Var Título:Cadena
Var Cuarto:Entero

Cadenita = "Soy una vulgar cadena"
Título = "mnmnqmnqmnqm"
Cuarto = 48

MessageBox(0,Cadenita,Título,Cuarto)


El problema esta al tratar de rellenar la variable "Cadenita" con "Soy una vulgar cadena".
Ya que al visualizar el MessageBox amarece "Soy un0" como texto.

El código ensamblador generado es el siguiente.

; Código generado en Fractor!
include 'C:\Users\DarkBlue\Desktop\Fractor\Macros.inc'
format PE GUI 4.0
.datos
TmpStr0 db "Hola soy una cadenita",0
TmpStr1 db "Soy un sexual título",0
cadenita db ?
otroparametro dd ?
título db ?
cuarto dd ?
TmpStr2 db "Soy una vulgar cadena",0
TmpStr3 db "mnmnqmnqmnqm",0
.código
inicio:
push eax ; Preservamos EAX.
push TmpStr2
push cadenita
ccall [strcat]
add esp,8
pop eax ; Restauramos EAX
push eax ; Preservamos EAX.
push TmpStr3
push título
ccall [strcat] ; POSIBLE ERROR.
add esp,8
pop eax ; Restauramos EAX
push eax ; Preservamos EAX.
push TmpStr2 ; Empujamos el valor de TmpStr2.
push TmpStr3 ; Empujamos el valor de TmpStr3.
mov eax,48 ; Fin del calculo.
mov [cuarto],eax ; Movemos a la variable el valor de EAX.
pop eax ; Restauramos EAX.
push eax ; Preservamos EAX.
push [cuarto] ; Empujamos el valor de cuarto.
push título ; Empujamos el valor de título.
push cadenita ; Empujamos el valor de cadenita.
push 0
call [MessageBox]
pop eax ; Restauramos EAX.
push 0
call [ExitProcess]
entry inicio
; Procedimientos declarados.
; Fin de los procedimientos declarados.

.importar
; APIS declaradas.
library \
Kernel32,'Kernel32.dll',\
msvcrt,'msvcrt.dll',\
User32,'User32.dll'
import \
Kernel32,ExitProcess,'ExitProcess'
import \
msvcrt,strcat,'strcat'
import \
User32,MessageBox,'MessageBoxA'
; Fin APIS.


Como se puede notar, para asignarle a Cadenita el texto "Soy una vulgar cadena" utilizo strcat ya que yo asumí que strcat copia el segundo parametro en el primero, ¿que estoy haciendo mal?

fary

Tienes que crear un buffer con malloc, LocalAlloc o similar y ahí concatenar las cadenas.

Saludos.
Un byte a la izquierda.

Yuki

#2
¿Me podrias dar un pequeño ejemplo? no puedo visualizar el código sin usar registros.

.datos
cadenita dd ?
TmpStr1 db "Soy una cadenita de longitud 50 o que se yo."
TmpLng = $ - TmpStr1
.código
inicio:
      ccall [malloc],TmpLng
      add esp,4 ; Liberamos el stack.
      mov [cadenita],eax
      push TmpStr1
      push [cadenita]
      ccall [strcat]
      add esp,8 ; Liberamos el stack.
      ; [cadenita] = Puntero A "Soy una cadenita de longitud 50 o que se yo."????????

entry inicio






Disculpen por el doble comentario, solucione mi problema con un procedimiento propio que hice, lo pongo acá por si alguien tiene el mismo problema que yo y requiere una solución, ademas no me gusta dejar mis posts sin el "resuelto".

Utilizo el siguiente procedimiento en mi compilador para concatenar cadenas.
Acepta 2 parametros (punteros a cadenas) y retorna un puntero a la cadena concatenada en EAX.

proc concatenar uses ecx,Fuente2,Fuente1 ; Retorna en EAX
mov EDI, [Fuente2]
push EDI
call [strlen]
Add ESP, 4
mov ESI, EAX
mov EDI, [Fuente1]
push EDI
call [strlen]
add ESP, 4
add ESI,EAX ; ecx = len(Fuente2) + len(Fuente1)
push ESI
call [malloc]
add ESP, 4
push EDI
push EAX
call [strcpy]
add ESP, 8
mov EDI, [Fuente2]
push EDI
push EAX
call [strcat]
add ESP, 8
ret
endp


Me hubiera gustado que fuera mas chica, pero como esta escrita en ensamblador supongo que de todas maneras debe ser muy rapida.

fary

#3
Hola Yuki,

Es combeniente que  el buffer sea de tamaño len(Fuente2) + len(Fuente1) + 1 para el byte nulo de final de cadena.

Usa mejor invoke para llamar a las API, queda un código mas corto y mas limpio y viene a ser lo mismo... para las funciones de las librerias de C usa cinvoke, que te arregla la pila.

Código (asm) [Seleccionar]
proc concatenar uses ecx,Fuente2,Fuente1 ; Retorna en EAX
   cinvoke strlen, [Fuente2]
   mov ESI, EAX
   cinvoke strlen, [Fuente1

   add ESI,EAX ; ecx = len(Fuente2) + len(Fuente1)
   cinvoke malloc, esi
   cinvoke strcpy, eax, edi
   cinvoke strcat, eax, [Fuente2]

   ret
endp


Ademas el buffer que crees con malloc limpialo con ZeroMemory o similares para que no contenga caracteres extraños, llegado el momento puedes tener lios con eso.

saludos y suerte con tu proyecto.

Un byte a la izquierda.