Can someone please enlighten my on a few things. This is code for a function generated from the vc++6 c/c++ compiler. I can't figure out why it crashes at: cmp BYTE PTR , 0 . Wasn't the address of _address$ moved to edi?? Also, what does mean when put after _address$ and why is it there? What are the esp and ebp registers for? And just one more question (sorry). Before the function is called in the main proc generated by the compiler I see that the addresses of the parameters are pushed onto the stack. Why is this done and how are the addresses of the strings retrieved in the function 'cos it doesn't look like it pops them off the stack. I've attached the original untouched generated file just incase. Thanx in advance!



searchstring proc _words$:dword, _address$:dword, _buffer$:dword, _until$:dword, _offfrom$:dword, _copyln$:dword
push ebx
push ebp

mov ebp, DWORD PTR _words$
push esi
xor eax, eax
xor esi, esi
push edi
mov edi, DWORD PTR _address$
test ebp, ebp
je SHORT $nullpointer$42215

cmp BYTE PTR , 0 ;<---- crashes here!!
je SHORT $L42219

mov cl, BYTE PTR
mov BYTE PTR 8+, cl
$L42218:
mov dl, BYTE PTR 8+
mov cl, BYTE PTR
xor ebx, ebx
cmp cl, dl
jne SHORT $L42226

mov cl, BYTE PTR
mov esi, eax
lea edx, DWORD PTR
lea eax, DWORD PTR
test cl, cl
mov DWORD PTR 12+, edx
je SHORT $L42223

add edx, edi
$L42222:

cmp BYTE PTR , cl
jne SHORT $L42257
mov cl, BYTE PTR

inc edx

inc eax
test cl, cl
jne SHORT $L42222

jmp SHORT $L42223
$L42257:

mov ebx, 1
$L42223:

mov ecx, DWORD PTR _copyln$
mov eax, esi
test ecx, ecx
je SHORT $L42258

test ebx, ebx
je SHORT $nullpointer$42215
$L42226:

mov cl, BYTE PTR

inc eax
test cl, cl
jne SHORT $L42218
$L42219:
pop edi
pop esi
pop ebp

or eax, -1
pop ebx

ret 0
$L42258:

mov eax, esi
pop edi
pop esi
pop ebp
pop ebx

ret 0
$nullpointer$42215:

mov ecx, DWORD PTR _copyln$
mov ebx, DWORD PTR _buffer$
xor edx, edx
test ecx, ecx
jle SHORT $L42259
mov ecx, DWORD PTR _offfrom$
add edi, esi
mov esi, DWORD PTR _until$
add edi, ecx
$L42230:

mov cl, BYTE PTR
cmp cl, BYTE PTR
je SHORT $L42259
cmp cl, BYTE PTR
je SHORT $L42259
cmp cl, BYTE PTR
je SHORT $L42259
cmp cl, BYTE PTR
je SHORT $L42259
cmp cl, BYTE PTR
je SHORT $L42259

mov BYTE PTR , cl
mov ecx, DWORD PTR _copyln$

inc edx
inc edi
cmp edx, ecx
jl SHORT $L42230
$L42259:
pop edi
pop esi

mov BYTE PTR , 0
pop ebp
pop ebx

ret 0
searchstring ENDP:o
Posted on 2001-09-15 16:12:11 by nin
Nin,

Try the following prototype and if this does not work, change the "C" to STDCALL".

searchstring PROTO C :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD

I gather you are trying to assembler this code as a module as it is a search function. To do that you need to specify the processor, memory model and make it case sensitive for 32 bit code.

.486 ; create 32 bit code
.model flat, stdcall ; 32 bit memory model
option casemap :none ; case sensitive

Then,

.CODE

The module,

Then
END

See if this helps you at all.

Regards,

hutch@pbq.com.au

PS I should have added, use the command line,

drv:\path\ML /c /coff yourmodule.asm
Posted on 2001-09-16 01:23:34 by hutch--
I did everything you said including trying the "C" and "STDCALL" but when i try the "C" in the proto I get: error LNK2001: unresolved external symbol _searchstring and it still crashes when i use "STDCALL".
Posted on 2001-09-16 13:28:26 by nin
The above code doesn't setup a stack frame using EBP - instead all the passed parameters are accessed through ESP. If your trying to assemble this with MASM, I think MASM is still trying to setup a stack frame with EBP. I'm not certain as I haven't tried assembling code out of VC++, but I think this code requires quite a bit of editing. If you don't understand what EBP/ESP are used for then you have a lot of reading in front of you. :)

Does the C code crash? Can you post the C code?
Posted on 2001-09-16 14:22:03 by bitRAKE
Thanx for your help so far. The C code is as follows and works fine:


int searchstring(char *words, char *address, char *buffer, char *until, int offfrom, int copyln)
{
int x = 0, s = 0, a = 0, ok = 0;
if(!words) goto nullpointer;

while(address != '\0')
{
ok = 0;

if(address == words[0])
{
s = x, a = 1;
x ++;

while(words != '\0')
{
if(address != words){ ok = 1; break; }
x ++;
a ++;
}

x = s;
if(!copyln) return x;

if(!ok)
{
nullpointer:
int p = s+offfrom, y = 0;

while(y < copyln)
{
if(address == until[0] ||
address == until[1] ||
address == until[2] ||
address == until[3] ||
address == until[4]) break;

buffer = address;
p ++;
y ++;
}

buffer = '\0';
return x;
}

}

x ++;

}

return -1;

}
Posted on 2001-09-16 14:32:50 by nin
See how close MASM is to C. A line for line translation. :)
return MACRO val:REQ

mov eax,val
ret
ENDM

;int searchstring(char *words, char *address, char *buffer, char *until, int offfrom, int copyln) {
searchstring PROC uses esi edi ebx,pWORDS:DWORD,pADDRESS:DWORD,pBUFFER:DWORD,pUNTIL:DWORD,offfrom:DWORD,copyln:DWORD
LOCAL s:DWORD
address EQU esi
words EQU edi
mov address,pADDRESS
mov words,pWORDS
x EQU ecx
a EQU edx
ok EQU ebx
;int x = 0, s = 0, a = 0, ok = 0;
mov x,0
mov s,0
mov a,0
mov ok,0
;if(!words) goto nullpointer;
.if !pWORDS
jmp nullpointer
.endif
;while(address[x] != '\0') {
.while (BYTE PTR [address + x] != 0)
;ok = 0;
mov ok,0
;if(address[x] == words[0]) {
mov al,[words]
.if BYTE PTR [address + x] == al
;s = x, a = 1;
mov s,x
mov a,1
;x ++;
inc x
;while(words[a] != '\0') {
.while BYTE PTR [words + a] != 0
;if(address[x] != words[a]){ ok = 1; break; }
mov al,[words + a]
.if [address + x] != al
mov ok,1
.break
.endif
;x ++;
inc x
;a ++;
inc a
;}
.endw
;x = s;
mov x,s
;if(!copyln) return x;
.if !copyln
return s ;s=x at this point!
.endif
;if(!ok) {
.if !ok
nullpointer:
p EQU ecx
y EQU edx
until EQU ebx
buffer EQU edi
mov buffer,pBUFFER
mov until,pUNTIL
;int p = s+offfrom, y = 0;
mov p,offfrom
add p,s
mov y,0
;while(y < copyln) {
.while y < copyln
;if(address[p] == until[0] || address[p] == until[1] || address[p] == until[2] || address[p] == until[3] || address[p] == until[4]) break;
mov al,[address + p]
.if al == [until]
.break
.elseif al == [until + 1]
.break
.elseif al == [until + 2]
.break
.elseif al == [until + 3]
.break
.endif
;buffer[y] = address[p];
mov al,[address + p]
mov [buffer + y],al
;p ++;
inc p
;y ++;
inc y
;}
.endw
;buffer[y] = '\0';
mov BYTE PTR [buffer + y],0
;return x;
return s ;s=x at this point!
;}
.endif
;}
.endif
;x ++;
inc x
;}
.endw
;return -1;
return -1
;}
searchstring ENDP
Posted on 2001-09-16 17:26:32 by bitRAKE
nin, if you have a C algo you want to translate to asm, looking at
the compiler output is not a very good idea, at least not if you want
to try and understand what is happening - the same would be the
case when looking at highly optimized code written by somebody who's
good at optimizing asm code.

If you want to mess with C/Asm linking, there's a lot of reading to
do. Calling conventions, name mangling, how the stack works, et
cetera.

May I ask why you are messing with compiler-output asm source?
If you just want to link C with asm code, that's not hard to do. If you
want to optimize your code, there are better approaches.
Posted on 2001-09-16 17:48:10 by f0dder
Well i had quite a good encryption algo not written by me in C and wanted to be able to turn it into an asm proc using the same params. searchstring proc was just an example of what I was trying to do. Basically, how can I convert it in this way from vc++??
Posted on 2001-09-16 18:12:47 by nin
What f0dder was getting at was that you don't need to convert it - unless you find that kind of thing fun. :) You could compile an object file and link it to your asm project, or you assemble your assembly stuff into an object file and link it into a C project. There are many options that you can choose from.

VC++ produces much better code than my conversion above. It was just an example.
Posted on 2001-09-16 20:04:30 by bitRAKE
Ahh nice! But how do I create an object file for 1 function in vc++. Or better still would it be better to create a .lib? And don't I have to re-arrange things cos of the way the params are arranged in vc++??
Posted on 2001-09-17 04:27:49 by nin
The "Hardest" thing about linking asm with C is the calling conventions
and name mangling. Make sure your C compiler uses the "C" calling
convention. If you're compiling in c++ mode, declare your functions
like:



extern "C" int myFunc(int parm1, int parm2);


Or, even better



#ifdef __cplusplus
extern "C" {
#endif

// function prototypes here

#ifdef __cplusplus
}
#endif


In masm, you will then have to generate prototypes for your
functions, like...



myFunc PROTO C :DWORD, :DWORD


... and then you should be all set, and able to use invoke :).
Posted on 2001-09-17 08:26:46 by f0dder
If you do want to use the code in MASM, then you can disable the prologue & epilogue like so:



OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE

This will stop the variable names being any use to you though, you also have to remember to "ret" the proper value (not a problem with the C calling convention as it is always 0)!

Remember to re-enable the defaults afterwards though!


OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef


If you do just want to use the function as is, it would probably be better to just keep the C obj file though.

Mirno
Posted on 2001-09-17 09:13:21 by Mirno