The MASM Forum

General => The Campus => Topic started by: Ron on July 23, 2015, 12:48:36 AM

Title: Memory deletion issue
Post by: Ron on July 23, 2015, 12:48:36 AM
This is in a C++ application that calls a function which uses assembly language. The function works correctly but if I execute the delete[] line, it abends.

unsigned char * inB2;
inB2 = new (std::nothrow) unsigned char[count];
if (inB2 != nullptr) {



__asm {

pushad

mov esi, inB

mov edi, inB2

add esi, count
mov ecx, count

xor eax, eax

lodsb

push eax
dec esi
dec esi

L1 :
lodsb
mov[edi], al
dec esi
dec esi
inc edi
dec ecx
jnz L1
pop eax
stosb

//now copy back into inB
                                //if I comment this out, the function does not abend

mov esi, inB2
mov edi, inB
mov ecx, count
dec ecx
L2:
lodsb
stosb
dec ecx
jnz L2
 
popad
}
delete[] inB2;
}


I'll admit, C++ is not my strong suit.

RON
Title: Re: Memory deletion issue
Post by: dedndave on July 23, 2015, 01:08:11 AM
that routine makes no sense - lol

you seem to be missing part of the idea behind the string instructions
and - i think the code may attempt to access data beyond the inB and inB2 buffers

by default, the direction flag will be cleared - at least, i believe that to be true
after a LODSB is executed, ESI is automatically incremented (by 1 because it's a byte instruction)
after a STOSB, EDI is automatically incremented in the same manner
LODSW would increment ESI by 2
LODSD would increment ESI by 4
if the direction flag were set, it would decrement the pointers, instead
STD and CLD are very slow instructions on many processors
in fact, LODSB and STOSB aren't as fast as they could be
inside the L2 loop, you use LODSB and STOSB - MOVSB could be used to replace both

the only time you get good performance out of the string instructions is when used with REP
to use REP, you put the count in ECX and execute
the entire L2 loop could be replaced with
    rep     movsb

but, i believe the trouble is before the loop
carefully step through that code, and keep track of where ESI and EDI are pointing
Title: Re: Memory deletion issue
Post by: dedndave on July 23, 2015, 01:12:13 AM
mov esi, inB

mov edi, inB2

add esi, count
mov ecx, count

xor eax, eax

lodsb


bang !
the first LODSB accesses data beyond the inB buffer
it points to the address of inB, plus the count
so - it is pointing to the first byte that follows the buffer
after LODSB executes, it would point to the next byte after that one   :P
Title: Re: Memory deletion issue
Post by: Gunther on July 23, 2015, 02:10:19 AM
Good catch, Dave.  :t It can be adopted with the inline assembler or as an external procedure.

Gunther
Title: Re: Memory deletion issue
Post by: Ron on July 23, 2015, 02:47:59 AM
Thanks. I didn't see that. I'm just trying to (re) learn some string manipulation in assembler. This function takes an unsigned char array and reverses it. Now it works, OK. Including the delete[] at the end.
Title: Re: Memory deletion issue
Post by: dedndave on July 23, 2015, 03:04:59 AM
        push    esi
        push    edi
        mov     ecx,count
        mov     esi,inB
        mov     edi,inB2
        push    esi
        push    ecx
        dec     esi
        push    edi

L1:     mov     al,[esi+ecx]
        mov     [edi],al
        dec     ecx
        lea     edi,[edi+1]
        jnz     L1

        pop     edi
        pop     ecx
        pop     esi
        rep     movsb
        pop     edi
        pop     esi