rendered paste body// No 16 bit addressing because it's a pain and obsolete.// Segment selection unfortunately isn't obsolete, but it's still a pain.#include <assert.h>typedef unsigned char u8;typedef unsigned short u16;typedef unsigned long u32;typedef unsigned long long u64;typedef char s8;typedef short s16;typedef long s32;typedef long long s64;#define TLS __declspec(thread)#define OPNAME(op) x##op#define OP1(op, b1) struct x86##op : b1 { using b1::operator(); }; \ const x86##op OPNAME(op);#define OP2(op, b1, b2) struct x86##op : b1, b2 { \ using b1::operator(); using b2::operator(); }; \ const x86##op OPNAME(op);#include <stdio.h>// internals all prefixed with x86 because I'm paranoid like thatnamespace X86 { TLS u8 *x86Ptr; struct x86Reg { int type; int n; inline bool operator==(const x86Reg& reg) const { return type == reg.type && n == reg.n; } }; const int x86RegWidth[6] = {8, 16, 32, 64, 64, 128}; const x86Reg x86NoReg = {-1, -1}; const x86Reg al = {0, 0}, cl = {0, 1}, dl = {0, 2}, bl = {0, 3}, ah = {0, 4}, ch = {0, 5}, dh = {0, 6}, bh = {0, 7}; const x86Reg ax = {1, 0}, cx = {1, 1}, dx = {1, 2}, bx = {1, 3}, sp = {1, 4}, bp = {1, 5}, si = {1, 6}, di = {1, 7}; const x86Reg eax = {2, 0}, ecx = {2, 1}, edx = {2, 2}, ebx = {2, 3}, esp = {2, 4}, ebp = {2, 5}, esi = {2, 6}, edi = {2, 7}; const x86Reg rax = {3, 0}, rcx = {3, 1}, rdx = {3, 2}, rbx = {3, 3}, rsp = {3, 4}, rbp = {3, 5}, rsi = {3, 6}, rdi = {3, 7}, r8 = {3, 8}, r9 = {3, 9}, r10 = {3, 10}, r11 = {3, 11}, r12 = {3, 12}, r13 = {3, 13}, r14 = {3, 14}, r15 = {3, 15}; const x86Reg st0 = {4, 0}, st1 = {4, 1}, st2 = {4, 2}, st3 = {4, 3}, st4 = {4, 4}, st5 = {4, 5}, st6 = {4, 6}, st7 = {4, 7}; const x86Reg mm0 = {4, 0}, mm1 = {4, 1}, mm2 = {4, 2}, mm3 = {4, 3}, mm4 = {4, 4}, mm5 = {4, 5}, mm6 = {4, 6}, mm7 = {4, 7}; const x86Reg xmm0 = {5, 0}, xmm1 = {5, 1}, xmm2 = {5, 2}, xmm3 = {5, 3}, xmm4 = {5, 4}, xmm5 = {5, 5}, xmm6 = {5, 6}, xmm7 = {5, 7}; // an intermediate class converted to an effective address with *ptr[] struct x86RegMaths { x86Reg base; x86Reg index; int scale; s32 disp; };}inline const X86::x86RegMaths operator*(const X86::x86Reg &r, int s){ const X86::x86RegMaths ret = {X86::x86NoReg, r, s, 0}; return ret;}inline const X86::x86RegMaths operator+(const X86::x86Reg &r, s32 disp){ const X86::x86RegMaths ret = {r, X86::x86NoReg, 0, disp}; return ret;}inline const X86::x86RegMaths operator+(const X86::x86RegMaths &rm, s32 disp){ const X86::x86RegMaths ret = {rm.base, rm.index, rm.scale, rm.disp + disp}; return ret;}inline const X86::x86RegMaths operator+(const X86::x86RegMaths &rm, const X86::x86Reg &r){ if (rm.base == X86::x86NoReg) { const X86::x86RegMaths ret = {r, rm.index, rm.scale, rm.disp}; return ret; } else if (r == rm.base && rm.index == X86::x86NoReg) { const X86::x86RegMaths ret = {X86::x86NoReg, r, 2, rm.disp}; return ret; }}namespace X86 { struct x86EAddr { int width; struct x86RegMaths rm; }; template<int width> class x86EAddrFactory { x86EAddr operator[](const x86RegMaths &rm) { const x86EAddr ret = {width, {rm.base, rm.index, rm.scale, rm.disp}}; return ret; } x86EAddr operator[](const x86Reg ®) { const x86EAddr ret = {width, {reg, x86NoReg, 0, 0}}; return ret; } template<typename T> x86EAddr operator[](T *p) { const x86EAddr ret = {width, {x86NoReg, x86NoReg, 0, (s32)p}}; return ret; } }; x86EAddrFactory<0> ptr; x86EAddrFactory<8> ptr8, byteptr; x86EAddrFactory<16> ptr16, wordptr; x86EAddrFactory<32> ptr32, dwordptr; x86EAddrFactory<64> ptr64, qwordptr, mmwordptr; x86EAddrFactory<128> ptr128, xmmwordptr; void x86Write8(u8 b) { *x86Ptr++ = b; } void x86Write16(u16 w) { *(u16*)x86Ptr = w; x86Ptr += 2; } void x86Write32(u32 dw) { *(u32*)x86Ptr = dw; x86Ptr += 4; } void x86Write64(u64 qw) { *(u64*)x86Ptr = qw; x86Ptr += 8; } // Left to right opcode helper for readability void x86WriteOp(u32 opcode) { if (opcode >> 24) x86Write32(opcode); else { if (opcode >> 16) x86Write8((opcode >> 16) & 0xffU); if (opcode >> 8) x86Write8((opcode >> 8) & 0xffU); x86Write8(opcode & 0xffU); } } void x86WriteModRM(x86Reg rm, int reg) { /* TODO */ } void x86WriteModRM(x86EAddr rm, int reg) { /* TODO */ } template<u32 opcode> struct x86Naked { void operator()() const { x86WriteOp(opcode); } }; template<u32 opcode> struct x86Imm8 { void operator()(u8 ib) const { x86WriteOp(opcode); x86Write8(ib); } }; template<u32 opcode> struct x86Imm16 { void operator()(u16 iw) const { x86WriteOp(opcode); x86Write16(iw); } }; template<u32 opcode, u8 reg, u32 opA> struct x86Rm_ImmSW { void operator()(x86EAddr x, s32 y) const { int signext = (s8)(u8)y == y; if (EAX == x) { x86WriteOp(opA | signext); x86WriteModRM(x, reg); } else { x86WriteOp(opcode | signext); x86WriteModRM(x, reg); } if (signext) x86Write8((u8)y); else x86Write32((u32)y); } }; template<u32 opcode> struct x86Rm_RmW { private: __forceinline void write(const x86Reg &rm, const x86Reg ®, int w, int dir) const { x86WriteOp(opcode | (w >= 16 ? 1 : 0) | (dir ? 2 : 0)); } __forceinline void write(const x86EAddr &rm, const x86Reg ®, int w, int dir) const { x86WriteOp(opcode | (w >= 16 ? 1 : 0) | (dir ? 2 : 0)); } public: __forceinline void operator()(const x86Reg &x, const x86Reg &y) const { assert(x.type == y.type); write(x, y, x86RegWidth[x.type], 0); } __forceinline void operator()(const x86EAddr &x, const x86Reg &y) const { assert(x86RegWidth[y.type] == x.width); write(x, y, x.width, 0); } template<int w> __forceinline void operator()(const x86Reg &x, const x86EAddr &y) const { assert(x86RegWidth[x.type] == y.width); write(y, x, y.width, 1); } };// ugh#define _ , namespace X86_32 { OP1(AAA, x86Naked<0x37>); OP2(AAD, x86Naked<0xD50A>, x86Imm8<0xD5>); OP2(AAM, x86Naked<0xD40A>, x86Imm8<0xD4>); OP1(AAS, x86Naked<0x3F>); }; namespace X86_3264 { OP2(RET, x86Naked<0xC3>, x86Imm16<0xC2>); OP2(RETF, x86Naked<0xCB>, x86Imm16<0xCA>); OP2(ADC, x86Rm_ImmSW<0x80 _ 2 _ 0x14>, x86Rm_RmW<0x10>); }; // import after X86_3264 namespace X86_64 { // OP2(ADC };#undef _};using namespace X86;using namespace X86::X86_3264;using namespace X86::X86_32;using namespace X86::X86_64;#include <stdlib.h>#include <stdio.h>int main(){ u8* buf = static_cast<u8*>(malloc(0x40000)); x86Ptr = buf; xRET(); xAAA(); xAAD(); xAAD(16); xAAM(); xAAM(16); xAAS(); xADC(eax, edx); xADC(dwordptr[buf], eax); xRET(); xRET(16); xRETF(); xRETF(20); ((void(*)())buf)(); return 0;}