News:

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

Inline Assembly not the Same as MASM?

Started by Kyle, December 01, 2009, 01:29:17 AM

Previous topic - Next topic

Kyle

I've been taking what MSVC 2008 puts out when I tell it to generate the assembly, and I get lines like:

mov BYTE PTR Box [ ebp + ecx ], cl ------ error C2404: 'ecx' : illegal register in 'first operand'

mov BYTE PTR Testvar [ ebp + ecx - 1 ], al ------ error C2404: 'ecx' : illegal register in 'first operand'

movzx ecx, BYTE PTR Enhance [ ebp + edx ] ------ error C2404: 'edx' : illegal register in 'second operand'

lea ecx, DWORD PTR Box [ ebp + ecx ] ------ error C2404: 'ecx' : illegal register in 'second operand'


Of course I cleaned it up a bit and then tried to inline it in the project. But is there any work around for this? I'm rather new to this, so its a bit odd. I know this may be an odd question.

I reckon this would work just fine in MASM, so I'm a bit stumped why MSVC is throwing a fit.

dedndave

i am not sure why it is doing that
it could be because the EBP register wants to reference to the stack segment
try switching it to EBX

        mov     Box[ebx+ecx],cl

i dunno about all those spaces, either - lol

or segment override

        mov     ds:Box[ebp+ecx],cl

BYTE PTR isn't needed in this case, because the size of the CL register forces it to be a byte
EDIT - oops - if Box is defined as a something other than a byte array, BYTE PTR may be required

hutch--

Kyle,

There is good reason NOT to use inline assembler in an optimising compiler, the register usage in inline assembler either messes up the optimisation due to lack of registers OR the compiler isolates the inline assembler code and increases its overhead which slows it down.

If it matters enough to try and make it faster, make the extra effort and put the assembler into a seperate module and link it into the app, this wa you get the best of both worlds, optimised compiles and fast assembler.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

Kyle

I tried both of your suggestions, and both of them gave the exact same error. I guess MSVC doesn't like 2 registers being used like that. I tried switching from ebp to ebx and the segment override. Looks like I'll have to switch to just use MASM lol.

I usually just stick with inline assembly for being able to deal with the parameters and local variables easier. So this will be a good learning experience.

@ Hutch, I think I'm just going to completely switch over to MASM rather than bother with inline assembly. It seems time to switch over already anyways. I'm tired of the runtime and assumptions the compiler makes.

drizz

are "Box" etc. local variables?

don't forget that local variables are referenced through esp or ebp

you can't have
mov BYTE PTR [ ESP+ ebp + ecx ], cl
three registers for address, last one reported as error.


The truth cannot be learned ... it can only be recognized.

Kyle

Yes they are locals. Well, if thats the case I suppose I need to look into how to use ESP/EBP to reference them.

drizz

Do the addition before memory access.

mov BYTE PTR Box [ ebp + ecx ], cl ------ error C2404: 'ecx' : illegal register in 'first operand'
mov BYTE PTR Testvar [ ebp + ecx - 1 ], al ------ error C2404: 'ecx' : illegal register in 'first operand'
movzx ecx, BYTE PTR Enhance [ ebp + edx ] ------ error C2404: 'edx' : illegal register in 'second operand'
lea ecx, DWORD PTR Box [ ebp + ecx ] ------ error C2404: 'ecx' : illegal register in 'second operand'


-->

add ebp,ecx
mov BYTE PTR Box [ ebp ], cl
...
etc.


or if via temp register

lea eax,[ebp+ecx]
mov BYTE PTR Box [ eax ], cl
...
etc.


of course learning the stack layout won't hurt either... :wink
The truth cannot be learned ... it can only be recognized.

MichaelW

Kyle,

You could avoid the compiler's use of EBP/ESP, and minimize the overhead, by using a naked function where what you get is just what you coded.


__declspec( naked ) int sum( int arg1, int arg2 )
{
    __asm
    {
        mov eax, [esp+4]
        add eax, [esp+8]
        ret
    }
}


PUBLIC _sum
; Function compile flags: /Odt
_TEXT SEGMENT
_arg1$ = 8 ; size = 4
_arg2$ = 12 ; size = 4
_sum PROC NEAR
; File c:\program files\microsoft visual c++ toolkit 2003\my\naked\test.c
; Line 5
mov eax, DWORD PTR [esp+4]
; Line 6
add eax, DWORD PTR [esp+8]
; Line 7
ret 0
_sum ENDP
_TEXT ENDS

eschew obfuscation

Kyle

Quote from: drizz on December 01, 2009, 09:04:59 PM
Do the addition before memory access.

mov BYTE PTR Box [ ebp + ecx ], cl ------ error C2404: 'ecx' : illegal register in 'first operand'
mov BYTE PTR Testvar [ ebp + ecx - 1 ], al ------ error C2404: 'ecx' : illegal register in 'first operand'
movzx ecx, BYTE PTR Enhance [ ebp + edx ] ------ error C2404: 'edx' : illegal register in 'second operand'
lea ecx, DWORD PTR Box [ ebp + ecx ] ------ error C2404: 'ecx' : illegal register in 'second operand'


-->

add ebp,ecx
mov BYTE PTR Box [ ebp ], cl
...
etc.


or if via temp register

lea eax,[ebp+ecx]
mov BYTE PTR Box [ eax ], cl
...
etc.


of course learning the stack layout won't hurt either... :wink

Ah I can't believe I didn't think of that. I'm actually about to try that and see what happens (should work, I don't see why it wouldn't). But one quick question, adding the contents of ecx to ebp like that, is there anything I should do to restore ebp back to where it was before the addition operation?

Quote from: MichaelW on December 01, 2009, 10:03:37 PM
Kyle,

You could avoid the compiler's use of EBP/ESP, and minimize the overhead, by using a naked function where what you get is just what you coded.


__declspec( naked ) int sum( int arg1, int arg2 )
{
    __asm
    {
        mov eax, [esp+4]
        add eax, [esp+8]
        ret
    }
}


PUBLIC _sum
; Function compile flags: /Odt
_TEXT SEGMENT
_arg1$ = 8 ; size = 4
_arg2$ = 12 ; size = 4
_sum PROC NEAR
; File c:\program files\microsoft visual c++ toolkit 2003\my\naked\test.c
; Line 5
mov eax, DWORD PTR [esp+4]
; Line 6
add eax, DWORD PTR [esp+8]
; Line 7
ret 0
_sum ENDP
_TEXT ENDS



Oh man I love the suggestions I'm getting on this forum. You all are really getting me much more active with learning  :toothy :toothy :toothy. I'm going to look into naked functions after I get this sorted.




I got rid of all the errors, (which sometimes means nothing for MSVC) but I'm still getting this error:

Quote'strlen' : illegal symbol in first operand

from the lines:

push OFFSET MyString
call strlen


Seems a bit odd, as the proper headers, etc are included. But this seems to be the inline assembly whining about how I'm calling it or something of the sort.

drizz

msvc++ automatically preserves all volatile registers you use in your inline assembly, unless "__declspec( naked )" is specified.
Just be careful with ebp as it may or may not be used to reference local variables, depending on your compiler options (optimization).

There shouldn't be any problem with "call strlen", just know that it is a __cdecl function (caller balances the stack).

push string
call strlen
add esp,4
The truth cannot be learned ... it can only be recognized.

Kyle

Hmm, I tried exactly what you just showed and MSVC is still giving me the error. This is very odd.

Quoteerror C2420: 'strlen' : illegal symbol in first operand
error C2415: improper operand type

It says that about the same line:

call strlen

:(

drizz

The truth cannot be learned ... it can only be recognized.

drizz

ok, this seems to be ms compiler issue, it compiles fine with /O1 , but fails with /O2 switch.
intel c++ does not have this issue. msvc probably tries to optimise strlen but fails to realise its in asm block.

#include <string.h>
main(){
__asm{
int 3
call strlen
}
}

CL /c /O1 /GB /w /TP
The truth cannot be learned ... it can only be recognized.

drizz

yeah, compiler fails to realise that intrinsic expansion of strlen is in __asm block.
use "/Oi-"
The truth cannot be learned ... it can only be recognized.

Kyle

Yeah now it compiled :). But I'm going to have to work out the code without using [ ebp ] as that is making the application crash.