#pragma once #include // intel: // mov dst, src // mov eax, 16 // mov eax, 0ffh // // move whats pointed by ebx into eax // mov eax, [ebx] // // no need to use movb // this already moves a byte // mov al, 5 // registers // +----------------+-----------------+-----------------+ // | 8 Bit - No REX | 16 Bit - No REX | 32 Bit - No REX | // +-------+--------+-----------------+-----------------| // | AL | AH | AX | EAX | // | BL | BH | BX | EBX | // | CL | CH | CX | ECX | // | DL | DH | DX | EDX | // +-------+--------+ DI | EDI | // +////////////////+ SI | EDI | // +////////////////+ BP | EBP | // +////////////////+ SP | ESP | // +----------------+-----------------+-----------------+------------+ // | 8 Bit - REX | 16 Bit - REX | 32 Bit - REX | 64 Bit | // +----------------+-----------------+-----------------+------------+ // | AL | AX | EAX | RAX | // | BL | BX | EBX | RBX | // | CL | CX | ECX | RCX | // | DL | DX | EDX | RDX | // | DIL | DI | EDI | RDI | // | SIL | SI | ESI | RSI | // | BPL | BP | EBP | RBP | // | SPL | SP | ESP | RSP | // | R8B | R8W | R8D | R8 | // | R9B | R9W | R9D | R9 | // | R10B | R10W | R10D | R10 | // | R11B | R11W | R11D | R11 | // | R12B | R12W | R12D | R12 | // | R13B | R13W | R13D | R13 | // | R14B | R14W | R14D | R14 | // | R15B | R15W | R15D | R15 | // +----------------+-----------------+-----------------+------------+ // // Special // RFLAGS <- lower 32 bits used, upper reserved #define COM1 0x3f8 static inline void cli() { asm volatile ("cli"); } static inline void sti() { asm volatile ("sti"); } static inline void hlt() { asm volatile("hlt"); } static inline void cpuid_vendor(char* str) { int* casted = (int*)str; asm volatile ("mov rax, 0; cpuid;" : "=b" (casted[0]), "=d" (casted[1]), "=c" (casted[2]) : // input in empty : "eax"); // touched registers } static inline void cpuid(uint64_t leaf, uint64_t subleaf, uint32_t* a, uint32_t* b, uint32_t* c, uint32_t* d) { uint32_t la, lb, lc, ld; asm volatile("cpuid;" : "=a" (la), "=b" (lb), "=c" (lc), "=d" (ld) : "a" (leaf), "c" (subleaf) : ); *a = la; *b = lb; *c = lc; *d = ld; } static inline uint64_t xchg(volatile uint64_t *addr, uint64_t newval) { uint64_t result; // might need to reorder asm volatile ("lock; xchgl %0, %1" : "+m" (*addr), "=a" (result) : "1" (newval) : "cc"); return result; } static inline void lcr3(uint64_t value) { asm volatile ("mov cr3, %0" : : "r" (value) : ); } static inline void lgdt(void* ptr) { asm volatile ("lgdt [%0];" : : "r" (ptr) ); } static inline void lidt(void* ptr) { asm volatile ("lidt [%0];" : : "r" (ptr)); } static inline void ltr(unsigned short sel) { asm volatile ("ltr %0" : : "r" (sel)); } static inline uint64_t rrsp() { uint64_t r; asm volatile ("mov %0, rsp" : "=r" (r) : ); return r; } static inline void rdmsr(uint32_t msr, uint64_t* d, uint64_t* a) { uint64_t ld; uint64_t la; asm volatile("rdmsr" : "=d" (ld), "=a" (la) : "c" (msr) ); *d = ld; *a = la; } static inline void fldcw(const uint16_t control) { asm volatile("fldcw %0;"::"m"(control)); } static inline void outb(uint16_t port, uint8_t val) { asm volatile ( "outb %1, %0" : : "a"(val), "Nd"(port) ); } static inline void outw(uint16_t port, uint16_t val) { asm volatile ("outw %1, %0" : : "a"(val), "Nd"(port) ); } static inline void outl(uint16_t port, uint32_t val) { asm volatile ("outl %1, %0" : : "a"(val), "Nd"(port) ); } static inline uint8_t inb(uint16_t port) { uint8_t ret; asm volatile ( "inb %0, %1" : "=a"(ret) : "Nd"(port) ); return ret; } static inline uint16_t inw(uint16_t port) { uint16_t ret; asm volatile ( "inb %0, %1" : "=a"(ret) : "Nd"(port) ); return ret; } static inline uint32_t inl(uint16_t port) { uint32_t ret; asm volatile ( "inb %0, %1" : "=a"(ret) : "Nd"(port) ); return ret; }