From bf62c0660b97314e2b014d3a1eae859750528674 Mon Sep 17 00:00:00 2001 From: MITSUNARI Shigeo Date: Sun, 20 Nov 2016 19:46:35 +0900 Subject: [PATCH] add [rip + pointer] addressing --- readme.md | 17 +++++++++++- readme.txt | 3 +- test/jmp.cpp | 40 +++++++++++++++++++++++++++ xbyak/xbyak.h | 31 +++++++++++++++------ xbyak/xbyak_mnemonic.h | 62 +++++++++++++++++++++--------------------- 5 files changed, 111 insertions(+), 42 deletions(-) diff --git a/readme.md b/readme.md index 5d0e582..72e78f0 100644 --- a/readme.md +++ b/readme.md @@ -1,5 +1,5 @@ -Xbyak 5.03 ; JIT assembler for x86(IA32), x64(AMD64, x86-64) by C++ +Xbyak 5.10 ; JIT assembler for x86(IA32), x64(AMD64, x86-64) by C++ ============= Abstract @@ -220,6 +220,20 @@ The above jmp opecode jumps label1. * srcLabel must be used in L(). * dstLabel must not be used in L(). +### Rip +``` +Label label; +mov(eax, ptr [rip + label]); // eax = 4 +... + +L(label); +dd(4); +``` +``` +int x; +... + mov(eax, ptr[rip + &x]); // throw exception if the difference between &x and current position is larger than 2GiB +``` ### Code size The default max code size is 4096 bytes. Please set it in constructor of CodeGenerator() if you want to use large size. @@ -309,6 +323,7 @@ The header files under xbyak/ are independent of cybozulib. History ------------- +* 2016/Nov/20 ver 5.10 add addressing [rip+&var] * 2016/Sep/29 ver 5.03 fix detection ERR_INVALID_OPMASK_WITH_MEMORY(thanks to PVS-Studio) * 2016/Aug/15 ver 5.02 xbyak does not include xbyak_bin2hex.h * 2016/Aug/15 ver 5.011 fix detection of version of gcc 5.4 diff --git a/readme.txt b/readme.txt index 29db30d..6773150 100644 --- a/readme.txt +++ b/readme.txt @@ -1,5 +1,5 @@ - C++用x86(IA-32), x64(AMD64, x86-64) JITアセンブラ Xbyak 5.03 + C++用x86(IA-32), x64(AMD64, x86-64) JITアセンブラ Xbyak 5.10 ----------------------------------------------------------------------------- ◎概要 @@ -333,6 +333,7 @@ cybozulibは単体テストでのみ利用されていて、xbyak/ディレク ----------------------------------------------------------------------------- ◎履歴 +2016/11/20 ver 5.10 [rip+&var]の形のアドレッシング追加 2016/09/29 ver 5.03 ERR_INVALID_OPMASK_WITH_MEMORYの判定ミス修正(thanks to PVS-Studio) 2016/08/15 ver 5.02 xbyak_bin2hex.hをincludeしない 2016/08/15 ver 5.011 gcc 5.4のバージョン取得ミスの修正 diff --git a/test/jmp.cpp b/test/jmp.cpp index e15f634..eab97fc 100644 --- a/test/jmp.cpp +++ b/test/jmp.cpp @@ -1025,4 +1025,44 @@ CYBOZU_TEST_AUTO(rip_jmp) int ret = code.getCode()(); CYBOZU_TEST_EQUAL(ret, ret1234() + ret9999()); } + +#ifdef XBYAK64_GCC +CYBOZU_TEST_AUTO(rip_addr) +{ + /* + assume |&x - &code| < 2GiB + */ + static int x = 5; + struct Code : Xbyak::CodeGenerator { + Code() + { + mov(eax, 123); + mov(ptr[rip + &x], eax); + ret(); + } + } code; + code.getCode()(); + CYBOZU_TEST_EQUAL(x, 123); +} +#endif +CYBOZU_TEST_AUTO(rip_addr_with_fixed_buf) +{ + MIE_ALIGN(4096) static char buf[8192]; + static char *p = buf + 4096; + static int *x0 = (int*)buf; + static int *x1 = x0 + 1; + struct Code : Xbyak::CodeGenerator { + Code() : Xbyak::CodeGenerator(4096, p) + { + mov(eax, 123); + mov(ptr[rip + x0], eax); + mov(dword[rip + x1], 456); + ret(); + } + } code; + Xbyak::CodeArray::protect(p, 4096, true); + code.getCode()(); + CYBOZU_TEST_EQUAL(*x0, 123); + CYBOZU_TEST_EQUAL(*x1, 456); +} #endif diff --git a/xbyak/xbyak.h b/xbyak/xbyak.h index b1a40cd..ffae219 100644 --- a/xbyak/xbyak.h +++ b/xbyak/xbyak.h @@ -105,7 +105,7 @@ namespace Xbyak { enum { DEFAULT_MAX_CODE_SIZE = 4096, - VERSION = 0x5030 /* 0xABCD = A.BC(D) */ + VERSION = 0x5100 /* 0xABCD = A.BC(D) */ }; #ifndef MIE_INTEGER_TYPE_DEFINED @@ -176,6 +176,7 @@ enum { ERR_INVALID_BROADCAST, ERR_INVALID_OPMASK_WITH_MEMORY, ERR_INVALID_ZERO, + ERR_INVALID_RIP_IN_AUTO_GROW, ERR_INTERNAL }; @@ -235,6 +236,7 @@ public: "invalid broadcast", "invalid opmask with memory", "invalid zero", + "invalid rip in AutoGrow", "internal error", }; assert((size_t)err_ < sizeof(errTbl) / sizeof(*errTbl)); @@ -584,17 +586,22 @@ struct Reg64 : public Reg32e { struct RegRip { sint64 disp_; Label* label_; - explicit RegRip(sint64 disp = 0, Label* label = 0) : disp_(disp), label_(label) {} + bool isAddr_; + explicit RegRip(sint64 disp = 0, Label* label = 0, bool isAddr = false) : disp_(disp), label_(label), isAddr_(isAddr) {} friend const RegRip operator+(const RegRip& r, sint64 disp) { - return RegRip(r.disp_ + disp, r.label_); + return RegRip(r.disp_ + disp, r.label_, r.isAddr_); } friend const RegRip operator-(const RegRip& r, sint64 disp) { - return RegRip(r.disp_ - disp, r.label_); + return RegRip(r.disp_ - disp, r.label_, r.isAddr_); } friend const RegRip operator+(const RegRip& r, Label& label) { - if (r.label_) throw Error(ERR_BAD_ADDRESSING); + if (r.label_ || r.isAddr_) throw Error(ERR_BAD_ADDRESSING); return RegRip(r.disp_, &label); } + friend const RegRip operator+(const RegRip& r, const void *addr) { + if (r.disp_ || r.label_ || r.isAddr_) throw Error(ERR_BAD_ADDRESSING); + return RegRip((sint64)addr, 0, true); + } }; #endif @@ -945,7 +952,8 @@ public: enum Mode { M_ModRM, M_64bitDisp, - M_rip + M_rip, + M_ripAddr }; Address(uint32 sizeBit, bool broadcast, const RegExp& e) : Operand(0, MEM, sizeBit), e_(e), label_(0), mode_(M_ModRM), permitVsib_(false), broadcast_(broadcast) @@ -957,7 +965,7 @@ public: explicit Address(size_t disp) : Operand(0, MEM, 64), e_(disp), label_(0), mode_(M_64bitDisp), permitVsib_(false), broadcast_(false){ } Address(uint32 sizeBit, bool broadcast, const RegRip& addr) - : Operand(0, MEM, sizeBit), e_(addr.disp_), label_(addr.label_), mode_(M_rip), permitVsib_(false), broadcast_(broadcast) { } + : Operand(0, MEM, sizeBit), e_(addr.disp_), label_(addr.label_), mode_(addr.isAddr_ ? M_ripAddr : M_rip), permitVsib_(false), broadcast_(broadcast) { } #endif void permitVsib() const { permitVsib_ = true; } const RegExp& getRegExp() const { return e_; } @@ -1596,12 +1604,17 @@ private: { if (addr.getMode() == Address::M_ModRM) { setSIB(addr.getRegExp(), reg, disp8N); - } else if (addr.getMode() == Address::M_rip) { + } else if (addr.getMode() == Address::M_rip || addr.getMode() == Address::M_ripAddr) { setModRM(0, reg, 5); if (addr.getLabel()) { // [rip + Label] putL_inner(*addr.getLabel(), true, addr.getDisp() - immSize); } else { - dd(inner::VerifyInInt32(addr.getDisp())); + size_t disp = addr.getDisp(); + if (addr.getMode() == Address::M_ripAddr) { + if (isAutoGrow()) throw Error(ERR_INVALID_RIP_IN_AUTO_GROW); + disp -= (size_t)getCurr() + 4 + immSize; + } + dd(inner::VerifyInInt32(disp)); } } } diff --git a/xbyak/xbyak_mnemonic.h b/xbyak/xbyak_mnemonic.h index 4fb03a7..27f3737 100644 --- a/xbyak/xbyak_mnemonic.h +++ b/xbyak/xbyak_mnemonic.h @@ -1,4 +1,4 @@ -const char *getVersionString() const { return "5.02"; } +const char *getVersionString() const { return "5.10"; } void adc(const Operand& op, uint32 imm) { opRM_I(op, imm, 0x10, 2); } void adc(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x10); } void adcx(const Reg32e& reg, const Operand& op) { opGen(reg, op, 0xF6, 0x66, isREG32_REG32orMEM, NONE, 0x38); } @@ -293,124 +293,124 @@ void idiv(const Operand& op) { opR_ModM(op, 0, 7, 0xF6); } void imul(const Operand& op) { opR_ModM(op, 0, 5, 0xF6); } void inc(const Operand& op) { opIncDec(op, 0x40, 0); } void insertps(const Xmm& xmm, const Operand& op, uint8 imm) { opGen(xmm, op, 0x21, 0x66, isXMM_XMMorMEM, imm, 0x3A); } -void ja(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x77, 0x87, 0x0F); } void ja(const char *label, LabelType type = T_AUTO) { ja(std::string(label), type); } +void ja(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x77, 0x87, 0x0F); } void ja(const void *addr) { opJmpAbs(addr, T_NEAR, 0x77, 0x87, 0x0F); } void ja(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x77, 0x87, 0x0F); } -void jae(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x73, 0x83, 0x0F); } void jae(const char *label, LabelType type = T_AUTO) { jae(std::string(label), type); } +void jae(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x73, 0x83, 0x0F); } void jae(const void *addr) { opJmpAbs(addr, T_NEAR, 0x73, 0x83, 0x0F); } void jae(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x73, 0x83, 0x0F); } -void jb(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x72, 0x82, 0x0F); } void jb(const char *label, LabelType type = T_AUTO) { jb(std::string(label), type); } +void jb(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x72, 0x82, 0x0F); } void jb(const void *addr) { opJmpAbs(addr, T_NEAR, 0x72, 0x82, 0x0F); } void jb(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x72, 0x82, 0x0F); } -void jbe(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x76, 0x86, 0x0F); } void jbe(const char *label, LabelType type = T_AUTO) { jbe(std::string(label), type); } +void jbe(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x76, 0x86, 0x0F); } void jbe(const void *addr) { opJmpAbs(addr, T_NEAR, 0x76, 0x86, 0x0F); } void jbe(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x76, 0x86, 0x0F); } -void jc(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x72, 0x82, 0x0F); } void jc(const char *label, LabelType type = T_AUTO) { jc(std::string(label), type); } +void jc(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x72, 0x82, 0x0F); } void jc(const void *addr) { opJmpAbs(addr, T_NEAR, 0x72, 0x82, 0x0F); } void jc(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x72, 0x82, 0x0F); } -void je(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x74, 0x84, 0x0F); } void je(const char *label, LabelType type = T_AUTO) { je(std::string(label), type); } +void je(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x74, 0x84, 0x0F); } void je(const void *addr) { opJmpAbs(addr, T_NEAR, 0x74, 0x84, 0x0F); } void je(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x74, 0x84, 0x0F); } -void jg(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7F, 0x8F, 0x0F); } void jg(const char *label, LabelType type = T_AUTO) { jg(std::string(label), type); } +void jg(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7F, 0x8F, 0x0F); } void jg(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7F, 0x8F, 0x0F); } void jg(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7F, 0x8F, 0x0F); } -void jge(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7D, 0x8D, 0x0F); } void jge(const char *label, LabelType type = T_AUTO) { jge(std::string(label), type); } +void jge(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7D, 0x8D, 0x0F); } void jge(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7D, 0x8D, 0x0F); } void jge(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7D, 0x8D, 0x0F); } -void jl(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7C, 0x8C, 0x0F); } void jl(const char *label, LabelType type = T_AUTO) { jl(std::string(label), type); } +void jl(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7C, 0x8C, 0x0F); } void jl(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7C, 0x8C, 0x0F); } void jl(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7C, 0x8C, 0x0F); } -void jle(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7E, 0x8E, 0x0F); } void jle(const char *label, LabelType type = T_AUTO) { jle(std::string(label), type); } +void jle(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7E, 0x8E, 0x0F); } void jle(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7E, 0x8E, 0x0F); } void jle(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7E, 0x8E, 0x0F); } -void jna(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x76, 0x86, 0x0F); } void jna(const char *label, LabelType type = T_AUTO) { jna(std::string(label), type); } +void jna(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x76, 0x86, 0x0F); } void jna(const void *addr) { opJmpAbs(addr, T_NEAR, 0x76, 0x86, 0x0F); } void jna(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x76, 0x86, 0x0F); } -void jnae(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x72, 0x82, 0x0F); } void jnae(const char *label, LabelType type = T_AUTO) { jnae(std::string(label), type); } +void jnae(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x72, 0x82, 0x0F); } void jnae(const void *addr) { opJmpAbs(addr, T_NEAR, 0x72, 0x82, 0x0F); } void jnae(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x72, 0x82, 0x0F); } -void jnb(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x73, 0x83, 0x0F); } void jnb(const char *label, LabelType type = T_AUTO) { jnb(std::string(label), type); } +void jnb(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x73, 0x83, 0x0F); } void jnb(const void *addr) { opJmpAbs(addr, T_NEAR, 0x73, 0x83, 0x0F); } void jnb(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x73, 0x83, 0x0F); } -void jnbe(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x77, 0x87, 0x0F); } void jnbe(const char *label, LabelType type = T_AUTO) { jnbe(std::string(label), type); } +void jnbe(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x77, 0x87, 0x0F); } void jnbe(const void *addr) { opJmpAbs(addr, T_NEAR, 0x77, 0x87, 0x0F); } void jnbe(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x77, 0x87, 0x0F); } -void jnc(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x73, 0x83, 0x0F); } void jnc(const char *label, LabelType type = T_AUTO) { jnc(std::string(label), type); } +void jnc(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x73, 0x83, 0x0F); } void jnc(const void *addr) { opJmpAbs(addr, T_NEAR, 0x73, 0x83, 0x0F); } void jnc(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x73, 0x83, 0x0F); } -void jne(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x75, 0x85, 0x0F); } void jne(const char *label, LabelType type = T_AUTO) { jne(std::string(label), type); } +void jne(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x75, 0x85, 0x0F); } void jne(const void *addr) { opJmpAbs(addr, T_NEAR, 0x75, 0x85, 0x0F); } void jne(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x75, 0x85, 0x0F); } -void jng(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7E, 0x8E, 0x0F); } void jng(const char *label, LabelType type = T_AUTO) { jng(std::string(label), type); } +void jng(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7E, 0x8E, 0x0F); } void jng(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7E, 0x8E, 0x0F); } void jng(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7E, 0x8E, 0x0F); } -void jnge(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7C, 0x8C, 0x0F); } void jnge(const char *label, LabelType type = T_AUTO) { jnge(std::string(label), type); } +void jnge(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7C, 0x8C, 0x0F); } void jnge(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7C, 0x8C, 0x0F); } void jnge(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7C, 0x8C, 0x0F); } -void jnl(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7D, 0x8D, 0x0F); } void jnl(const char *label, LabelType type = T_AUTO) { jnl(std::string(label), type); } +void jnl(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7D, 0x8D, 0x0F); } void jnl(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7D, 0x8D, 0x0F); } void jnl(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7D, 0x8D, 0x0F); } -void jnle(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7F, 0x8F, 0x0F); } void jnle(const char *label, LabelType type = T_AUTO) { jnle(std::string(label), type); } +void jnle(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7F, 0x8F, 0x0F); } void jnle(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7F, 0x8F, 0x0F); } void jnle(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7F, 0x8F, 0x0F); } -void jno(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x71, 0x81, 0x0F); } void jno(const char *label, LabelType type = T_AUTO) { jno(std::string(label), type); } +void jno(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x71, 0x81, 0x0F); } void jno(const void *addr) { opJmpAbs(addr, T_NEAR, 0x71, 0x81, 0x0F); } void jno(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x71, 0x81, 0x0F); } -void jnp(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7B, 0x8B, 0x0F); } void jnp(const char *label, LabelType type = T_AUTO) { jnp(std::string(label), type); } +void jnp(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7B, 0x8B, 0x0F); } void jnp(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7B, 0x8B, 0x0F); } void jnp(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7B, 0x8B, 0x0F); } -void jns(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x79, 0x89, 0x0F); } void jns(const char *label, LabelType type = T_AUTO) { jns(std::string(label), type); } +void jns(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x79, 0x89, 0x0F); } void jns(const void *addr) { opJmpAbs(addr, T_NEAR, 0x79, 0x89, 0x0F); } void jns(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x79, 0x89, 0x0F); } -void jnz(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x75, 0x85, 0x0F); } void jnz(const char *label, LabelType type = T_AUTO) { jnz(std::string(label), type); } +void jnz(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x75, 0x85, 0x0F); } void jnz(const void *addr) { opJmpAbs(addr, T_NEAR, 0x75, 0x85, 0x0F); } void jnz(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x75, 0x85, 0x0F); } -void jo(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x70, 0x80, 0x0F); } void jo(const char *label, LabelType type = T_AUTO) { jo(std::string(label), type); } +void jo(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x70, 0x80, 0x0F); } void jo(const void *addr) { opJmpAbs(addr, T_NEAR, 0x70, 0x80, 0x0F); } void jo(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x70, 0x80, 0x0F); } -void jp(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7A, 0x8A, 0x0F); } void jp(const char *label, LabelType type = T_AUTO) { jp(std::string(label), type); } +void jp(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7A, 0x8A, 0x0F); } void jp(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7A, 0x8A, 0x0F); } void jp(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7A, 0x8A, 0x0F); } -void jpe(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7A, 0x8A, 0x0F); } void jpe(const char *label, LabelType type = T_AUTO) { jpe(std::string(label), type); } +void jpe(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7A, 0x8A, 0x0F); } void jpe(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7A, 0x8A, 0x0F); } void jpe(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7A, 0x8A, 0x0F); } -void jpo(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7B, 0x8B, 0x0F); } void jpo(const char *label, LabelType type = T_AUTO) { jpo(std::string(label), type); } +void jpo(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7B, 0x8B, 0x0F); } void jpo(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7B, 0x8B, 0x0F); } void jpo(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7B, 0x8B, 0x0F); } -void js(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x78, 0x88, 0x0F); } void js(const char *label, LabelType type = T_AUTO) { js(std::string(label), type); } +void js(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x78, 0x88, 0x0F); } void js(const void *addr) { opJmpAbs(addr, T_NEAR, 0x78, 0x88, 0x0F); } void js(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x78, 0x88, 0x0F); } -void jz(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x74, 0x84, 0x0F); } void jz(const char *label, LabelType type = T_AUTO) { jz(std::string(label), type); } +void jz(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x74, 0x84, 0x0F); } void jz(const void *addr) { opJmpAbs(addr, T_NEAR, 0x74, 0x84, 0x0F); } void jz(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x74, 0x84, 0x0F); } void lahf() { db(0x9F); }