• Welcome to Valhalla Legends Archive.
 

Improper Operand Type

Started by iago, August 06, 2003, 07:15 AM

Previous topic - Next topic

iago

I'm having a problem using inline assembly.  Here is my code, it's a fairly simple wrapper:
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
   }   
}


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

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?
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


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.

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:
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
  }  
}


Is that the best way to do it?
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


Adron

If I was a compiler, I might do something like this:


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
 }  
}


The code is completely untested, but you get the idea?

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
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


Yoni

That's pretty common, try for example:
int x = somebool ? 17 : 42;
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.

Adron

#6
Actually, later that same day I demonstrated that fact with this code:


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


which becomes


 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



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" :)

Grok

#7
<ot>

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

</ot>