Valhalla Legends Forums Archive | Assembly Language (any cpu) | Improper Operand Type

AuthorMessageTime
iago
I'm having a problem using inline assembly. Here is my code, it's a fairly simple wrapper:
[code]void __declspec(naked) __fastcall CatchWrapper()
{
   static const DWORD Continue = 0x6facc128;
   static const DWORD NoContinue = 0x6facc089;

   __asm
   {
      push ecx
      call CommandCatcher
      test eax,eax
      je NoContinue
      jmp Continue
   }   
}[/code]

the line "je NoContinue" is failing to compile with the message "Improper operand type".
[quote]c:\Documents and Settings\Ron\My Documents\Visual Studio Projects\Plugin\Catcher.cpp(15): error C2415: improper operand type[/quote]

If I switch the je to a jz, jne, or jnz, there is no change. If I switch it to a jmp, it works fine (compiles, I mean). Any idea why the compiler doesn't like je and jne?
August 6, 2003, 12:15 PM
Adron
As far as I know, conditional jumps are always relative jumps. The opcode has an 8-bit or 32-bit signed jump offset. There's just no support in the cpu for reading the destination from a memory location. To find out more about this, look at "addressing modes" for various instructions.
August 6, 2003, 12:25 PM
iago
Hmm, that would make it rather difficult to do a conditional jump to a specific address. How would you get around it?

I'm thinking like this:
[code]void __declspec(naked) __fastcall CatchWrapper()
{
static const DWORD Continue = 0x6facc128;
static const DWORD NoContinue = 0x6facc089;

__asm
{
push ecx
call CommandCatcher
test eax,eax
je bah
jmp Continue
bah:
jmp NoContinue
}
}[/code]

Is that the best way to do it?
August 6, 2003, 12:52 PM
Adron
If I was a compiler, I might do something like this:

[code]
void __declspec(naked) __fastcall CatchWrapper()
{
#define Continue 0x6facc128
#define NoContinue 0x6facc089
__asm
{
push ecx
call CommandCatcher
test eax, eax
sbb eax, eax
and eax, Continue-NoContinue
add eax, NoContinue
jmp eax
}
}
[/code]

The code is completely untested, but you get the idea?
August 6, 2003, 2:10 PM
iago
haha that's really cool code, honestly.

I get the idea, make eax a boolean, use overflow and whatnot.. that's nuts, but I love the code :D
August 6, 2003, 2:56 PM
Yoni
That's pretty common, try for example:
[code]int x = somebool ? 17 : 42;[/code]
Or almost anything else with the ?: operator, and see how the compiler compiles it. Microsoft's compiler likes to turn that into a test+sbb+and+add combination.
August 10, 2003, 11:19 PM
Adron
Actually, later that same day I demonstrated that fact with this code:

[code]
typedef void somefuncptr(void);
#define address1 0x12345678
#define address2 0x9abcdef0
   ((somefuncptr*)(yourfunctionyoucall() ? address1 : address2)) ();
[/code]

which becomes

[code]
00009   e8 00 00 00 00    call    ?yourfunctionyoucall@@YAHXZ ; yourfunctionyoucall
0000e   f7 d8       neg    eax
00010   1b c0       sbb    eax, eax
00012   25 88 77 77 77    and    eax, 2004318088      ; 77777788H
00017   05 f0 de bc 9a    add    eax, -1698898192   ; 9abcdef0H
0001c   ff d0       call    eax
[/code]


It is common for compilers to generate that code, but not nearly as common for human assembler coders to do. That's why I said "if i was a compiler" :)
August 11, 2003, 8:39 AM
Grok
<ot>

If you squint, it looks like Adron's code is trying to spell something ... "IRb --"

</ot>
August 11, 2003, 11:40 PM

Search