#include        "defs.h"

void *asm_pushad(__in void *p){
        unsigned char *b = p;
        
        b[0] = 0x60;
        return b+1;
}


void *asm_pushfd(__in void *p){
        unsigned char *b = p;
        
        b[0] = 0x9C;
        return b+1;
}

void *asm_popad(__in void *p){
        unsigned char *b = p;
        
        b[0] = 0x61;
        return b+1;
}

void *asm_popfd(__in void *p){
        unsigned char *b = p;
        
        b[0] = 0x9D;
        return b+1;
}

void *asm_push_imm32(__in void *p, unsigned long imm32){
        unsigned char *b = p;
        
        b[0] = 0x68;
        *(ULONG_PTR *)&b[1] = imm32;
        return b+5;
}

void *asm_push_reg(__in void *p, __in unsigned long reg){
        unsigned char *b = p;
        b[0] = 0x50 + (unsigned char)reg;
        return b+1;
}

void *asm_pop_reg(__in void *p, __in unsigned long reg){
        unsigned char *b = p;
        
        b[0] = 0x58 + (unsigned char)reg;
        return b+1;
}

void *asm_mov_reg_imm32(__in void *p, __in unsigned long reg, __in unsigned long imm32){
        unsigned char *b = p;
        
        b[0] = 0xB8 + (unsigned char)reg;
        *(ULONG_PTR *)&b[1] = (ULONG_PTR)imm32;
        return b+5;
}

void *asm_xchg_esp_teb(__in void *p, __in unsigned long imm32){
        unsigned char *b = p;
        
        b[0] = 0x64;
        b[1] = 0x87;
        b[2] = 0x25;
        *(ULONG_PTR *)&b[3] = imm32;
        
        return b+7;
}

void *asm_mov_reg_mem32(__in void *p, __in unsigned long reg, __in unsigned long mem32){
        unsigned char *b = p;
        
        b[0] = 0x8B;
        b[1] = 0x05 + ((unsigned char)reg << 3);
        *(ULONG_PTR *)&b[2] = mem32;
        return b+6;
}
        
void *asm_mov_mem32_reg(__in void *p, __in unsigned long mem32, __in unsigned long reg){
        unsigned char *b = p;
        
        b[0] = 0x89;
        b[1] = 0x05 + ((unsigned char)reg << 3);
        *(ULONG_PTR *)&b[2] = mem32;
        return b+6;
}

void *asm_add_fs_prefix(__in void *p){
        unsigned char *b = p;
        
        b[0] = 0x64;
        return b+1;
}

void *asm_mov_mem32_imm32(__in void *p, __in unsigned long mem32, __in unsigned long imm32){
        unsigned char *b = p;
        
        b[0] = 0xC7;
        b[1] = 0x05;
        *(ULONG_PTR *)&b[2] = (ULONG_PTR)mem32;
        *(ULONG_PTR *)&b[6] = (ULONG_PTR)imm32;
        
        return b+10;
}

void *asm_push_mem32(__in void *p, __in unsigned long mem32){
        unsigned char *b = p;
        
        b[0] = 0xFF;
        b[1] = 0x35;
        *(ULONG_PTR *)&b[2] = (ULONG_PTR)mem32;
        return b+6;
}        

void *asm_call_mem32(__in void *p, __in unsigned long mem32){
        unsigned char *b = p;
        
        b[0] = 0xFF;
        b[1] = 0x15;
        *(ULONG_PTR *)&b[2] = (ULONG_PTR)mem32;
        return b+6;
}

void *asm_jmp_mem32(__in void *p, __in unsigned long mem32){
        unsigned char *b = p;
        
        b[0] = 0xFF;
        b[1] = 0x25;
        *(ULONG_PTR *)&b[2] = (ULONG_PTR)mem32;
        return b+6;
}        

void *asm_add_reg_imm(__in void *p, __in unsigned long reg, __in unsigned long imm32){
        unsigned char *b = p;
        
        b[0] = 0x81;
        b[1] = 0xC0 + (unsigned char)reg;
        *(ULONG_PTR *)&b[2] = imm32;
        return b+6;
}

void *asm_sub_reg_imm(__in void *p, __in unsigned long reg, __in unsigned long imm32){
        unsigned char *b = p;
        
        b[0] = 0x81;
        b[1] = 0xE8 + (unsigned char)reg;
        *(ULONG_PTR *)&b[2] = imm32;
        return b+6;
}


void *asm_int(__in void *p, __in unsigned long imm32){
        unsigned char *b = p;
        
        b[0] = 0xCD;
        b[1] = (unsigned char)imm32;
        return b+2;
}

void *asm_mov_reg_mem32_reg(__in void *p, __in unsigned long reg_dst, __in unsigned long mem_dest, __in unsigned long reg_src){
        unsigned char *b = p;
        
        b[0] = 0x89;
        b[1] = 0x80 + (unsigned char)reg_dst + (unsigned char)(reg_src << 3);
        *(ULONG_PTR *)&b[2] = mem_dest;
        return b+6;
}

void *asm_mov_reg_reg_mem32(__in void *p, __in unsigned long reg_dst, __in unsigned long reg_src, __in unsigned long mem_src){
        unsigned char *b = p;
        
        b[0] = 0x8B;
        b[1] = 0x80 + (unsigned char)reg_src + (unsigned char)(reg_dst << 3);
        *(ULONG_PTR *)&b[2] = mem_src;
        return b+6;
}         

void *asm_mov_reg_mem32_imm(__in void *p, __in unsigned long reg_dst, __in unsigned long mem_dest, __in unsigned long imm_src){
        unsigned char *b = p;
        
        b[0] = 0xC7;
        b[1] = 0x80 + (unsigned char)(reg_dst);
        *(ULONG_PTR *)&b[2] = mem_dest;
        *(ULONG_PTR *)&b[6] = imm_src;
        return b + 10;
}

void *asm_sysenter(__in void *p){
        unsigned char *b = p;
        b[0] = 0x0F;
        b[1] = 0x34;
        return b+2;
}

void *asm_call_reg(__in void *p, __in unsigned long reg){
        unsigned char *b = p;
        
        b[0] = 0xFF;
        b[1] = 0xD0 + (unsigned char)reg;
        return b+2;
}

void *asm_ret(__in void *p, __in unsigned long imm32){
       unsigned char *b = p;
       
       b[0] = 0xC2;
       *(unsigned short *)&b[1] = (unsigned short)imm32;
       return b+3;  
}
  
void *asm_jcc_short(__in void *p, __in unsigned long iclass, __in unsigned long offset){
        unsigned char *b = p;
        
        switch (iclass)
        {
        case XED_ICLASS_JB 	        :
                b[0] = 0x72;
                break;
        case XED_ICLASS_JBE 	        :
                b[0] = 0x76;
                break;
        case XED_ICLASS_JL 	        :
                b[0] = 0x7C;
                break;
        case XED_ICLASS_JLE 	        :
                b[0] = 0x7e;
                break;
        case XED_ICLASS_JNB 	        :
                b[0] = 0x73;
                break;
        case XED_ICLASS_JNBE 	        :
                b[0] = 0x77;
                break;
        case XED_ICLASS_JNL 	        :
                b[0] = 0x7D;
                break;
        case XED_ICLASS_JNLE 	        :
                b[0] = 0x7F;
                break;
        case XED_ICLASS_JNO 	        :
                b[0] = 0x71;
                break;
        case XED_ICLASS_JNP 	        :
                b[0] = 0x7B;
                break;
        case XED_ICLASS_JNS 	        :
                b[0] = 0x79;
                break;
        case XED_ICLASS_JNZ 	        :
                b[0] = 0x75;
                break;
        case XED_ICLASS_JO 	        :
                b[0] = 0x70;
                break;
        case XED_ICLASS_JP 	        :
                b[0] = 0x7A;
                break;
        case XED_ICLASS_JS 	        :
                b[0] = 0x78;
                break;
        case XED_ICLASS_JZ              :
                b[0] = 0x74;
                break;
        default:
                DbgPrint(("% -- Unknown jcc with iclass : %d", __FUNCTION__, iclass));
                __asm jmp $
        }
        
        b[1] = (unsigned char)offset;
        return b+2;        
}  