
x86/x86-64 निर्देश एन्कोडिंग के लिए हेडर-ओनली C++2x कम्पाइल-टाइम असेंबलर
एक हेडर-ओनली C++20 लाइब्रेरी जो संकलन-समय पर x86/x86-64 निर्देश एन्कोडिंग के लिए है।
यह प्रोजेक्ट बूस्ट सॉफ़्टवेयर लाइसेंस 1.0 और MIT लाइसेंस के तहत दोहरे-लाइसेंस है। आप कोई भी लाइसेंस चुन सकते हैं।
#include "static_asm.hpp"
using namespace static_asm::x86::registers;
using namespace static_asm::x86::instructions;
// संकलन समय पर मशीन कोड बनाएं
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 एक std::array<uint8_t, N> है - पूरी तरह constexpr!
// रजिस्टर से रजिस्टर
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 (रजिस्टर को शून्य करने का सामान्य तरीका)
cmp(rax, rcx); // 48 39 C8
// रजिस्टर के साथ तत्काल मान
add(rax, 0x10); // 48 83 C0 10 (हस्ताक्षर-विस्तारित imm8)
add(rax, 0x10000); // 48 05 00 00 01 00 (imm32)
sub(ecx, 100); // 83 E9 64
and_(rdx, 0xFF); // 48 83 E2 FF
// मेमोरी ऑपरेंड के साथ
add(eax, dword_ptr(rbx)); // 03 03
add(rax, qword_ptr(rcx + 0x10)); // 48 03 41 10
sub(dword_ptr(rsp + 0x20), eax); // 29 44 24 20
// रजिस्टर से रजिस्टर
mov(rax, rbx); // 48 89 D8
mov(eax, ecx); // 89 C8
mov(r8, r9); // 4D 89 C8
// तत्काल मान से रजिस्टर
mov(rax, 0x12345678); // 48 C7 C0 78 56 34 12
mov(eax, 0xDEADBEEF); // B8 EF BE AD DE
// मेमोरी संचालन
mov(rax, qword_ptr(rbx)); // 48 8B 03
mov(eax, dword_ptr(rcx + 0x10)); // 8B 41 10
mov(qword_ptr(rsp + 0x8), rax); // 48 89 44 24 08
mov(dword_ptr(rbp - 0x20), 0x100); // C7 45 E0 00 01 00 00
// शून्य/हस्ताक्षर विस्तार
movzx(eax, bl); // 0F B6 C3 (बाइट को dword में शून्य-विस्तार)
movzx(rax, bx); // 48 0F B7 C3 (शब्द को qword में शून्य-विस्तार)
movsx(eax, cl); // 0F BE C1 (बाइट को dword में हस्ताक्षर-विस्तार)
movsx(rax, dx); // 48 0F BF C2 (शब्द को qword में हस्ताक्षर-विस्तार)
movsxd(rax, ecx); // 48 63 C1 (dword को qword में हस्ताक्षर-विस्तार)
// प्रभावी पता लोड करें
lea(rax, qword_ptr(rbx + rcx * s4)); // 48 8D 04 8B
lea(rax, qword_ptr(rbx + rcx * s8 + 0x10)); // 48 8D 44 CB 10
// आदान-प्रदान
xchg(rax, rbx); // 48 87 D8
// [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 + 0x10)); // 48 8B 44 8B 10
mov(rax, qword_ptr(r12 + r13 * s8 + 0x1000)); // 4B 8B 84 EC 00 10 00 00
// SIB पते पर स्टोर करें
mov(dword_ptr(rax + rdx * s4), ecx); // 89 0C 90
mov(qword_ptr(rbx + rsi * s8 + 0x20), rax); // 48 89 44 F3 20
// SIB के साथ LEA (पता गणना के लिए उपयोगी)
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
// 1 से शिफ्ट
shl(eax, 1); // D1 E0
shr(rax, 1); // 48 D1 E8
sar(ecx, 1); // D1 F9
// तत्काल मान से शिफ्ट
shl(eax, 4); // C1 E0 04
shr(rax, 8); // 48 C1 E8 08
sar(rdx, 16); // 48 C1 FA 10
// CL रजिस्टर से शिफ्ट
shl(eax, cl); // D3 E0
shr(rax, cl); // 48 D3 E8
// रोटेट
rol(eax, 1); // D1 C0
ror(rax, 8); // 48 C1 C8 08
rcl(ecx, cl); // D3 D1
rcr(rdx, 1); // 48 D1 DA
// एकल ऑपरेंड (परिणाम rdx:rax में)
mul(rbx); // 48 F7 E3 (अहस्ताक्षरित: rdx:rax = rax * rbx)
imul(rcx); // 48 F7 E9 (हस्ताक्षरित: rdx:rax = rax * rcx)
div(rbx); // 48 F7 F3 (अहस्ताक्षरित: rax = rdx:rax / rbx, rdx = शेष)
idiv(rcx); // 48 F7 F9 (हस्ताक्षरित विभाजन)
// दो-ऑपरेंड IMUL (dest = dest * src)
imul(rax, rbx); // 48 0F AF C3
imul(ecx, edx); // 0F AF CA
// तीन-ऑपरेंड IMUL (dest = src * imm)
imul(rax, rbx, 10); // 48 6B C3 0A
imul(ecx, edx, 1000); // 69 CA E8 03 00 00
// बिना शर्त कूद
jmp(0x10); // EB 10 (छोटा, 8-बिट ऑफ़सेट)
jmp(0x1000); // E9 00 10 00 00 (निकट, 32-बिट ऑफ़सेट)
jmp(rax); // FF E0 (अप्रत्यक्ष)
jmp(here); // EB FE (jmp $, अनंत लूप)
// सशर्त कूद (8-बिट ऑफ़सेट)
jz(0x10); // 74 10
jnz(0x20); // 75 20
jb(0x08); // 72 08 (नीचे/कैरी)
jae(0x08); // 73 08 (ऊपर या बराबर/कोई कैरी नहीं)
jl(0x10); // 7C 10 (कम से, हस्ताक्षरित)
jge(0x10); // 7D 10 (अधिक या बराबर, हस्ताक्षरित)
// सशर्त कूद (लंबी शाखाओं के लिए 32-बिट ऑफ़सेट)
jz_near(0x10000); // 0F 84 00 00 01 00
jnz_near(0x20000); // 0F 85 00 00 02 00
// कॉल और रिटर्न
call(rax); // FF D0 (अप्रत्यक्ष कॉल)
call(0x100); // E8 00 01 00 00 (सापेक्ष कॉल)
ret(); // C3
ret(0x10); // C2 10 00 (वापसी और 16 बाइट पॉप)
// शर्त सत्य होने पर मूव करें (कोई शाखा दंड नहीं!)
cmovz(rax, rbx); // 48 0F 44 C3 (शून्य होने पर मूव)
cmovnz(eax, ecx); // 0F 45 C1 (शून्य न होने पर मूव)
cmovl(rax, rdx); // 48 0F 4C C2 (कम होने पर मूव, हस्ताक्षरित)
cmovge(ecx, esi); // 0F 4D CE (अधिक या बराबर होने पर मूव, हस्ताक्षरित)
cmovb(rax, rbx); // 48 0F 42 C3 (नीचे होने पर मूव, अहस्ताक्षरित)
cmovae(edx, edi); // 0F 43 D7 (ऊपर या बराबर होने पर मूव, अहस्ताक्षरित)
// मेमोरी स्रोत के साथ
cmovz(rax, qword_ptr(rbx)); // 48 0F 44 03
cmovnz(eax, dword_ptr(rcx + 0x10)); // 0F 45 41 10
// बिट परीक्षण
bt(eax, 5); // 0F BA E0 05
bt(rax, rbx); // 48 0F A3 D8
// बिट परीक्षण और सेट/रीसेट/पूरक
bts(eax, 10); // 0F BA E8 0A (परीक्षण और सेट)
btr(rax, rcx); // 48 0F B3 C8 (परीक्षण और रीसेट)
btc(edx, 3); // 0F BA FA 03 (परीक्षण और पूरक)
// बिट स्कैन
bsf(eax, ecx); // 0F BC C1 (पहले 1 के लिए आगे स्कैन)
bsr(rax, rbx); // 48 0F BD C3 (पहले 1 के लिए पीछे स्कैन)
// जनसंख्या गणना और अग्रणी/अनुगामी शून्य
popcnt(eax, ecx); // F3 0F B8 C1
lzcnt(rax, rbx); // F3 48 0F BD C3
tzcnt(eax, edx); // F3 0F BC C2
// बाइट स्वैप
bswap(eax); // 0F C8 (बाइट क्रम उलटें)
bswap(rax); // 48 0F C8
// मूल स्ट्रिंग ऑप्स ([rsi] और/या [rdi] पर काम करते हैं)
movsb(); // A4 (बाइट [rsi] -> [rdi] ले जाएं)
movsw(); // 66 A5
movsd(); // A5
movsq(); // 48 A5
cmpsb(); // A6 ([rsi] की [rdi] से तुलना करें)
stosb(); // AA (al को [rdi] में स्टोर करें)
lodsb(); // AC ([rsi] को al में लोड करें)
scasb(); // AE (al की [rdi] से तुलना करें)