首页
社区
课程
招聘
[求助]請問關於C++問題
发表于: 2015-1-31 16:51 11871

[求助]請問關於C++問題

2015-1-31 16:51
11871
unsigned int num_src = *ModRM & 0x7;
unsigned int num_dst = (*ModRM >> 3) & 0x7;
unsigned int mod = *ModRM >> 6;

這個計算方式是怎麼計算

我知道 ModRM 的值是byte 0x00 - 0xff

& 跟 >> 我還是看不懂

我有爬過文 但是還是不能裡解...

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 0
支持
分享
最新回复 (30)
雪    币: 7048
活跃值: (3527)
能力值: ( LV12,RANK:340 )
在线值:
发帖
回帖
粉丝
2
*ModRM & 0x7就是取ModRM的值,然后与0x7做and运算.
(*ModRM >> 3) & 0x7就是取ModRM的值并右移3位,再与0x7做and运算.
*ModRM >> 6就是取ModRM的值并右移6位.

按照代码的逻辑来看.
num_src就是*ModRM的低3位(1~3).
num_dst就是*ModRM的中3位(4~6).
mod就是*ModRM的高2位(7~8).
2015-1-31 17:06
0
雪    币: 23
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
楼主这是要搞编译器的节奏啊,如果要搞编译器,小弟愿意尽绵薄之力,一直想搞个咱们国内原创的编译引挚。苦于没团队做噢。
2015-1-31 19:57
0
雪    币: 376
活跃值: (92)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
大神有写个 汇编注入器 资料参考吗,想写个 输入框里面 写入汇编注入进程的小工具
2015-1-31 21:05
0
雪    币: 320
活跃值: (104)
能力值: (RANK:180 )
在线值:
发帖
回帖
粉丝
5
我是想試著改 SSSE3 模擬器 給AMD老CPU用的

我不知道這樣修改對不對

指令部份我用 SSEPlus 模擬的

目前測試是有bug jpg圖片顯示顏色不正常

int ssse3_emu(uint8_t *instruction, x86_saved_state_t *state, int longmode, int kernel_trap)
{
    // pointer to the current byte we're working on
    uint8_t *bytep = instruction;
    int ins_size = 0;
    int is_128 = 0, src_higher = 0, dst_higher = 0;

    ssp_m128 xmmsrc, xmmdst, xmmres;
    ssp_m64 mmsrc,mmdst, mmres;

    /** We can get a few prefixes, in any order:
     **  66 throws into 128-bit xmm mode.
     **  40->4f use higher xmm registers.
     **/
    if(*bytep == 0x66) {
        is_128 = 1;
        bytep++;
        ins_size++;
    }

    if((*bytep & 0xF0) == 0x40) {
        if(*bytep & 1) src_higher = 1;
        if(*bytep & 4) dst_higher = 1;
        bytep++;
        ins_size++;
    }

    if(*bytep != 0x0f) return 0;
    bytep++;
    ins_size++;

    /* Two SSSE3 instruction prefixes. */
    if((*bytep == 0x38 && bytep[1] != 0x0f) || (*bytep == 0x3a && bytep[1] == 0x0f)) {
        uint8_t opcode = bytep[1];
        uint8_t *modrm = &bytep[2];
        unsigned char imm;
        ins_size += 2; // not counting modRM byte or anything after.

        if (opcode == 0x0f)
        {
            if ((bytep[2] > 0x3F) && (bytep[2] < 0x80))
            {
                imm = bytep[4]; // modrm offset + 2
            }
            else if ((bytep[2] > 0x7F) && (bytep[2] < 0xC0))
            {
                imm = bytep[7]; // modrm offset + 5
            }
            else
            {
                imm = bytep[3]; // modrm offset + 1
            }
        }

        if(is_128)
        {
            int consumed = fetchoperands(modrm, src_higher, dst_higher, &xmmsrc, &xmmdst, longmode, state, kernel_trap, 1, ins_size);

            ins_size += consumed;

            switch(opcode) {
                case 0x00: //pshufb128(&xmmsrc,&xmmdst,&xmmres); break;
                    xmmres.i = ssp_shuffle_epi8_SSSE3 (xmmdst.i, xmmsrc.i); break;
                case 0x01: //phaddw128(&xmmsrc,&xmmdst,&xmmres); break;
                    xmmres.i = ssp_hadd_epi16_SSSE3 (xmmdst.i, xmmsrc.i); break;
                case 0x02: //phaddd128(&xmmsrc,&xmmdst,&xmmres); break;
                    xmmres.i = ssp_hadd_epi32_SSSE3 (xmmdst.i, xmmsrc.i); break;
                case 0x03: //phaddsw128(&xmmsrc,&xmmdst,&xmmres); break;
                    xmmres.i = ssp_hadds_epi16_SSSE3 (xmmdst.i, xmmsrc.i); break;
                case 0x04: //pmaddubsw128(&xmmsrc,&xmmdst,&xmmres); break;
                    xmmres.i = ssp_maddubs_epi16_SSSE3 (xmmdst.i, xmmsrc.i); break;
                case 0x05: //phsubw128(&xmmsrc,&xmmdst,&xmmres); break;
                    xmmres.i = ssp_hsub_epi16_SSSE3 (xmmdst.i, xmmsrc.i); break;
                case 0x06: //phsubd128(&xmmsrc,&xmmdst,&xmmres); break;
                    xmmres.i = ssp_hsub_epi32_SSSE3 (xmmdst.i, xmmsrc.i); break;
                case 0x07: //phsubsw128(&xmmsrc,&xmmdst,&xmmres); break;
                    xmmres.i = ssp_hsubs_epi16_SSSE3 (xmmdst.i, xmmsrc.i); break;
                case 0x08: //psignb128(&xmmsrc,&xmmdst,&xmmres); break;
                    xmmres.i = ssp_sign_epi8_SSSE3 (xmmdst.i, xmmsrc.i); break;
                case 0x09: //psignw128(&xmmsrc,&xmmdst,&xmmres); break;
                    xmmres.i = ssp_sign_epi16_SSSE3 (xmmdst.i, xmmsrc.i); break;
                case 0x0A: //psignd128(&xmmsrc,&xmmdst,&xmmres); break;
                    xmmres.i = ssp_sign_epi32_SSSE3 (xmmdst.i, xmmsrc.i); break;
                case 0x0B: //pmulhrsw128(&xmmsrc,&xmmdst,&xmmres); break;
                    xmmres.i = ssp_mulhrs_epi16_SSSE3 (xmmdst.i, xmmsrc.i); break;
                case 0x0F: //palignr128(&xmmsrc,&xmmdst,&xmmres,imm); ins_size++; break;
                    xmmres.i = ssp_alignr_epi8_SSSE3 (xmmdst.i, xmmsrc.i, imm); ins_size++; break;
                case 0x1C: //pabsb128(&xmmsrc,&xmmres); break;
                    xmmres.i = ssp_abs_epi8_SSSE3 (xmmsrc.i); break;
                case 0x1D: //pabsw128(&xmmsrc,&xmmres); break;
                    xmmres.i = ssp_abs_epi16_SSSE3 (xmmsrc.i); break;
                case 0x1E: //pabsd128(&xmmsrc,&xmmres); break;
                    xmmres.i = ssp_abs_epi32_SSSE3 (xmmsrc.i); break;
                default: return 0;
            }

            storeresult128(*modrm, dst_higher, xmmres);
        }
        else
        {
            int consumed = fetchoperands(modrm, src_higher, dst_higher, &mmsrc, &mmdst, longmode, state, kernel_trap, 0, ins_size);

            ins_size += consumed;

            switch(opcode) {
                case 0x00: //pshufb64(&mmsrc,&mmdst,&mmres); break;
                    mmres.m64 = ssp_shuffle_pi8_SSSE3 (mmdst.m64, mmsrc.m64); break;
                case 0x01: //phaddw64(&mmsrc,&mmdst,&mmres); break;
                    mmres.m64 = ssp_hadd_pi16_SSSE3 (mmdst.m64, mmsrc.m64); break;
                case 0x02: //phaddd64(&mmsrc,&mmdst,&mmres); break;
                    mmres.m64 = ssp_hadd_pi32_SSSE3 (mmdst.m64, mmsrc.m64); break;
                case 0x03: //phaddsw64(&mmsrc,&mmdst,&mmres); break;
                    mmres.m64 = ssp_hadds_pi16_SSSE3 (mmdst.m64, mmsrc.m64); break;
                case 0x04: //pmaddubsw64(&mmsrc,&mmdst,&mmres); break;
                    mmres.m64 = ssp_maddubs_pi16_SSSE3 (mmdst.m64, mmsrc.m64); break;
                case 0x05: //phsubw64(&mmsrc,&mmdst,&mmres); break;
                    mmres.m64 = ssp_hsub_pi16_SSSE3 (mmdst.m64, mmsrc.m64); break;
                case 0x06: //phsubd64(&mmsrc,&mmdst,&mmres); break;
                    mmres.m64 = ssp_hsub_pi32_SSSE3 (mmdst.m64, mmsrc.m64); break;
                case 0x07: //phsubsw64(&mmsrc,&mmdst,&mmres); break;
                    mmres.m64 = ssp_hsubs_pi16_SSSE3 (mmdst.m64, mmsrc.m64); break;
                case 0x08: //psignb64(&mmsrc,&mmdst,&mmres); break;
                    mmres.m64 = ssp_sign_pi8_SSSE3 (mmdst.m64, mmsrc.m64); break;
                case 0x09: //psignw64(&mmsrc,&mmdst,&mmres); break;
                    mmres.m64 = ssp_sign_pi16_SSSE3 (mmdst.m64, mmsrc.m64); break;
                case 0x0A: //psignd64(&mmsrc,&mmdst,&mmres); break;
                    mmres.m64 = ssp_sign_pi32_SSSE3 (mmdst.m64, mmsrc.m64); break;
                case 0x0B: //pmulhrsw64(&mmsrc,&mmdst,&mmres); break;
                    mmres.m64 = ssp_mulhrs_pi16_SSSE3 (mmdst.m64, mmsrc.m64); break;
                case 0x0F: //palignr64(&mmsrc,&mmdst,&mmres, imm); ins_size++; break;
                    mmres.m64 = ssp_alignr_pi8_SSSE3 (mmdst.m64, mmsrc.m64, imm); ins_size++; break;
                case 0x1C: //pabsb64(&mmsrc,&mmres); break;
                    mmres.m64 = ssp_abs_pi8_SSSE3 (mmsrc.m64); break;
                case 0x1D: //pabsw64(&mmsrc,&mmres); break;
                    mmres.m64 = ssp_abs_pi16_SSSE3 (mmsrc.m64); break;
                case 0x1E: //pabsd64(&mmsrc,&mmres); break;
                    mmres.m64 = ssp_abs_pi32_SSSE3 (mmsrc.m64); break;
                default: return 0;
            }

            storeresult64(*modrm, dst_higher, mmres);
        }

    } else {
        // opcode wasn't handled here
        return 0;
    }

    return ins_size;
}

int fetchoperands(uint8_t *ModRM, unsigned int hsrc, unsigned int hdst, void *src, void *dst, unsigned int longmode, x86_saved_state_t *saved_state, int kernel_trap, int size_128, int  ins_size)
{
    unsigned int num_src = *ModRM & 0x7;
    unsigned int num_dst = (*ModRM >> 3) & 0x7;
    unsigned int mod = *ModRM >> 6;
    int consumed = 1; //modrm + 1 byte
    
    if(hsrc) num_src += 8;
    if(hdst) num_dst += 8;
    if(size_128) getxmm((ssp_m128*)dst, num_dst);
    else getmm((ssp_m64*)dst, num_dst);
    
    if(mod == 3)
    {
        if(size_128) getxmm((ssp_m128*)src, num_src);
        else getmm((ssp_m64*)src, num_src);
    }

    // AnV - Implemented 64-bit fetch
    else if ((longmode = is_saved_state64(saved_state)))
    {
        uint64_t address;
        // DST is always an XMM register. decode for SRC.
        x86_saved_state64_t *r64 = saved_state64(saved_state);
        __uint64_t reg_sel[8] = {r64->rax, r64->rcx, r64->rdx,
            r64->rbx, r64->isf.rsp, r64->rbp,
            r64->rsi, r64->rdi};

        if(hsrc) printf("opemu error: high reg ssse\n"); // FIXME

        if(num_src == 4)
        {
            // Special case: SIB byte used TODO fix r8-r15? 
            uint8_t scale = ModRM[1] >> 6;
            uint8_t base = ModRM[1] & 0x7;
            uint8_t index = (ModRM[1] >> 3) & 0x7;
            consumed++; //modrm mode 2
            
            // meaning of SIB depends on mod
            if(mod == 0)
            {
                if(base == 5) printf("opemu error: mod0 disp32 not implemented\n"); // FIXME
                if(index == 4) address = reg_sel[base];
                else address = reg_sel[base] + (reg_sel[index] * (1<<scale));
            }
            else
            {
                if(index == 4) address = reg_sel[base];
                else address = reg_sel[base] + (reg_sel[index] * (1<<scale));
            }
        }
        else
        {
            address = reg_sel[num_src];
        }
        
        if((mod == 0) && (num_src == 5))
        {
            // RIP-relative dword displacement
            // AnV - Warning from cast alignment fix
            __uint64_t ModRMVal = (__uint64_t)&ModRM[consumed];
            __int32_t *ModRMCast = (__int32_t *)ModRMVal;
            address = *(uint32_t*)&r64->isf.rip + *ModRMCast;
            consumed += 4;
            //printf("opemu adress rip: %llu \n",address);
        }

        if(mod == 1)
        {
            // byte displacement
            address +=(int8_t)ModRM[consumed];
            consumed++;
            //printf("opemu adress byte : %llu \n",address);
        }
        else if(mod ==2 )
        {
            // dword displacement. can it be qword?
            // AnV - Warning from cast alignment fix
            __uint64_t ModRMVal = (__uint64_t)&ModRM[consumed];
            __int32_t *ModRMCast = (__int32_t *)ModRMVal;
            address +=  *ModRMCast;
            consumed += 4;
            //printf("opemu adress byte : %llu \n",address);
        }
        
        // address is good now, do read and store operands.
        if(kernel_trap)
        {
            if(size_128) ((ssp_m128*)src)->ui = *(__uint128_t *)address;
            else ((ssp_m64*)src)->u64 = *(uint64_t *)address;
        }
        else
        {
            //printf("xnu: da = %llx, rsp=%llx,  rip=%llx\n", address, reg_sel[4], r64->isf.rip);
            if(size_128) copyin(address, (char*)& ((ssp_m128*)src)->ui, 16);
            else copyin(address, (char*)& ((ssp_m64*)src)->u64, 8);
        }
    }
    // AnV - Implemented 32-bit fetch
    else
    {
        uint32_t address;
        // DST is always an XMM register. decode for SRC.
        x86_saved_state32_t* r32 = saved_state32(saved_state);
        uint32_t reg_sel[8] = {r32->eax, r32->ecx, r32->edx,
            r32->ebx, r32->uesp, r32->ebp,
            r32->esi, r32->edi};

        if(hsrc) printf("opemu error: high reg ssse\n"); // FIXME

        if(num_src == 4)
        {
            /* Special case: SIB byte used TODO fix r8-r15? */
            uint8_t scale = ModRM[1] >> 6;
            uint8_t base = ModRM[1] & 0x7;
            uint8_t index = (ModRM[1] >> 3) & 0x7;
            consumed++;
            
            // meaning of SIB depends on mod
            if(mod == 0)
            {
                if(base == 5) printf("opemu error: mod0 disp32 not implemented\n"); // FIXME
                if(index == 4) address = reg_sel[base];
                else address = reg_sel[base] + (reg_sel[index] * (1<<scale));
            }
            else
            {
                if(index == 4) address = reg_sel[base];
                else address = reg_sel[base] + (reg_sel[index] * (1<<scale));
            }
        }
        else
        {
            address = reg_sel[num_src];
        }
        
        if((mod == 0) && (num_src == 5))
        {
            // RIP-relative dword displacement
            // AnV - Warning from cast alignment fix
            uint64_t ModRMVal = (uint64_t)&ModRM[consumed];
            int32_t *ModRMCast = (int32_t *)ModRMVal;
            address = r32->eip + *ModRMCast;
            consumed += 4;
            //address = r32->eip + *((int32_t*)&ModRM[consumed]);
        }

        if(mod == 1)
        {
            // byte displacement
            //int32_t mods = (int32_t)ModRM[consumed];
            //int8_t *Mods = (int8_t*)&mods;
            address += (int8_t)ModRM[consumed];
            consumed++;
            // printf("opemu adress byte : %llu \n",address);
        }
        else if(mod == 2)
        {
            // dword displacement. can it be qword?
            // AnV - Warning from cast alignment fix
            uint64_t ModRMVal = (uint64_t)&ModRM[consumed];
            int32_t *ModRMCast = (int32_t *)ModRMVal;
            address += *ModRMCast;
            consumed += 4;
            //address += *((int32_t*)&ModRM[consumed]);
        }
        
        // address is good now, do read and store operands.
        uint64_t addr = address;

        if(kernel_trap)
        {
            if(size_128) ((ssp_m128*)src)->ui = *(__uint128_t *)addr;
            else ((ssp_m64*)src)->u64 = *(uint64_t *)addr;
        }
        else
        {
            //printf("xnu: da = %llx, rsp=%llx,  rip=%llx\n", address, reg_sel[4], r32->eip);
            if(size_128) copyin(addr, (char*) &((ssp_m128*)src)->ui, 16);
            else copyin(addr, (char*) &((ssp_m64*)src)->u64, 8);
        }
    }
    return consumed;
}

void storeresult128(uint8_t ModRM, unsigned int hdst, ssp_m128 res)
{
    unsigned int num_dst = (ModRM >> 3) & 0x7;
    if(hdst) num_dst += 8;
    movxmm(&res, num_dst);
}
void storeresult64(uint8_t ModRM, unsigned int __unused hdst, ssp_m64 res)
{
    unsigned int num_dst = (ModRM >> 3) & 0x7;
    movmm(&res, num_dst);
}

/* get value from the xmm register i */
void getxmm(ssp_m128 *v, unsigned int i)
{
    switch(i) {
        case 0:
            asm __volatile__ ("movdqu %%xmm0, %0" : "=m" (*v->s8));
            break;
        case 1:
            asm __volatile__ ("movdqu %%xmm1, %0" : "=m" (*v->s8));
            break;
        case 2:
            asm __volatile__ ("movdqu %%xmm2, %0" : "=m" (*v->s8));
            break;
        case 3:
            asm __volatile__ ("movdqu %%xmm3, %0" : "=m" (*v->s8));
            break;
        case 4:
            asm __volatile__ ("movdqu %%xmm4, %0" : "=m" (*v->s8));
            break;
        case 5:
            asm __volatile__ ("movdqu %%xmm5, %0" : "=m" (*v->s8));
            break;
        case 6:
            asm __volatile__ ("movdqu %%xmm6, %0" : "=m" (*v->s8));
            break;
        case 7:
            asm __volatile__ ("movdqu %%xmm7, %0" : "=m" (*v->s8));
            break;
#ifdef __x86_64__
        case 8:
            asm __volatile__ ("movdqu %%xmm8, %0" : "=m" (*v->s8));
            break;
        case 9:
            asm __volatile__ ("movdqu %%xmm9, %0" : "=m" (*v->s8));
            break;
        case 10:
            asm __volatile__ ("movdqu %%xmm10, %0" : "=m" (*v->s8));
            break;
        case 11:
            asm __volatile__ ("movdqu %%xmm11, %0" : "=m" (*v->s8));
            break;
        case 12:
            asm __volatile__ ("movdqu %%xmm12, %0" : "=m" (*v->s8));
            break;
        case 13:
            asm __volatile__ ("movdqu %%xmm13, %0" : "=m" (*v->s8));
            break;
        case 14:
            asm __volatile__ ("movdqu %%xmm14, %0" : "=m" (*v->s8));
            break;
        case 15:
            asm __volatile__ ("movdqu %%xmm15, %0" : "=m" (*v->s8));
            break;
#endif
    }
}

/* get value from the mm register i  */
void getmm(ssp_m64 *v, unsigned int i)
{
    switch(i) {
        case 0:
            asm __volatile__ ("movq %%mm0, %0" : "=m" (*v->s8));
            break;
        case 1:
            asm __volatile__ ("movq %%mm1, %0" : "=m" (*v->s8));
            break;
        case 2:
            asm __volatile__ ("movq %%mm2, %0" : "=m" (*v->s8));
            break;
        case 3:
            asm __volatile__ ("movq %%mm3, %0" : "=m" (*v->s8));
            break;
        case 4:
            asm __volatile__ ("movq %%mm4, %0" : "=m" (*v->s8));
            break;
        case 5:
            asm __volatile__ ("movq %%mm5, %0" : "=m" (*v->s8));
            break;
        case 6:
            asm __volatile__ ("movq %%mm6, %0" : "=m" (*v->s8));
            break;
        case 7:
            asm __volatile__ ("movq %%mm7, %0" : "=m" (*v->s8));
            break;
    }
}

/* move value over to xmm register i */
void movxmm(ssp_m128 *v, unsigned int i)
{
    switch(i) {
        case 0:
            asm __volatile__ ("movdqu %0, %%xmm0" :: "m" (*v->s8) );
            break;
        case 1:
            asm __volatile__ ("movdqu %0, %%xmm1" :: "m" (*v->s8) );
            break;
        case 2:
            asm __volatile__ ("movdqu %0, %%xmm2" :: "m" (*v->s8) );
            break;
        case 3:
            asm __volatile__ ("movdqu %0, %%xmm3" :: "m" (*v->s8) );
            break;
        case 4:
            asm __volatile__ ("movdqu %0, %%xmm4" :: "m" (*v->s8) );
            break;
        case 5:
            asm __volatile__ ("movdqu %0, %%xmm5" :: "m" (*v->s8) );
            break;
        case 6:
            asm __volatile__ ("movdqu %0, %%xmm6" :: "m" (*v->s8) );
            break;
        case 7:
            asm __volatile__ ("movdqu %0, %%xmm7" :: "m" (*v->s8) );
            break;
#ifdef __x86_64__
        case 8:
            asm __volatile__ ("movdqu %0, %%xmm8" :: "m" (*v->s8) );
            break;
        case 9:
            asm __volatile__ ("movdqu %0, %%xmm9" :: "m" (*v->s8) );
            break;
        case 10:
            asm __volatile__ ("movdqu %0, %%xmm10" :: "m" (*v->s8) );
            break;
        case 11:
            asm __volatile__ ("movdqu %0, %%xmm11" :: "m" (*v->s8) );
            break;
        case 12:
            asm __volatile__ ("movdqu %0, %%xmm12" :: "m" (*v->s8) );
            break;
        case 13:
            asm __volatile__ ("movdqu %0, %%xmm13" :: "m" (*v->s8) );
            break;
        case 14:
            asm __volatile__ ("movdqu %0, %%xmm14" :: "m" (*v->s8) );
            break;
        case 15:
            asm __volatile__ ("movdqu %0, %%xmm15" :: "m" (*v->s8) );
            break;
#endif
    }
}

/* move value over to mm register i */
void movmm(ssp_m64 *v, unsigned int i)
{
    switch(i) {
        case 0:
            asm __volatile__ ("movq %0, %%mm0" :: "m" (*v->s8) );
            break;
        case 1:
            asm __volatile__ ("movq %0, %%mm1" :: "m" (*v->s8) );
            break;
        case 2:
            asm __volatile__ ("movq %0, %%mm2" :: "m" (*v->s8) );
            break;
        case 3:
            asm __volatile__ ("movq %0, %%mm3" :: "m" (*v->s8) );
            break;
        case 4:
            asm __volatile__ ("movq %0, %%mm4" :: "m" (*v->s8) );
            break;
        case 5:
            asm __volatile__ ("movq %0, %%mm5" :: "m" (*v->s8) );
            break;
        case 6:
            asm __volatile__ ("movq %0, %%mm6" :: "m" (*v->s8) );
            break;
        case 7:
            asm __volatile__ ("movq %0, %%mm7" :: "m" (*v->s8) );
            break;
    }
}

2015-1-31 21:43
0
雪    币: 320
活跃值: (104)
能力值: (RANK:180 )
在线值:
发帖
回帖
粉丝
6
THX 我知道了

ModRM >> 3 就是 ModRM 得值輸入計算機 >> 符號按3下
2015-1-31 21:58
0
雪    币: 468
活跃值: (52)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
这个思路好啊,这样也可以让老的amd cpu模拟执行sse3 指令集啊。
原理是不是这样,接管有一个cpu无效指令的中断号,接管这个中断号,当碰到无效指令的时候,去解析这个无效指令,解析为sse3指令的时候,去软件模拟执行这个sse3指令,然后恢复eip到下一条指令。
这样是不是也可以在x86上面模拟执行arm指令啊?
2015-2-1 09:12
0
雪    币: 209
活跃值: (143)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
谷歌自带的安卓模拟器就是这个原理,arm指令翻译为x86指令,巨卡
2015-2-1 09:32
0
雪    币: 23
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
要真发布这种东西,会影响很多小伙伴正常工作的,这种问题有时间私下聊吧。
2015-2-1 17:30
0
雪    币: 23
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
小看了下程序结构,因为sse3集本身指令非常非常少。这样做还可以,具体是哪个opcode出的问题,还要提供下线索,另外如果真完全模拟所有指令执行,这样swicth case肯定不行,要走image路线。
2015-2-1 17:33
0
雪    币: 23
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
肯定卡,opcode本身执行,和模拟执行相差的性能,成百倍级的增加。这种东西只能用来调试,不能做为最终方案,再说现在随便一个i5 i7都可以执行sse4,amd最新的也可以执行到sse5了
2015-2-1 17:36
0
雪    币: 320
活跃值: (104)
能力值: (RANK:180 )
在线值:
发帖
回帖
粉丝
12
我重新改寫這個函數 但是我不知道這樣改是不是正確的

我按照我再 IDA Pro 上看到的opcode 為準

這個我有疑問的是 mod 0 - 2 計算 Pointer address 是不是正確的

例如:
                //0  1  2  3  4  5  6  7  8
                //66 0F 38 01 05 01 02 03 04
                //phaddw  xmm0, xmmword ptr [cs:04030201h]


offset + 6 的四個byte(字節) 是指標(指針) 的位址(地址)

兩種寫法哪個正確

1.
consumed++;
__uint64_t ModRMVal = (__uint64_t)&ModRM[consumed];
__int32_t *ModRMCast = (__int32_t *)ModRMVal;
address = *(uint32_t*)&r64->isf.rip + *ModRMCast;
consumed += 3;

2.
consumed++;
address = (uint32_t)ModRM[consumed];
consumed += 3;

最後 address 的數值是 kernel_trap 裡面的 address

        if(kernel_trap)
        {
            if(size_128) ((ssp_m128*)src)->ui = *(__uint128_t *)address;
            else ((ssp_m64*)src)->u64 = *(uint64_t *)address;
        }
        else
        {
            //printf("xnu: da = %llx, rsp=%llx,  rip=%llx\n", address, reg_sel[4], r64->isf.rip);
            if(size_128) copyin(address, (char*)& ((ssp_m128*)src)->ui, 16);
            else copyin(address, (char*)& ((ssp_m64*)src)->u64, 8);
        }


64-bit mode
int operands(uint8_t *ModRM, uint8_t hsrc, uint8_t hdst, void *src, void *dst, unsigned int longmode, x86_saved_state_t *saved_state, int kernel_trap, int size_128, int  ins_size)
{
    unsigned char num_src = *ModRM & 0x7; // 1 byte + 1
    unsigned char num_dst = (*ModRM >> 3) & 0x7; //8 byte + 1
    unsigned char mod = *ModRM >> 6; // 40 byte + 1
    int consumed = 1; //modrm + 1 byte

    if(hsrc) num_src += 8;
    if(hdst) num_dst += 8;

    if(size_128)
        getxmm((ssp_m128*)dst, num_dst);
    else
        getmm((ssp_m64*)dst, num_dst);

    if(mod == 3)
    {
        if(size_128)
            getxmm((ssp_m128*)src, num_src);
        else
            getmm((ssp_m64*)src, num_src);
    }

    // AnV - Implemented 64-bit fetch
    else if ((longmode = is_saved_state64(saved_state)))
    {
        uint64_t address;
        // DST is always an XMM register. decode for SRC.
        x86_saved_state64_t *r64 = saved_state64(saved_state);
        __uint64_t reg_sel[8] = {r64->rax, r64->rcx, r64->rdx,
            r64->rbx, r64->isf.rsp, r64->rbp,
            r64->rsi, r64->rdi};

        if(hsrc) printf("opemu error: high reg ssse\n"); // FIXME
        

        if (mod == 0)
        {
            if (num_src == 4)
            {
                uint8_t scale = ModRM[1] >> 6; //40 byte + 1
                uint8_t base = ModRM[1] & 0x7; //1 byte + 1 reg loop
                uint8_t index = (ModRM[1] >> 3) & 0x7; //8 byte + 1 reg loop

                if(base == 5)
                {
                    consumed += 2;
                    //modrm[1] = byte[5]
                    //0  1  2  3  4  5  6  7  8  9
                    //66 0F 38 01 04 05 04 03 02 01
                    //phaddw     xmm0, xmmword [ds:0x1020304+rax]
                    //__uint64_t ModRMVal = (__uint64_t)&ModRM[consumed];
                    //__int32_t *ModRMCast = (__int32_t *)ModRMVal;
                    //address = /* *(uint32_t*)&r64->isf.rip + */ *ModRMCast + reg_sel[index];
                    address = (uint32_t)ModRM[consumed] + reg_sel[index];
                    consumed += 3;
                }
                else
                {
                    if (index == 4)
                    {
                        //0  1  2  3  4  5
                        //66 0F 38 01 04 61
                        //phaddw     xmm0, xmmword [ds:rcx]
                        address = reg_sel[base];
                        consumed++;
                    }
                    else
                    {
                        //0  1  2  3  4  5
                        //66 0F 38 01 04 44
                        //phaddw  xmm0, xmmword ptr [rsp+rax*2]
                        address = reg_sel[base] + (reg_sel[index] * (1<<scale));
                        consumed++;
                    }
                }
            }
            else if (num_src == 5)
            {
                consumed++;
                //0  1  2  3  4  5  6  7  8
                //66 0F 38 01 05 01 02 03 04
                //phaddw  xmm0, xmmword ptr [cs:04030201h]
                __uint64_t ModRMVal = (__uint64_t)&ModRM[consumed];
                __int32_t *ModRMCast = (__int32_t *)ModRMVal;
                address = *(uint32_t*)&r64->isf.rip + *ModRMCast;
                //address = (uint32_t)ModRM[consumed];
                consumed += 3;
            }
            else
            {
                //0  1  2  3  4
                //66 0F 38 01 03
                //phaddw     xmm0, xmmword [ds:rbx]
                address = reg_sel[num_src];
            }
        }

        if (mod == 1)
        {
            if(num_src == 4)
            {
                uint8_t scale = ModRM[1] >> 6; //40 byte + 1
                uint8_t base = ModRM[1] & 0x7; //1 byte + 1 reg loop
                uint8_t index = (ModRM[1] >> 3) & 0x7; //8 byte + 1 reg loop

                if (index == 4)
                {
                    //0  1  2  3  4  5  6
                    //66 0F 38 01 44 27 80
                    //phaddw  xmm0, xmmword ptr [rdi-80h]
                    consumed+= 2;
                    address = reg_sel[base] + (int8_t)ModRM[consumed];
                }
                else
                {
                    //0  1  2  3  4  5  6
                    //66 0F 38 01 44 44 80
                    //phaddw  xmm0, xmmword ptr [rsp+rax*2-80h]
                    consumed+= 2;
                    address = reg_sel[base] + (reg_sel[index] * (1<<scale)) + (int8_t)ModRM[consumed];
                }
            }
            else
            {
                //0  1  2  3  4  5
                //66 0F 38 01 43 01
                //phaddw  xmm0, xmmword [ds:rbx+0x1]
                consumed++;
                address = reg_sel[num_src] + (int8_t)ModRM[consumed];
            }
        }

        if (mod == 2)
        {
            if(num_src == 4)
            {
                uint8_t scale = ModRM[1] >> 6; //40 byte + 1
                uint8_t base = ModRM[1] & 0x7; //1 byte + 1 reg loop
                uint8_t index = (ModRM[1] >> 3) & 0x7; //8 byte + 1 reg loop

                if (index == 4)
                {
                    //0  1  2  3  4  5  6  7  8  9
                    //66 0F 38 01 84 20 04 03 02 01
                    //phaddw  xmm0, xmmword ptr [rax+1020304h]
                    consumed += 2;
                    address = reg_sel[base] + (uint32_t)ModRM[consumed];
                    consumed += 3;
                }
                else
                {
                    //0  1  2  3  4  5  6  7  8  9
                    //66 0F 38 01 84 44 04 03 02 01
                    //phaddw  xmm0, xmmword ptr [rsp+rax*2+1020304h]
                    consumed += 2;
                    //__uint64_t ModRMVal = (__uint64_t)&ModRM[consumed];
                    //__int32_t *ModRMCast = (__int32_t *)ModRMVal;
                    //address = reg_sel[base] + (reg_sel[index] * (1<<scale)) + /* *(uint32_t*)&r64->isf.rip + */ *ModRMCast;
                    address = reg_sel[base] + (reg_sel[index] * (1<<scale)) + (uint32_t)ModRM[consumed];
                    consumed += 3;
                }

            }
            else
            {
                //0  1  2  3  4  5  6  7  8
                //66 0F 38 01 83 01 02 03 04
                //phaddw     xmm0, xmmword [ds:rbx+0x4030201]
                consumed++;
                //__uint64_t ModRMVal = (__uint64_t)&ModRM[consumed];
                //__int32_t *ModRMCast = (__int32_t *)ModRMVal;
                //address = reg_sel[num_src] + /* *(uint32_t*)&r64->isf.rip + */ *ModRMCast;
                address = reg_sel[num_src] + (uint32_t)ModRM[consumed];
                consumed += 3;
            }
        }

        // address is good now, do read and store operands.
        if(kernel_trap)
        {
            if(size_128) ((ssp_m128*)src)->ui = *(__uint128_t *)address;
            else ((ssp_m64*)src)->u64 = *(uint64_t *)address;
        }
        else
        {
            //printf("xnu: da = %llx, rsp=%llx,  rip=%llx\n", address, reg_sel[4], r64->isf.rip);
            if(size_128) copyin(address, (char*)& ((ssp_m128*)src)->ui, 16);
            else copyin(address, (char*)& ((ssp_m64*)src)->u64, 8);
        }
    }
    return consumed;
}

2015-2-2 14:49
0
雪    币: 7048
活跃值: (3527)
能力值: ( LV12,RANK:340 )
在线值:
发帖
回帖
粉丝
13
不明白你说的什么意思,我对x86指令结构不了解,也不好回答,
你可以参考下开源的反汇编引擎是怎么解码x86指令的,例如:udis86.
2015-2-2 16:02
0
雪    币: 23
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
//0  1  2  3  4  5  6  7  8
   //66 0F 38 01 05 01 02 03 04
   //phaddw  xmm0, xmmword ptr [cs:04030201h]
66 = 宽度调整
0f 38 = 三字节前缀
01 = Opcode
05 = mod=00,rm=05=displace32
01 02 03 04 = displace = 因尾端调整 = [04030201h]
还是那句话,强烈建议看intel手册或amd手册,另外开源反编译引挚,最多解到sse1就算不错了,而且错误非常多,想做个像od那样的反汇引挚,只有照着手册来
另外这里不存在offset的问题,因为是直接地址寻址。无偏移量。
2015-2-2 16:20
0
雪    币: 320
活跃值: (104)
能力值: (RANK:180 )
在线值:
发帖
回帖
粉丝
15
[QUOTE=dppdpp;1351130]//0  1  2  3  4  5  6  7  8
   //66 0F 38 01 05 01 02 03 04
   //phaddw  xmm0, xmmword ptr [cs:04030201h]
66 = 宽度调整
0f 38 = 三字节前缀
01 = Opcode
05...[/QUOTE]

我說的是 語法正不正確 取後面4byte 當addr

像這樣 uint32_t
address = (uint32_t)ModRM[consumed];

還是
uint64_t 或是 __uint64_t

uint32_t 是 4個byte 對嗎

但是64bit模式 addr 好像都是8個byte  例如 0x0000000004030201

但是如果這樣
address = (uint64_t)ModRM[consumed];

address 會不會多取後面4個byte 變成 0x0?0?0?0?04030201

我知道要看手冊啊

但我現在看到的是

編譯後的二進制文件 裡面有指令集的操作代碼

例如 某二進制文件裡面的opcode
000000000001dd36         pmulhrsw   xmm4, xmmword [ds:0x23270]
在0x000000000001dd36h 有這個指令 pmulhrsw   xmm4, xmmword [ds:0x23270]
如果你的CPU不支援這個指令集
那kernel 就會返回錯誤操作代碼 app會異常或退出

所以變成 app -> CPU 指令不支援 -> 錯誤

這個addr 是取二進制文件裡面的opcode
例如在該指令 pmulhrsw   xmm4, xmmword [ds:0x04030201] 最後面四個字節
2015-2-2 16:53
0
雪    币: 23
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
address = (uint64_t)ModRM[consumed];
这种语法肯定是64位的取值,但正确与否要看你的地址空间,是32位,还是64位,如果是32这种表述无关紧要,多了几个零而已,如果64位,要向后再取四个byte的数值。
另外你说的cpu指令集不支持问题,大部份是cpu型号问题,跟操作系统关系不大,你取下cpuid去查查看是否支持指令集。
另外如果你要模拟运行,要写出模拟的结果就可以了,我的意思是,干什么跟一个这么老旧的cpu过不去,搞个新cpu不就问题解决了。
再另外x64的解码与x86又不一样的,他有一个rex prefix段,具体的看手册。
再另外000000000001dd36         pmulhrsw   xmm4, xmmword [ds:0x23270]这个编码,我没看懂。能讲一下是怎么编码的吗?
2015-2-2 17:58
0
雪    币: 225
活跃值: (349)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
这里就是正解
2015-2-2 18:48
0
雪    币: 320
活跃值: (104)
能力值: (RANK:180 )
在线值:
发帖
回帖
粉丝
18
[QUOTE=dppdpp;1351158]address = (uint64_t)ModRM[consumed];
这种语法肯定是64位的取值,但正确与否要看你的地址空间,是32位,还是64位,如果是32这种表述无关紧要,多了几个零而已,如果64位,要向后再取四个byte的数值。
另外你说的cpu指令集不支持问题,大部份是cpu型号问题...[/QUOTE]

pmulhrsw   xmm4, xmmword [ds:0x23270]

這個是用Debuger 打開二進制文件 看到的opcode

指標(指針)是 0x23270

xmmword 我不知道是幾位 我知道 dword 是 4-byte

那假設 xmm4, xmmword [rax+0x23270]

如果 rax=2

那就是 2+23270 = 23272

指標 addr = 0x23272

pmulhrsw 的性質我不知道 我最近剛摸索這東西

應該是 指標addr的值 長度xmmword 用pmulhrsw的方式 移到 xmm4 吧

我知道 mov eax ,dword ptr[0x00401000]
是把指標 addr 0x00401000 的值 長度4-byte 移到 eax

EAX <- ptr[0x00401000] dword

假設 00401000 的值是 ffffffff

那就是 把 ffffffff 移到eax

你看到的 000000000001dd36 這個是addr
在 000000000001dd36 上的opcode pmulhrsw   xmm4, xmmword [ds:0x23270]

看圖你應該明白吧

編譯後的二進制文件裡面的操作代碼都是這樣的
SSE指令集 Opcode 長度 幾byte 用Debuger看都是絕對值 沒有例外

2015-2-2 20:38
0
雪    币: 23
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
还是图清楚些,明白了,我纳闷000000000001dd36是啥玩意呢,呵呵,原来是地址,你先别考虑64位的问题,先把x86搞清楚些,dword ptr 是代表4byte,32位宽。很开心碰上你啊,现在喜欢研究代码本质的人,很少了。有啥不清楚的,你就在这贴里问好了,我一定知无不言,言无不尽。另外你没必要纠结cpu支持代码集的问题,模拟opcode这个思路基本没用,除非跨平台,像前面有个兄弟说的把 arm放x86运行,需要模拟,单纯的为了支持老cpu没必要,换一块好点cpu就行了。

再另外,如果你理解不了x86全部的技术细节,马上看x64就像物理学,刚学会三定律,要理解多维度宇宙一样难。
再另外,x86=二维空间,sse系列=三维空间,x64=四维空间,avx=n维空间
再另外,66 0F 38 01 05 01 02 03 04没有rex prefix所以这条序列是一个32位序列,它没有进入x64扩展
再另外,xmmword=128,ymmword=256
其他理解全正确。
2015-2-2 23:26
0
雪    币: 320
活跃值: (104)
能力值: (RANK:180 )
在线值:
发帖
回帖
粉丝
20
SSSE3 模擬器我是用在mac上的

Mac OS X 10.6 - 目前10.10 系統運行指令集需求 MMX SSE SSE2 SSE3 SSSE3
在AMD K8 K10 都具備 MMX - SSE3 但惟獨缺少 SSSE3
K10 FX 跟最新的APU 就全系列支援了 還有SSE4x 跟 AVX
我當然知道換CPU 就好了 但是我還是希望可以完成這個模擬器
如果成功 那大概也可以應用到每個平台
Windows 核心除外 因為 微軟沒有開放核心的源碼 MS 下大概只能用在APP
------------------------

我現在還有一個問題

例如這個SSSE3 指令 phaddw
在MSDN 上模擬的資料
https://msdn.microsoft.com/en-us/library/bb514103.aspx
我們已經知道
__m128i A = (*ModRM >> 3) & 0x7
__m128i B = *ModRM & 0x7

那換成這個指令
https://msdn.microsoft.com/en-us/library/bb531427.aspx
__m128i A = (*ModRM >> 3) & 0x7
__m128i mask

Mask 得值是怎麼來的 該怎麼求MASK ???

THX
2015-2-3 07:33
0
雪    币: 23
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
_mm_shuffle_epi8是phaddw的c++接口,不用管原理,直接给参数用就行,但模拟器肯定不行,因为指令集不支持,编译后还是phaddw的编码,模拟器需要自己写出,每个opcode的伪实现型式。需要用opcode方式实现,汇编不行。最后还要转为c++接口形式,不转也没事,直接调用,写好call和ret就可以了
2015-2-3 11:28
0
雪    币: 320
活跃值: (104)
能力值: (RANK:180 )
在线值:
发帖
回帖
粉丝
22
hi dppdpp 大 我有看 intel 手冊了 但我之前下載到的是2003版
內容只到SSE2
昨天我找到2015 版 稍微翻一下 有些不太懂
rex 前綴是指像 SSSE3 這類前綴有0x66開頭的指令嗎

SSSE3 分為兩種模式

例如 PHADDD
66 0f 38 02 <<< 這個 66 開頭是 m128 類型 使用xmm 暫存器
如果是 0f 38 02 <<< 這個沒有66前綴 是 m64 類型使用 mm 暫存器

現在我不清楚的有2點

暫存器用到 xmm0 - 15 的是只要在64bit OS 的環境下都是 xmm 0-15嗎
還是 32 bit OS 也有用 xmm 0-15

mm 暫存器 在64-bit OS平台 也使用mm0-15嗎

還是只要是 66 前綴開頭的 就是使用 xmm0 - 15

或者是說 m128 使用 xmm8-15
m64 使用mm0-8

另外 SIB 模式 是64 bit 才有 還是只要是前綴66就有

32 bit OS 平台有 SIB 模式嗎
2015-2-6 06:13
0
雪    币: 23
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
rex是x64结构里特有的。有w,x,b,r四个子域,具体的查下手册都是做什么的,一点点说,估计能写几屏,内容实在太多了,另外prefix 66不是在每个指令里都有用的,具体哪些指令有作用,又是如何扩展的,都要去查手册。2A Section 里每一条指令都有详细的说明。
SIB是从x86开始就有的作用域,除了x8616位模式无作用外,直到avx集全部有用,也可以说是intel当初为了扩展32位相对寻址模式时用的方案。modrm域和sib域构成了一个完整的x86寻址体系。

mm寄存器?你是不是说mmx寄存器?mmx寄存器是64位多媒体寄存器。
2015-2-6 10:37
0
雪    币: 320
活跃值: (104)
能力值: (RANK:180 )
在线值:
发帖
回帖
粉丝
24
Intel 描述太雜了 我現在只針對 SSSE3 跟 SSE3 就好了

那 dppdpp大 可以幫我看一下 我現在理解的 MODRM 跟 SIB 尋址模式對不對

是不是有遺漏的尋址模式??

ModRM / SIB 尋址模式

4=ESP/RSP
5=EBP/RBP

一般尋址模式
mod 00b
    address = R/M REG

mod 01b
    address = R/M REG + DISP8 OFFSET

mod 10b
    address = R/M REG + DISP32 OFFSET



SIB 模式 R/M = 04 RSP/ESP
mod 00b
  base = 5 & index = 4
    address = DISP32 OFFSET
  base = 5
    address = DISP32 OFFSET + (INDEX REG * SCALE)

  index = 4 不是 base = 5
    address = BASE REG

  index = 4 base = 5 都不是
    address = BASE REG + (INDEX REG * SCALE)

mod 01b
  index = 4
    address = BASE REG + DISP8 OFFSET
  不是 index = 4
    address = BASE REG + (INDEX REG * SCALE) + DISP8 OFFSET

mod 10b
  index = 4
    address = BASE REG + DISP32 OFFSET
  不是 index = 4
    address = BASE REG + (INDEX REG * SCALE) + DISP32 OFFSET


特殊模式 R/M = 05 EBP/RBP
mod 00b
  R/M REG = 5 
    address = DISP32 OFFSET


括弧內的值 (INDEX REG * SCALE)

SIB scale 域 00b 的時候 是 (index * 1)
SIB scale 域 01b 的時候 是 (index * 2)
SIB scale 域 10b 的時候 是 (index * 4)
SIB scale 域 11b 的時候 是 (index * 8)

的值 這個好像有問題 的到的是 0 1 2 3
uint8_t scale = ModRM[1] >> 6;

在 C++ 我用 (index * (1 <<scale))
這樣寫正確嗎

附件是我修改的模擬器源碼
上传的附件:
2015-2-7 14:08
0
雪    币: 23
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
还是那个老问题,没搞明白x86就直接上sse了,这样不行,给你个原来我参考过的资料,大神博客上的整理,http://blog.csdn.net/xfcyhuang/article/details/6236042
2015-2-7 18:51
0
游客
登录 | 注册 方可回帖
返回
//