
x86/x86-64 निर्देश एन्कोडिंग के लिए हेडर-ओनली C++2x कम्पाइल-टाइम असेंबलर
कंपाइल-टाइम x86/x86-64 इंस्ट्रक्शन एन्कोडिंग के लिए एक हेडर-ओनली C++20 लाइब्रेरी।
यह प्रोजेक्ट Boost Software License 1.0 और MIT License के अंतर्गत दोहरे लाइसेंस प्राप्त है। आप इनमें से कोई भी लाइसेंस चुन सकते हैं।
#include "static_asm.hpp"
using namespace static_asm;
using namespace static_asm::x86;
using namespace static_asm::x86::registers;
using namespace static_asm::x86::instructions;
// Build machine code at compile time
constexpr auto code = core::assemble(
mov(rax, 0x12345678), // mov rax, imm32
add(rax, rcx), // add rax, rcx
xor_(r8, r8), // xor r8, r8
call(rax), // call rax
ret() // ret
);
// code is std::array<uint8_t, N> - fully constexpr!
नामित शाखाओं और एम्बेडेड डेटा के लिए, लेबल और शाखा शिथिलीकरण देखें।
// Register to register
add(rax, rbx); // 48 01 D8
sub(ecx, edx); // 29 D1
and_(r8, r9); // 4D 21 C8
or_(rsi, rdi); // 48 09 FE
xor_(eax, eax); // 31 C0 (common idiom to zero a register)
cmp(rax, rcx); // 48 39 C8
// Register with immediate
add(rax, 0x10); // 48 83 C0 10 (sign-extended imm8)
add(rax, 0x10000); // 48 05 00 00 01 00 (imm32)
sub(ecx, 100); // 83 E9 64
and_(rdx, 0xFF); // 48 83 E2 FF
// With memory operands
add(eax, dword_ptr(rbx)); // 03 03
add(rax, qword_ptr(rcx + disp<0x10>)); // 48 03 41 10
sub(dword_ptr(rsp + disp<0x20>), eax); // 29 44 24 20
सबसे छोटे विस्थापन के लिए
disp<value>का उपयोग करें। यह शून्य के लिए कोई विस्थापन नहीं चुनता जहाँ वैध हो, -128 से 127 तक के लिए एक signeddisp8चुनता है, और अन्यथाdisp32चुनता है। RIP-relative पते को हमेशाdisp32की आवश्यकता होती है; शून्य के साथ RBP/R13 को अभी भी एक शून्यdisp8की आवश्यकता होती है। signed 32 बिट्स से बाहर के मान संकलन विफल कर देते हैं।rcx + 0x10जैसा एक सादा पूर्णांक अभी भीdisp32का उपयोग करता है: C++ एकintआर्ग्युमेंट के मान से विभिन्न सटीक-आकार वाले instruction array प्रकारों का चयन नहीं कर सकता। सामान्य base के साथ[base + disp]विहित ModR/M-only रूप (कोई SIB बाइट नहीं) का उपयोग करता है; RSP/R12 base एक SIB बाइट उत्सर्जित करते हैं क्योंकि हार्डवेयर को इसकी आवश्यकता होती है।
// Register to register
mov(rax, rbx); // 48 89 D8
mov(eax, ecx); // 89 C8
mov(r8, r9); // 4D 89 C8
// Immediate to register
mov(rax, 0x12345678); // 48 C7 C0 78 56 34 12
mov(eax, 0xDEADBEEF); // B8 EF BE AD DE
// Memory operations
mov(rax, qword_ptr(rbx)); // 48 8B 03
mov(eax, dword_ptr(rcx + disp<0x10>)); // 8B 41 10
mov(rax, qword_ptr(rbp - disp<0x20>)); // 48 8B 45 E0 (canonical, no SIB)
mov(qword_ptr(rsp + disp<0x8>), rax); // 48 89 44 24 08 (RSP base needs SIB)
// Zero/sign extension
movzx(eax, bl); // 0F B6 C3 (zero-extend byte to dword)
movzx(rax, bx); // 48 0F B7 C3 (zero-extend word to qword)
movsx(eax, cl); // 0F BE C1 (sign-extend byte to dword)
movsx(rax, dx); // 48 0F BF C2 (sign-extend word to qword)
movsxd(rax, ecx); // 48 63 C1 (sign-extend dword to qword)
// Load effective address
lea(rax, qword_ptr(rbx + rcx * s4)); // 48 8D 04 8B
lea(rax, qword_ptr(rbx + rcx * s8 + disp<0x10>)); // 48 8D 44 CB 10
// Exchange (register or memory; XCHG is symmetric)
xchg(rax, rbx); // 48 87 D8
xchg(qword_ptr(rcx), rax); // 48 87 01
xchg(rbx, qword_ptr(rcx + disp<0x10>)); // 48 87 59 10
// Store an immediate to a displaced / SIB / RIP memory destination
mov(dword_ptr(rbp - disp<0x20>), 0x100); // C7 45 E0 00 01 00 00
mov(qword_ptr(rcx + disp<0x10>), 1); // 48 C7 41 10 01 00 00 00
add(qword_ptr(rbx + disp<0x8>), 0x10); // 48 81 43 08 10 00 00 00
एक qword मेमोरी गंतव्य में केवल साइन-एक्सटेंडेड 32-बिट इमीडिएट एन्कोडिंग होती है।
किसी इंटीजर के 64-बिट बिट पैटर्न को उस एन्कोडिंग से मेल खाना चाहिए: उदाहरण के लिए, 0x7FFFFFFF
और -0x80000000LL फिट होते हैं, जबकि धनात्मक 0x80000000ULL नहीं होता। एक अमान्य
मान कॉन्स्टेंट इवैल्यूएशन में विफल होता है या रनटाइम पर std::out_of_range थ्रो करता है।
एक्सेप्शन अक्षम होने पर, एक अमान्य रनटाइम मान टर्मिनेट हो जाता है। स्पष्ट
imm32 ऑपरेंड कच्चे चार इमीडिएट बाइट्स प्रदान करते हैं।
rip + disp (और rip - disp) 64-बिट RIP-सापेक्ष रूप को एन्कोड करते हैं (ModR/M
mod=00 r/m=101, एक अनिवार्य disp32, कभी भी SIB बाइट नहीं):
mov(rax, qword_ptr(rip + 0x10)); // 48 8B 05 10 00 00 00
lea(rax, qword_ptr(rip + 0x100)); // 48 8D 05 00 01 00 00
add(qword_ptr(rip + 0x20), rbx); // 48 01 1D 20 00 00 00
inc(qword_ptr(rip + 0x40)); // 48 FF 05 40 00 00 00
test(rax, qword_ptr(rip + 0x10)); // 48 85 05 10 00 00 00
test(qword_ptr(rip + 0), 0x10); // 48 F7 05 00 00 00 00 10 00 00 00
// [base + index*scale]
mov(eax, dword_ptr(rbx + rcx * s1)); // 8B 04 0B
mov(eax, dword_ptr(rbx + rcx * s2)); // 8B 04 4B
mov(eax, dword_ptr(rbx + rcx * s4)); // 8B 04 8B
mov(eax, dword_ptr(rbx + rcx * s8)); // 8B 04 CB
// [base + index*scale + displacement]
mov(rax, qword_ptr(rbx + rcx * s4 + disp<0x10>)); // 48 8B 44 8B 10
mov(rax, qword_ptr(r12 + r13 * s8 + 0x1000)); // 4B 8B 84 EC 00 10 00 00
// Store to SIB address
mov(dword_ptr(rax + rdx * s4), ecx); // 89 0C 90
mov(qword_ptr(rbx + rsi * s8 + disp<0x20>), rax); // 48 89 44 F3 20
// LEA with SIB (useful for address calculations)
lea(rax, qword_ptr(rbx + rcx * s4)); // 48 8D 04 8B
lea(rax, qword_ptr(rdi + rsi * s8 + 0x100)); // 48 8D 84 F7 00 01 00 00
// Shift by 1
shl(eax, 1); // D1 E0
shr(rax, 1); // 48 D1 E8
sar(ecx, 1); // D1 F9
// Shift by immediate
shl(eax, 4); // C1 E0 04
shr(rax, 8); // 48 C1 E8 08
sar(rdx, 16); // 48 C1 FA 10
// Shift by CL register
shl(eax, cl); // D3 E0
shr(rax, cl); // 48 D3 E8
// Rotate
rol(eax, 1); // D1 C0
ror(rax, 8); // 48 C1 C8 08
rcl(ecx, cl); // D3 D1
rcr(rdx, 1); // 48 D1 DA
// Single operand (result in rdx:rax)
mul(rbx); // 48 F7 E3 (unsigned: rdx:rax = rax * rbx)
imul(rcx); // 48 F7 E9 (signed: rdx:rax = rax * rcx)
div(rbx); // 48 F7 F3 (unsigned: rax = rdx:rax / rbx, rdx = remainder)
idiv(rcx); // 48 F7 F9 (signed division)
// Two-operand IMUL (dest = dest * src)
imul(rax, rbx); // 48 0F AF C3
imul(ecx, edx); // 0F AF CA
// Three-operand IMUL (dest = src * imm)
imul(rax, rbx, 10); // 48 6B C3 0A
imul(ecx, edx, 1000); // 69 CA E8 03 00 00
// Single-operand form with a memory operand
mul(qword_ptr(rcx)); // 48 F7 21
imul(qword_ptr(rcx + disp<0x20>)); // 48 F7 69 20
div(dword_ptr(rax + disp<0x10>)); // F7 70 10
idiv(qword_ptr(rbx)); // 48 F7 3B