News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Inline functions

Started by GODlike, December 17, 2005, 09:36:21 PM

Previous topic - Next topic

GODlike

I was looking the disassembled code of a simple program built in VC++6 (Release). The program just calls the strlen function. I found out that instead of using the classic push to pass arguments the code was inline.

mov edi, offset pch0 (004080fc) 
or ecx, 0FFFFFFFFh       
xor eax, eax
repne scas byte ptr [edi]   
not ecx
dec ecx


I've tried many approaches to find what piece of C++ code produces this thing (inline functions, inline assembly etc). Unfortunately I couldn't produce something optimized like this.

I know that this is not related to assembly but I the help will solve an assembly problem. Any ideas??? Thanks!

zooba

It will be a command-line option most likely (somewhere in your IDE probably, or maybe a @pragma).

comrade

If you use IDA disassembler, it maybe give you a hint what compiler/runtime was used.

Human

in project setting in optimializations etc there is options for inlines, none,only inline, and any suitable, last one will try to convert all into inline

GODlike

I wrote this strlen function:

unsigned int inline strlen_ (char* pc)
{
_asm
{
mov edi, pc
xor eax, eax
or ecx, 0FFFFFFFFh

repne scas byte ptr [edi]

not ecx
dec ecx
mov eax, ecx
}
}


Now I have this C++ code:

...
x = strlen(pch0);          //VC++'s strlen
y = strlen_(pch0);       //Mine strlen
...


In disassembly:

x = strlen(pch0);

mov edi, offset pch0 (004080fc)
or ecx, 0FFFFFFFFh
xor eax, eax
repne scas byte ptr [edi]
not ecx
dec ecx
mov dword ptr [x (004080f4)], ecx

y = strlen_(pch0);

mov edi, offset pch0 (004080fc)
xor eax, eax
or ecx, 0FFFFFFFFh
repne scas byte ptr [edi]
not ecx
dec ecx
mov eax, ecx
mov [y (004080f8)], eax


The difference:

mov dword ptr [x (004080f4)], ecx

VS

mov eax,ecx
mov [y (004080f8)], eax


How the VC++'s function returns the value to the ecx???? How can I make my strlen to return the value to another register beside eax??? Once again thanks for the response!


P.S.: Sorry for the long message but I want to make my question as understandable as possible.

EduardoS

The VC++ use ECX, EAX and EDX as general porpose registers, so to compile your code it may use any of these registers to pass values, in the inline strlen the result stay on ecx, so it use ecx,
I'm not a C++ expert, don't know how to say to VC++ that your function return value in ecx.

GODlike

Quote from: EduardoS on December 18, 2005, 09:03:32 PMI'm not a C++ expert, don't know how to say to VC++ that your function return value in ecx.

This is it. How to tell VC++ to return the value to the ecx.

MichaelW

C/C++ functions normally return 32-bit integer values in EAX. This code:

mov dword ptr [x (004080f4)], ecx

Looks to me like an optimization that the compiler performed, assigning the return value directly from ECX. I don't know how you could efficiently duplicate this from within the function. Passing the address of the destination to the function and doing the assignment within the function would entail several additional instructions, where your current coding requires only one additional instruction, compared to the compiler-generated code. AFAIK the best you can do is to leave the return value in EAX, as you are currently doing with:

mov  eax, ecx

As the last instruction, or statement, in the function.

Agner Fog has a 39-page PDF document: "Calling conventions for different C++ compilers and operating systems", available here:
http://www.agner.org/assem/calling_conventions.pdf

eschew obfuscation

GODlike

I guess that there isn't a way to return the value to ecx. But I still wondering what's the code of strlen. :(

zooba

Quote from: MSDN: Optimizing Inline AssemblyThe presence of an __asm block in a function affects optimization in several ways. First, the compiler doesn't try to optimize the __asm block itself. What you write in assembly language is exactly what you get. Second, the presence of an __asm block affects register variable storage. The compiler avoids enregistering variables across an __asm block if the register's contents would be changed by the __asm block. Finally, some other function-wide optimizations will be affected by the inclusion of assembly language in a function.

Perhaps this is one of them? It won't try and substitute return variables if you've used an __asm block in your code?

As for the code of strlen:

size_t __cdecl strlen (
        const char * str
        )
{
        const char *eos = str;

        while( *eos++ ) ;

        return( (int)(eos - str - 1) );
}


Taken from the source distributed with VS2003

hutch--

I don't really see what the problem is if you bother to write seperate modules in an assembler then link them into C/C++ code, all it requires is properly prototyping the assembler modules in C/C++ using the correct EXTERN syntax. This keeps hand written code out of the compiler optimisation area and you get the best of both techniques.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

zooba

The compiler doesn't attempt to optimise __asm blocks, and it apparently won't attempt to optimise blocks containing __asm blocks. Linking in an external file won't change this, you're best off using the 'mov eax, ecx' instruction :P :8)

GODlike

Thanks for the responses. The problem isn't the strlen but the way VC++ do the opts. I'll work with the new input (thanks zooba) and I will post something more complete.

Once again thanks!! :thumbu

l_d_allan

QuoteI've tried many approaches to find what piece of C++ code produces this thing (inline functions, inline assembly etc). Unfortunately I couldn't produce something optimized like this.

I'm not sure I understand the question, but the Microsoft compiler has
#pragma intrinsic(strlen) 
... and numerous other low-level functions
which will cause use of inline asm code as applicable ... if that function is available

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccelng/htm/pragm_17.asp