From 1be3c2f1be8d3bf36f32662b77bb600f594218b5 Mon Sep 17 00:00:00 2001 From: RadWolfie Date: Sat, 28 Sep 2024 09:58:41 -0500 Subject: [PATCH] prepare asm macro wrapper before clang-format --- nboxkrnl/ex/ex.cpp | 36 +-- nboxkrnl/ex/exp_sup.cpp | 92 +++--- nboxkrnl/hal/halp.cpp | 64 ++--- nboxkrnl/hal/interrupt.cpp | 560 +++++++++++++++++-------------------- nboxkrnl/ke/bug.cpp | 20 +- nboxkrnl/ke/irql.cpp | 172 ++++++------ nboxkrnl/ke/ke.hpp | 56 ++-- nboxkrnl/ke/kernel.cpp | 46 +-- nboxkrnl/ke/thread.cpp | 180 ++++++------ nboxkrnl/kernel.hpp | 88 +++--- nboxkrnl/ki/hw_exp.cpp | 140 +++++----- nboxkrnl/ki/hw_exp.hpp | 196 ++++++------- nboxkrnl/ki/seh.cpp | 68 ++--- nboxkrnl/ki/seh.hpp | 20 +- nboxkrnl/main.cpp | 72 ++--- nboxkrnl/mm/mi.cpp | 10 +- nboxkrnl/nt/services.cpp | 22 +- nboxkrnl/ps/ps.cpp | 2 +- nboxkrnl/rtl/exp_sup.cpp | 56 ++-- nboxkrnl/rtl/rtl.cpp | 162 +++++------ nboxkrnl/types.hpp | 6 + nboxkrnl/xe/xe.cpp | 20 +- 22 files changed, 1031 insertions(+), 1057 deletions(-) diff --git a/nboxkrnl/ex/ex.cpp b/nboxkrnl/ex/ex.cpp index d8a9f46..97fe1e9 100644 --- a/nboxkrnl/ex/ex.cpp +++ b/nboxkrnl/ex/ex.cpp @@ -141,10 +141,10 @@ EXPORTNUM(51) LONG FASTCALL InterlockedCompareExchange LONG Comparand ) { - __asm { - mov eax, Comparand - cmpxchg [ecx], edx - } + ASM_BEGIN + ASM(mov eax, Comparand); + ASM(cmpxchg [ecx], edx); + ASM_END } EXPORTNUM(52) LONG FASTCALL InterlockedDecrement @@ -152,11 +152,11 @@ EXPORTNUM(52) LONG FASTCALL InterlockedDecrement volatile PLONG Addend ) { - __asm { - or eax, 0xFFFFFFFF - xadd [ecx], eax - dec eax - } + ASM_BEGIN + ASM(or eax, 0xFFFFFFFF); + ASM(xadd [ecx], eax); + ASM(dec eax); + ASM_END } EXPORTNUM(53) LONG FASTCALL InterlockedIncrement @@ -164,11 +164,11 @@ EXPORTNUM(53) LONG FASTCALL InterlockedIncrement volatile PLONG Addend ) { - __asm { - mov eax, 1 - xadd [ecx], eax - inc eax - } + ASM_BEGIN + ASM(mov eax, 1); + ASM(xadd [ecx], eax); + ASM(inc eax); + ASM_END } EXPORTNUM(54) LONG FASTCALL InterlockedExchange @@ -177,8 +177,8 @@ EXPORTNUM(54) LONG FASTCALL InterlockedExchange LONG Value ) { - __asm { - mov eax, Value - xchg [ecx], eax - } + ASM_BEGIN + ASM(mov eax, Value); + ASM(xchg [ecx], eax); + ASM_END } diff --git a/nboxkrnl/ex/exp_sup.cpp b/nboxkrnl/ex/exp_sup.cpp index 736f94c..00166b0 100644 --- a/nboxkrnl/ex/exp_sup.cpp +++ b/nboxkrnl/ex/exp_sup.cpp @@ -12,31 +12,31 @@ EXPORTNUM(26) __declspec(naked) VOID XBOXAPI ExRaiseException PEXCEPTION_RECORD ExceptionRecord ) { - __asm { - push ebp - mov ebp, esp - sub esp, SIZE CONTEXT - push esp - call RtlCaptureContext - add [esp]CONTEXT.Esp, 4 // pop ExceptionRecord argument - mov [esp]CONTEXT.ContextFlags, CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS // set ContextFlags member of CONTEXT - mov eax, [ebp + 8] - mov ecx, [ebp + 4] - mov [eax]EXCEPTION_RECORD.ExceptionAddress, ecx // set ExceptionAddress member of ExceptionRecord argument to caller's eip - push esp - push eax - call RtlDispatchException + ASM_BEGIN + ASM(push ebp); + ASM(mov ebp, esp); + ASM(sub esp, SIZE CONTEXT); + ASM(push esp); + ASM(call RtlCaptureContext); + ASM(add [esp]CONTEXT.Esp, 4); // pop ExceptionRecord argument + ASM(mov [esp]CONTEXT.ContextFlags, CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS); // set ContextFlags member of CONTEXT + ASM(mov eax, [ebp + 8]); + ASM(mov ecx, [ebp + 4]); + ASM(mov [eax]EXCEPTION_RECORD.ExceptionAddress, ecx); // set ExceptionAddress member of ExceptionRecord argument to caller's eip + ASM(push esp); + ASM(push eax); + ASM(call RtlDispatchException); // If the exception is continuable, then RtlDispatchException will return - mov ecx, esp - push FALSE - push ecx - test al, al - jz exp_unhandled - call ZwContinue // won't return - exp_unhandled: - push [ebp + 8] - call ZwRaiseException // won't return - } + ASM(mov ecx, esp); + ASM(push FALSE); + ASM(push ecx); + ASM(test al, al); + ASM(jz exp_unhandled); + ASM(call ZwContinue); // won't return + exp_unhandled: + ASM(push [ebp + 8]); + ASM(call ZwRaiseException); // won't return + ASM_END } EXPORTNUM(27) __declspec(naked) VOID XBOXAPI ExRaiseStatus @@ -44,27 +44,27 @@ EXPORTNUM(27) __declspec(naked) VOID XBOXAPI ExRaiseStatus NTSTATUS Status ) { - __asm { - push ebp - mov ebp, esp - sub esp, SIZE CONTEXT + SIZE EXCEPTION_RECORD - push esp - call RtlCaptureContext - add [esp]CONTEXT.Esp, 4 // pop Status argument - mov [esp]CONTEXT.ContextFlags, CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS // set ContextFlags member of CONTEXT - lea ecx, [ebp - SIZE EXCEPTION_RECORD] - mov eax, [ebp + 8] - mov [ecx]EXCEPTION_RECORD.ExceptionCode, eax // set ExceptionCode member of ExceptionRecord to Status argument - mov [ecx]EXCEPTION_RECORD.ExceptionFlags, EXCEPTION_NONCONTINUABLE - mov [ecx]EXCEPTION_RECORD.ExceptionRecord, 0 - mov eax, [ebp + 4] - mov [ecx]EXCEPTION_RECORD.ExceptionAddress, eax // set ExceptionAddress member of ExceptionRecord to caller's eip - mov [ecx]EXCEPTION_RECORD.NumberParameters, 0 - push esp - push ecx - call RtlDispatchException + ASM_BEGIN + ASM(push ebp); + ASM(mov ebp, esp); + ASM(sub esp, SIZE CONTEXT + SIZE EXCEPTION_RECORD); + ASM(push esp); + ASM(call RtlCaptureContext); + ASM(add [esp]CONTEXT.Esp, 4); // pop Status argument + ASM(mov [esp]CONTEXT.ContextFlags, CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS); // set ContextFlags member of CONTEXT + ASM(lea ecx, [ebp - SIZE EXCEPTION_RECORD]); + ASM(mov eax, [ebp + 8]); + ASM(mov [ecx]EXCEPTION_RECORD.ExceptionCode, eax); // set ExceptionCode member of ExceptionRecord to Status argument + ASM(mov [ecx]EXCEPTION_RECORD.ExceptionFlags, EXCEPTION_NONCONTINUABLE); + ASM(mov [ecx]EXCEPTION_RECORD.ExceptionRecord, 0); + ASM(mov eax, [ebp + 4]); + ASM(mov [ecx]EXCEPTION_RECORD.ExceptionAddress, eax); // set ExceptionAddress member of ExceptionRecord to caller's eip + ASM(mov [ecx]EXCEPTION_RECORD.NumberParameters, 0); + ASM(push esp); + ASM(push ecx); + ASM(call RtlDispatchException); // Because the exception is non-continuable, RtlDispatchException should never return. If it does return, then it must be a bug - push NORETURN_FUNCTION_RETURNED - call KeBugCheckLogEip // won't return - } + ASM(push NORETURN_FUNCTION_RETURNED); + ASM(call KeBugCheckLogEip); // won't return + ASM_END } diff --git a/nboxkrnl/hal/halp.cpp b/nboxkrnl/hal/halp.cpp index a8c9ae8..be93749 100644 --- a/nboxkrnl/hal/halp.cpp +++ b/nboxkrnl/hal/halp.cpp @@ -34,39 +34,39 @@ KEVENT HalpSmbusComplete; VOID HalpInitPIC() { - __asm { - mov al, ICW1_ICW4_NEEDED | ICW1_CASCADE | ICW1_INTERVAL8 | ICW1_EDGE | ICW1_INIT - out PIC_MASTER_CMD, al - out PIC_SLAVE_CMD, al - mov al, PIC_MASTER_VECTOR_BASE - out PIC_MASTER_DATA, al - mov al, PIC_SLAVE_VECTOR_BASE - out PIC_SLAVE_DATA, al - mov al, 4 - out PIC_MASTER_DATA, al - mov al, 2 - out PIC_SLAVE_DATA, al - mov al, ICW4_8086 | ICW4_NORNAL_EOI | ICW4_NON_BUFFERED | ICW4_NOT_FULLY_NESTED - out PIC_MASTER_DATA, al - out PIC_SLAVE_DATA, al + ASM_BEGIN + ASM(mov al, ICW1_ICW4_NEEDED | ICW1_CASCADE | ICW1_INTERVAL8 | ICW1_EDGE | ICW1_INIT); + ASM(out PIC_MASTER_CMD, al); + ASM(out PIC_SLAVE_CMD, al); + ASM(mov al, PIC_MASTER_VECTOR_BASE); + ASM(out PIC_MASTER_DATA, al); + ASM(mov al, PIC_SLAVE_VECTOR_BASE); + ASM(out PIC_SLAVE_DATA, al); + ASM(mov al, 4); + ASM(out PIC_MASTER_DATA, al); + ASM(mov al, 2); + ASM(out PIC_SLAVE_DATA, al); + ASM(mov al, ICW4_8086 | ICW4_NORNAL_EOI | ICW4_NON_BUFFERED | ICW4_NOT_FULLY_NESTED); + ASM(out PIC_MASTER_DATA, al); + ASM(out PIC_SLAVE_DATA, al); // Mask all interrupts in the IMR (except for IRQ2 on the master) - mov al, 0xFB - out PIC_MASTER_DATA, al - add al, 4 - out PIC_SLAVE_DATA, al - } + ASM(mov al, 0xFB); + ASM(out PIC_MASTER_DATA, al); + ASM(add al, 4); + ASM(out PIC_SLAVE_DATA, al); + ASM_END } VOID HalpInitPIT() { - __asm { - mov al, PIT_COUNT_BINARY | PIT_COUNT_MODE | PIT_COUNT_16BIT | PIT_COUNT_CHAN0 - out PIT_PORT_CMD, al - mov ax, PIT_COUNTER_1MS - out PIT_CHANNEL0_DATA, al - shr ax, 8 - out PIT_CHANNEL0_DATA, al - } + ASM_BEGIN + ASM(mov al, PIT_COUNT_BINARY | PIT_COUNT_MODE | PIT_COUNT_16BIT | PIT_COUNT_CHAN0); + ASM(out PIT_PORT_CMD, al); + ASM(mov ax, PIT_COUNTER_1MS); + ASM(out PIT_CHANNEL0_DATA, al); + ASM(shr ax, 8); + ASM(out PIT_CHANNEL0_DATA, al); + ASM_END } VOID HalpInitSMCstate() @@ -150,10 +150,10 @@ VOID HalpShutdownSystem() outl(KE_ABORT, 0); while (true) { - __asm { - cli - hlt - } + ASM_BEGIN + ASM(cli); + ASM(hlt); + ASM_END } } diff --git a/nboxkrnl/hal/interrupt.cpp b/nboxkrnl/hal/interrupt.cpp index 37d49d4..489fdcb 100644 --- a/nboxkrnl/hal/interrupt.cpp +++ b/nboxkrnl/hal/interrupt.cpp @@ -110,228 +110,196 @@ VOID XBOXAPI HalpSwIntApc() { // On entry, interrupts must be disabled - __asm { - movzx eax, byte ptr[KiPcr]KPCR.Irql - mov byte ptr[KiPcr]KPCR.Irql, APC_LEVEL // raise IRQL - and HalpPendingInt, ~(1 << APC_LEVEL) - push eax - sti - call KiExecuteApcQueue - cli - pop eax - mov byte ptr[KiPcr]KPCR.Irql, al // lower IRQL - call HalpCheckUnmaskedInt - } + ASM_BEGIN + ASM(movzx eax, byte ptr[KiPcr]KPCR.Irql); + ASM(mov byte ptr[KiPcr]KPCR.Irql, APC_LEVEL); // raise IRQL + ASM(and HalpPendingInt, ~(1 << APC_LEVEL)); + ASM(push eax); + ASM(sti); + ASM(call KiExecuteApcQueue); + ASM(cli); + ASM(pop eax); + ASM(mov byte ptr[KiPcr]KPCR.Irql, al); // lower IRQL + ASM(call HalpCheckUnmaskedInt); + ASM_END } VOID __declspec(naked) XBOXAPI HalpSwIntDpc() { // On entry, interrupts must be disabled - __asm { - movzx eax, byte ptr [KiPcr]KPCR.Irql - mov byte ptr [KiPcr]KPCR.Irql, DISPATCH_LEVEL // raise IRQL - and HalpPendingInt, ~(1 << DISPATCH_LEVEL) - push eax - lea eax, [KiPcr]KPCR.PrcbData.DpcListHead - cmp eax, [eax]LIST_ENTRY.Flink - jz no_dpc - push [KiPcr]KPCR.NtTib.ExceptionList - mov dword ptr [KiPcr]KPCR.NtTib.ExceptionList, EXCEPTION_CHAIN_END2 // dword ptr required or else MSVC will aceess ExceptionList as a byte - mov eax, esp - mov esp, [KiPcr]KPCR.PrcbData.DpcStack // switch to DPC stack - push eax - call KiExecuteDpcQueue - pop esp - pop dword ptr [KiPcr]KPCR.NtTib.ExceptionList // dword ptr required or else MSVC will aceess ExceptionList as a byte + ASM_BEGIN + ASM(movzx eax, byte ptr [KiPcr]KPCR.Irql); + ASM(mov byte ptr [KiPcr]KPCR.Irql, DISPATCH_LEVEL); // raise IRQL + ASM(and HalpPendingInt, ~(1 << DISPATCH_LEVEL)); + ASM(push eax); + ASM(lea eax, [KiPcr]KPCR.PrcbData.DpcListHead); + ASM(cmp eax, [eax]LIST_ENTRY.Flink); + ASM(jz no_dpc); + ASM(push [KiPcr]KPCR.NtTib.ExceptionList); + ASM(mov dword ptr [KiPcr]KPCR.NtTib.ExceptionList, EXCEPTION_CHAIN_END2); // dword ptr required or else MSVC will aceess ExceptionList as a byte + ASM(mov eax, esp); + ASM(mov esp, [KiPcr]KPCR.PrcbData.DpcStack); // switch to DPC stack + ASM(push eax); + ASM(call KiExecuteDpcQueue); + ASM(pop esp); + ASM(pop dword ptr [KiPcr]KPCR.NtTib.ExceptionList); // dword ptr required or else MSVC will aceess ExceptionList as a byte no_dpc: - sti - cmp [KiPcr]KPCR.PrcbData.QuantumEnd, 0 - jnz quantum_end - mov eax, [KiPcr]KPCR.PrcbData.NextThread - test eax, eax - jnz thread_switch - jmp end_func + ASM(sti); + ASM(cmp [KiPcr]KPCR.PrcbData.QuantumEnd, 0); + ASM(jnz quantum_end); + ASM(mov eax, [KiPcr]KPCR.PrcbData.NextThread); + ASM(test eax, eax); + ASM(jnz thread_switch); + ASM(jmp end_func); thread_switch: - push esi - push edi - push ebx - push ebp - mov edi, eax - mov esi, [KiPcr]KPCR.PrcbData.CurrentThread - mov ecx, esi - call KeAddThreadToTailOfReadyList - mov [KiPcr]KPCR.PrcbData.CurrentThread, edi - mov dword ptr [KiPcr]KPCR.PrcbData.NextThread, 0 // dword ptr required or else MSVC will aceess NextThread as a byte - mov ebx, 1 - call KiSwapThreadContext // when this returns, it means this thread was switched back again - pop ebp - pop ebx - pop edi - pop esi - jmp end_func + ASM(push esi); + ASM(push edi); + ASM(push ebx); + ASM(push ebp); + ASM(mov edi, eax); + ASM(mov esi, [KiPcr]KPCR.PrcbData.CurrentThread); + ASM(mov ecx, esi); + ASM(call KeAddThreadToTailOfReadyList); + ASM(mov [KiPcr]KPCR.PrcbData.CurrentThread, edi); + ASM(mov dword ptr [KiPcr]KPCR.PrcbData.NextThread, 0); // dword ptr required or else MSVC will aceess NextThread as a byte + ASM(mov ebx, 1); + ASM(call KiSwapThreadContext); // when this returns, it means this thread was switched back again + ASM(pop ebp); + ASM(pop ebx); + ASM(pop edi); + ASM(pop esi); + ASM(jmp end_func); quantum_end: - mov [KiPcr]KPCR.PrcbData.QuantumEnd, 0 - call KiQuantumEnd - test eax, eax - jnz thread_switch + ASM(mov [KiPcr]KPCR.PrcbData.QuantumEnd, 0); + ASM(call KiQuantumEnd); + ASM(test eax, eax); + ASM(jnz thread_switch); end_func: - cli - pop eax - mov byte ptr [KiPcr]KPCR.Irql, al // lower IRQL - call HalpCheckUnmaskedInt - ret - } + ASM(cli); + ASM(pop eax); + ASM(mov byte ptr [KiPcr]KPCR.Irql, al); // lower IRQL + ASM(call HalpCheckUnmaskedInt); + ASM(ret); + ASM_END } VOID XBOXAPI HalpHwInt0() { - __asm { - int IDT_INT_VECTOR_BASE + 0 - } + ASM(int IDT_INT_VECTOR_BASE + 0); } VOID XBOXAPI HalpHwInt1() { - __asm { - int IDT_INT_VECTOR_BASE + 1 - } + ASM(int IDT_INT_VECTOR_BASE + 1); } VOID XBOXAPI HalpHwInt2() { - __asm { - int IDT_INT_VECTOR_BASE + 2 - } + ASM(int IDT_INT_VECTOR_BASE + 2); } VOID XBOXAPI HalpHwInt3() { - __asm { - int IDT_INT_VECTOR_BASE + 3 - } + ASM(int IDT_INT_VECTOR_BASE + 3); } VOID XBOXAPI HalpHwInt4() { - __asm { - int IDT_INT_VECTOR_BASE + 4 - } + ASM(int IDT_INT_VECTOR_BASE + 4); } VOID XBOXAPI HalpHwInt5() { - __asm { - int IDT_INT_VECTOR_BASE + 5 - } + ASM(int IDT_INT_VECTOR_BASE + 5); } VOID XBOXAPI HalpHwInt6() { - __asm { - int IDT_INT_VECTOR_BASE + 6 - } + ASM(int IDT_INT_VECTOR_BASE + 6); } VOID XBOXAPI HalpHwInt7() { - __asm { - int IDT_INT_VECTOR_BASE + 7 - } + ASM(int IDT_INT_VECTOR_BASE + 7); } VOID XBOXAPI HalpHwInt8() { - __asm { - int IDT_INT_VECTOR_BASE + 8 - } + ASM(int IDT_INT_VECTOR_BASE + 8); } VOID XBOXAPI HalpHwInt9() { - __asm { - int IDT_INT_VECTOR_BASE + 9 - } + ASM(int IDT_INT_VECTOR_BASE + 9); } VOID XBOXAPI HalpHwInt10() { - __asm { - int IDT_INT_VECTOR_BASE + 10 - } + ASM(int IDT_INT_VECTOR_BASE + 10); } VOID XBOXAPI HalpHwInt11() { - __asm { - int IDT_INT_VECTOR_BASE + 11 - } + ASM(int IDT_INT_VECTOR_BASE + 11); } VOID XBOXAPI HalpHwInt12() { - __asm { - int IDT_INT_VECTOR_BASE + 12 - } + ASM(int IDT_INT_VECTOR_BASE + 12); } VOID XBOXAPI HalpHwInt13() { - __asm { - int IDT_INT_VECTOR_BASE + 13 - } + ASM(int IDT_INT_VECTOR_BASE + 13); } VOID XBOXAPI HalpHwInt14() { - __asm { - int IDT_INT_VECTOR_BASE + 14 - } + ASM(int IDT_INT_VECTOR_BASE + 14); } VOID XBOXAPI HalpHwInt15() { - __asm { - int IDT_INT_VECTOR_BASE + 15 - } + ASM(int IDT_INT_VECTOR_BASE + 15); } VOID __declspec(naked) HalpCheckUnmaskedInt() { // On entry, interrupts must be disabled - __asm { + ASM_BEGIN check_int: - movzx ecx, byte ptr [KiPcr]KPCR.Irql - mov edx, HalpPendingInt - and edx, HalpIrqlMasks[ecx * 4] // if not zero, then there are one or more pending interrupts that have become unmasked - jnz unmasked_int - jmp exit_func + ASM(movzx ecx, byte ptr [KiPcr]KPCR.Irql); + ASM(mov edx, HalpPendingInt); + ASM(and edx, HalpIrqlMasks[ecx * 4]); // if not zero, then there are one or more pending interrupts that have become unmasked + ASM(jnz unmasked_int); + ASM(jmp exit_func); unmasked_int: - test HalpIntInProgress, ACTIVE_IRQ_MASK // make sure we complete the active IRQ first - jnz exit_func - bsr ecx, edx - cmp ecx, DISPATCH_LEVEL - jg hw_int - call SwIntHandlers[ecx * 4] - jmp check_int + ASM(test HalpIntInProgress, ACTIVE_IRQ_MASK); // make sure we complete the active IRQ first + ASM(jnz exit_func); + ASM(bsr ecx, edx); + ASM(cmp ecx, DISPATCH_LEVEL); + ASM(jg hw_int); + ASM(call SwIntHandlers[ecx * 4]); + ASM(jmp check_int); hw_int: - mov ax, HalpIntDisabled - out PIC_MASTER_DATA, al - shr ax, 8 - out PIC_SLAVE_DATA, al - mov edx, 1 - shl edx, cl - test HalpIntInProgress, edx // check again HalpIntInProgress because if a sw/hw int comes, it re-enables interrupts, and a hw int could come again - jnz exit_func - or HalpIntInProgress, edx - xor HalpPendingInt, edx - call SwIntHandlers[ecx * 4] - xor HalpIntInProgress, edx - jmp check_int + ASM(mov ax, HalpIntDisabled); + ASM(out PIC_MASTER_DATA, al); + ASM(shr ax, 8); + ASM(out PIC_SLAVE_DATA, al); + ASM(mov edx, 1); + ASM(shl edx, cl); + ASM(test HalpIntInProgress, edx); // check again HalpIntInProgress because if a sw/hw int comes, it re-enables interrupts, and a hw int could come again + ASM(jnz exit_func); + ASM(or HalpIntInProgress, edx); + ASM(xor HalpPendingInt, edx); + ASM(call SwIntHandlers[ecx * 4]); + ASM(xor HalpIntInProgress, edx); + ASM(jmp check_int); exit_func: - ret - } + ASM(ret); + ASM_END } static ULONG FASTCALL HalpCheckMaskedIntAtIRQLLevelNonSpurious(ULONG BusInterruptLevel, ULONG Irql) @@ -473,173 +441,173 @@ VOID __declspec(naked) XBOXAPI HalpInterruptCommon() // This function uses a custom calling convention, so never call it from C++ code // esi -> Interrupt - __asm { - mov dword ptr [KiPcr]KPCR.NtTib.ExceptionList, EXCEPTION_CHAIN_END2 - inc [KiPcr]KPCR.PrcbData.InterruptCount // InterruptCount: number of interrupts that have occurred - movzx ebx, byte ptr [KiPcr]KPCR.Irql - movzx eax, byte ptr [esi]KINTERRUPT.Mode - shl eax, 6 - mov ecx, [esi]KINTERRUPT.BusInterruptLevel - mov edx, [esi]KINTERRUPT.Irql - call HalpCheckMaskedIntAtIRQL[eax + ecx * 4] - test eax, eax - jz valid_int - cli - jmp end_isr + ASM_BEGIN + ASM(mov dword ptr [KiPcr]KPCR.NtTib.ExceptionList, EXCEPTION_CHAIN_END2); + ASM(inc [KiPcr]KPCR.PrcbData.InterruptCount); // InterruptCount: number of interrupts that have occurred + ASM(movzx ebx, byte ptr [KiPcr]KPCR.Irql); + ASM(movzx eax, byte ptr [esi]KINTERRUPT.Mode); + ASM(shl eax, 6); + ASM(mov ecx, [esi]KINTERRUPT.BusInterruptLevel); + ASM(mov edx, [esi]KINTERRUPT.Irql); + ASM(call HalpCheckMaskedIntAtIRQL[eax + ecx * 4]); + ASM(test eax, eax); + ASM(jz valid_int); + ASM(cli); + ASM(jmp end_isr); valid_int: - push [esi]KINTERRUPT.ServiceContext - push esi - call [esi]KINTERRUPT.ServiceRoutine // call ISR of the interrupt - cli - movzx eax, byte ptr [esi]KINTERRUPT.Mode - test eax, eax - jnz check_unmasked_int // only send eoi if level-triggered - mov eax, [esi]KINTERRUPT.BusInterruptLevel - cmp eax, 8 - jae eoi_to_slave - or eax, OCW2_EOI_IRQ - out PIC_MASTER_CMD, al - jmp check_unmasked_int + ASM(push [esi]KINTERRUPT.ServiceContext); + ASM(push esi); + ASM(call [esi]KINTERRUPT.ServiceRoutine); // call ISR of the interrupt + ASM(cli); + ASM(movzx eax, byte ptr [esi]KINTERRUPT.Mode); + ASM(test eax, eax); + ASM(jnz check_unmasked_int); // only send eoi if level-triggered + ASM(mov eax, [esi]KINTERRUPT.BusInterruptLevel); + ASM(cmp eax, 8); + ASM(jae eoi_to_slave); + ASM(or eax, OCW2_EOI_IRQ); + ASM(out PIC_MASTER_CMD, al); + ASM(jmp check_unmasked_int); eoi_to_slave: - add eax, OCW2_EOI_IRQ - 8 - out PIC_SLAVE_CMD, al + ASM(add eax, OCW2_EOI_IRQ - 8); + ASM(out PIC_SLAVE_CMD, al); check_unmasked_int: - mov byte ptr [KiPcr]KPCR.Irql, bl // lower IRQL - call HalpCheckUnmaskedInt + ASM(mov byte ptr [KiPcr]KPCR.Irql, bl); // lower IRQL + ASM(call HalpCheckUnmaskedInt); end_isr: EXIT_INTERRUPT; - } + ASM_END } VOID __declspec(naked) XBOXAPI HalpClockIsr() { - __asm { + ASM_BEGIN CREATE_KTRAP_FRAME_FOR_INT; - movzx eax, byte ptr [KiPcr]KPCR.Irql - cmp eax, CLOCK_LEVEL - jge masked_int - mov byte ptr [KiPcr]KPCR.Irql, CLOCK_LEVEL // raise IRQL - push eax - mov al, OCW2_EOI_IRQ - out PIC_MASTER_CMD, al // send eoi to master pic + ASM(movzx eax, byte ptr [KiPcr]KPCR.Irql); + ASM(cmp eax, CLOCK_LEVEL); + ASM(jge masked_int); + ASM(mov byte ptr [KiPcr]KPCR.Irql, CLOCK_LEVEL); // raise IRQL + ASM(push eax); + ASM(mov al, OCW2_EOI_IRQ); + ASM(out PIC_MASTER_CMD, al); // send eoi to master pic // Query the total execution time and clock increment. If we instead just increment the time with the xbox increment, if the host // doesn't manage to call this every ms, then the time will start to lag behind the system clock time read from the CMOS, which in turn is synchronized // with the current host time - mov edx, KE_CLOCK_INCREMENT_LOW - in eax, dx - mov esi, eax - inc edx - in eax, dx - mov edi, eax - inc edx - in eax, dx - sti - mov ecx, [KeInterruptTime]KSYSTEM_TIME.LowTime - mov edx, [KeInterruptTime]KSYSTEM_TIME.HighTime - add ecx, esi - adc edx, edi - mov [KeInterruptTime]KSYSTEM_TIME.High2Time, edx - mov [KeInterruptTime]KSYSTEM_TIME.LowTime, ecx - mov [KeInterruptTime]KSYSTEM_TIME.HighTime, edx - mov ecx, [KeSystemTime]KSYSTEM_TIME.LowTime - mov edx, [KeSystemTime]KSYSTEM_TIME.HighTime - add ecx, esi - adc edx, edi - mov [KeSystemTime]KSYSTEM_TIME.High2Time, edx - mov [KeSystemTime]KSYSTEM_TIME.LowTime, ecx - mov [KeSystemTime]KSYSTEM_TIME.HighTime, edx - mov ebx, KeTickCount - mov KeTickCount, eax - mov edi, eax - mov ecx, ebx - call KiCheckExpiredTimers - sub edi, ebx // ms elapsed since the last clock interrupt - inc [KiPcr]KPCR.PrcbData.InterruptCount // InterruptCount: number of interrupts that have occurred - mov ecx, [KiPcr]KPCR.PrcbData.CurrentThread - cmp byte ptr [esp], DISPATCH_LEVEL - jb kernel_time - ja interrupt_time - cmp [KiPcr]KPCR.PrcbData.DpcRoutineActive, 0 - jz kernel_time - add [KiPcr]KPCR.PrcbData.DpcTime, edi // DpcTime: time spent executing DPCs, in ms - jmp quantum + ASM(mov edx, KE_CLOCK_INCREMENT_LOW); + ASM(in eax, dx); + ASM(mov esi, eax); + ASM(inc edx); + ASM(in eax, dx); + ASM(mov edi, eax); + ASM(inc edx); + ASM(in eax, dx); + ASM(sti); + ASM(mov ecx, [KeInterruptTime]KSYSTEM_TIME.LowTime); + ASM(mov edx, [KeInterruptTime]KSYSTEM_TIME.HighTime); + ASM(add ecx, esi); + ASM(adc edx, edi); + ASM(mov [KeInterruptTime]KSYSTEM_TIME.High2Time, edx); + ASM(mov [KeInterruptTime]KSYSTEM_TIME.LowTime, ecx); + ASM(mov [KeInterruptTime]KSYSTEM_TIME.HighTime, edx); + ASM(mov ecx, [KeSystemTime]KSYSTEM_TIME.LowTime); + ASM(mov edx, [KeSystemTime]KSYSTEM_TIME.HighTime); + ASM(add ecx, esi); + ASM(adc edx, edi); + ASM(mov [KeSystemTime]KSYSTEM_TIME.High2Time, edx); + ASM(mov [KeSystemTime]KSYSTEM_TIME.LowTime, ecx); + ASM(mov [KeSystemTime]KSYSTEM_TIME.HighTime, edx); + ASM(mov ebx, KeTickCount); + ASM(mov KeTickCount, eax); + ASM(mov edi, eax); + ASM(mov ecx, ebx); + ASM(call KiCheckExpiredTimers); + ASM(sub edi, ebx); // ms elapsed since the last clock interrupt + ASM(inc [KiPcr]KPCR.PrcbData.InterruptCount); // InterruptCount: number of interrupts that have occurred + ASM(mov ecx, [KiPcr]KPCR.PrcbData.CurrentThread); + ASM(cmp byte ptr [esp], DISPATCH_LEVEL); + ASM(jb kernel_time); + ASM(ja interrupt_time); + ASM(cmp [KiPcr]KPCR.PrcbData.DpcRoutineActive, 0); + ASM(jz kernel_time); + ASM(add [KiPcr]KPCR.PrcbData.DpcTime, edi); // DpcTime: time spent executing DPCs, in ms + ASM(jmp quantum); interrupt_time: - add [KiPcr]KPCR.PrcbData.InterruptTime, edi // InterruptTime: time spent executing code at IRQL > 2, in ms - jmp quantum + ASM(add [KiPcr]KPCR.PrcbData.InterruptTime, edi); // InterruptTime: time spent executing code at IRQL > 2, in ms + ASM(jmp quantum); kernel_time: - add [ecx]KTHREAD.KernelTime, edi // KernelTime: per-thread time spent executing code at IRQL < 2, in ms + ASM(add [ecx]KTHREAD.KernelTime, edi); // KernelTime: per-thread time spent executing code at IRQL < 2, in ms quantum: - mov eax, CLOCK_QUANTUM_DECREMENT - mul edi // scale ms with the clock decrement - sub [ecx]KTHREAD.Quantum, eax - jg not_expired - cmp ecx, offset KiIdleThread // if it's the idle thread, then don't switch - jz not_expired - mov [KiPcr]KPCR.PrcbData.QuantumEnd, 1 - mov cl, DISPATCH_LEVEL - call HalRequestSoftwareInterrupt + ASM(mov eax, CLOCK_QUANTUM_DECREMENT); + ASM(mul edi); // scale ms with the clock decrement + ASM(sub [ecx]KTHREAD.Quantum, eax); + ASM(jg not_expired); + ASM(cmp ecx, offset KiIdleThread); // if it's the idle thread, then don't switch + ASM(jz not_expired); + ASM(mov [KiPcr]KPCR.PrcbData.QuantumEnd, 1); + ASM(mov cl, DISPATCH_LEVEL); + ASM(call HalRequestSoftwareInterrupt); not_expired: - cli - pop ecx - mov byte ptr [KiPcr]KPCR.Irql, cl // lower IRQL - call HalpCheckUnmaskedInt - jmp end_isr + ASM(cli); + ASM(pop ecx); + ASM(mov byte ptr [KiPcr]KPCR.Irql, cl); // lower IRQL + ASM(call HalpCheckUnmaskedInt); + ASM(jmp end_isr); masked_int: - mov edx, 1 - mov ecx, IRQL_OFFSET_FOR_IRQ // clock IRQ is zero - shl edx, cl - or HalpPendingInt, edx // save masked int in sw IRR, so that we can deliver it later when the IRQL goes down - mov ax, PicIRQMasksForIRQL[eax * 2] - or ax, HalpIntDisabled // mask all IRQs on the PIC with IRQL <= than current IRQL - out PIC_MASTER_DATA, al - shr ax, 8 - out PIC_SLAVE_DATA, al + ASM(mov edx, 1); + ASM(mov ecx, IRQL_OFFSET_FOR_IRQ); // clock IRQ is zero + ASM(shl edx, cl); + ASM(or HalpPendingInt, edx); // save masked int in sw IRR, so that we can deliver it later when the IRQL goes down + ASM(mov ax, PicIRQMasksForIRQL[eax * 2]); + ASM(or ax, HalpIntDisabled); // mask all IRQs on the PIC with IRQL <= than current IRQL + ASM(out PIC_MASTER_DATA, al); + ASM(shr ax, 8); + ASM(out PIC_SLAVE_DATA, al); end_isr: EXIT_INTERRUPT; - } + ASM_END } VOID __declspec(naked) XBOXAPI HalpSmbusIsr() { - __asm { + ASM_BEGIN CREATE_KTRAP_FRAME_FOR_INT; - mov al, OCW2_EOI_IRQ | 2 - out PIC_MASTER_CMD, al // send eoi to master pic - movzx eax, byte ptr [KiPcr]KPCR.Irql - cmp eax, SMBUS_LEVEL - jge masked_int - mov byte ptr [KiPcr]KPCR.Irql, SMBUS_LEVEL // raise IRQL - push eax - sti - inc [KiPcr]KPCR.PrcbData.InterruptCount // InterruptCount: number of interrupts that have occurred - xor eax, eax - mov edx, SMBUS_STATUS - in al, dx - out dx, al // clear status bits on smbus to dismiss the interrupt - push 0 - push eax - push offset HalpSmbusDpcObject - call KeInsertQueueDpc - cli - mov eax, 11 + OCW2_EOI_IRQ - 8 - out PIC_SLAVE_CMD, al // send eoi to slave pic - pop eax - mov byte ptr [KiPcr]KPCR.Irql, al // lower IRQL - call HalpCheckUnmaskedInt - jmp end_isr + ASM(mov al, OCW2_EOI_IRQ | 2); + ASM(out PIC_MASTER_CMD, al); // send eoi to master pic + ASM(movzx eax, byte ptr [KiPcr]KPCR.Irql); + ASM(cmp eax, SMBUS_LEVEL); + ASM(jge masked_int); + ASM(mov byte ptr [KiPcr]KPCR.Irql, SMBUS_LEVEL); // raise IRQL + ASM(push eax); + ASM(sti); + ASM(inc [KiPcr]KPCR.PrcbData.InterruptCount); // InterruptCount: number of interrupts that have occurred + ASM(xor eax, eax); + ASM(mov edx, SMBUS_STATUS); + ASM(in al, dx); + ASM(out dx, al); // clear status bits on smbus to dismiss the interrupt + ASM(push 0); + ASM(push eax); + ASM(push offset HalpSmbusDpcObject); + ASM(call KeInsertQueueDpc); + ASM(cli); + ASM(mov eax, 11 + OCW2_EOI_IRQ - 8); + ASM(out PIC_SLAVE_CMD, al); // send eoi to slave pic + ASM(pop eax); + ASM(mov byte ptr [KiPcr]KPCR.Irql, al); // lower IRQL + ASM(call HalpCheckUnmaskedInt); + ASM(jmp end_isr); masked_int: - mov edx, 1 - mov ecx, 11 + IRQL_OFFSET_FOR_IRQ // smbus IRQ is eleven - shl edx, cl - or HalpPendingInt, edx // save masked int in sw IRR, so that we can deliver it later when the IRQL goes down - mov ax, PicIRQMasksForIRQL[eax * 2] - or ax, HalpIntDisabled // mask all IRQs on the PIC with IRQL <= than current IRQL - out PIC_MASTER_DATA, al - shr ax, 8 - out PIC_SLAVE_DATA, al + ASM(mov edx, 1); + ASM(mov ecx, 11 + IRQL_OFFSET_FOR_IRQ); // smbus IRQ is eleven + ASM(shl edx, cl); + ASM(or HalpPendingInt, edx); // save masked int in sw IRR, so that we can deliver it later when the IRQL goes down + ASM(mov ax, PicIRQMasksForIRQL[eax * 2]); + ASM(or ax, HalpIntDisabled); // mask all IRQs on the PIC with IRQL <= than current IRQL + ASM(out PIC_MASTER_DATA, al); + ASM(shr ax, 8); + ASM(out PIC_SLAVE_DATA, al); end_isr: EXIT_INTERRUPT; - } + ASM_END } EXPORTNUM(43) VOID XBOXAPI HalEnableSystemInterrupt @@ -666,11 +634,11 @@ EXPORTNUM(43) VOID XBOXAPI HalEnableSystemInterrupt PicImr = HalpIntDisabled & 0xFF; } - __asm { - mov edx, ElcrPort - in al, dx - mov CurrElcr, al - } + ASM_BEGIN + ASM(mov edx, ElcrPort); + ASM(in al, dx); + ASM(mov CurrElcr, al); + ASM_END if (InterruptMode == Edge) { CurrElcr &= ~ElcrMask; @@ -679,15 +647,15 @@ EXPORTNUM(43) VOID XBOXAPI HalEnableSystemInterrupt CurrElcr |= ElcrMask; } - __asm { - mov edx, ElcrPort - mov al, CurrElcr - out dx, al - mov al, PicImr - mov edx, DataPort - out dx, al - sti - } + ASM_BEGIN + ASM(mov edx, ElcrPort); + ASM(mov al, CurrElcr); + ASM(out dx, al); + ASM(mov al, PicImr); + ASM(mov edx, DataPort); + ASM(out dx, al); + ASM(sti); + ASM_END } EXPORTNUM(44) ULONG XBOXAPI HalGetInterruptVector @@ -712,15 +680,15 @@ EXPORTNUM(48) VOID FASTCALL HalRequestSoftwareInterrupt { assert((Request == APC_LEVEL) || (Request == DISPATCH_LEVEL)); - __asm { - pushfd - cli - } + ASM_BEGIN + ASM(pushfd); + ASM(cli); + ASM_END HalpPendingInt |= (1 << Request); if (HalpIrqlMasks[KiPcr.Irql] & (1 << Request)) { // is the requested IRQL unmasked at the current IRQL? SwIntHandlers[Request](); } - __asm popfd + ASM(popfd); } diff --git a/nboxkrnl/ke/bug.cpp b/nboxkrnl/ke/bug.cpp index 00d61ca..3dbf101 100644 --- a/nboxkrnl/ke/bug.cpp +++ b/nboxkrnl/ke/bug.cpp @@ -40,14 +40,14 @@ VOID __declspec(naked, noinline) CDECL KeBugCheckLogEip(ULONG BugCheckCode) { // This function must be naked and never inlined because it needs to capture the return address placed on the stack by the caller - __asm { - mov eax, dword ptr [esp] - mov ecx, dword ptr [esp + 4] - push 0 - push 0 - push 0 - push eax - push ecx - call KeBugCheckEx // won't return - } + ASM_BEGIN + ASM(mov eax, dword ptr [esp]); + ASM(mov ecx, dword ptr [esp + 4]); + ASM(push 0); + ASM(push 0); + ASM(push 0); + ASM(push eax); + ASM(push ecx); + ASM(call KeBugCheckEx); // won't return + ASM_END } diff --git a/nboxkrnl/ke/irql.cpp b/nboxkrnl/ke/irql.cpp index 3666511..77fa9cf 100644 --- a/nboxkrnl/ke/irql.cpp +++ b/nboxkrnl/ke/irql.cpp @@ -10,7 +10,7 @@ EXPORTNUM(103) KIRQL XBOXAPI KeGetCurrentIrql() { - __asm movzx eax, byte ptr [KiPcr].Irql + ASM(movzx eax, byte ptr [KiPcr].Irql); } EXPORTNUM(129) KIRQL XBOXAPI KeRaiseIrqlToDpcLevel() @@ -18,22 +18,22 @@ EXPORTNUM(129) KIRQL XBOXAPI KeRaiseIrqlToDpcLevel() // This function is called frequently, so avoid forwarding to KfRaiseIrql // This function must update the irql atomically, so we use inline assembly - __asm { - movzx eax, byte ptr [KiPcr].Irql // clear the high bits to avoid returning a bogus irql - mov byte ptr [KiPcr].Irql, DISPATCH_LEVEL + ASM_BEGIN + ASM(movzx eax, byte ptr [KiPcr].Irql); // clear the high bits to avoid returning a bogus irql + ASM(mov byte ptr [KiPcr].Irql, DISPATCH_LEVEL); #if _DEBUG // Only bug check in debug builds - cmp al, DISPATCH_LEVEL - jle ok - push 0 - push 0 - push DISPATCH_LEVEL - push eax - push IRQL_NOT_GREATER_OR_EQUAL - call KeBugCheckEx + ASM(cmp al, DISPATCH_LEVEL); + ASM(jle ok); + ASM(push 0); + ASM(push 0); + ASM(push DISPATCH_LEVEL); + ASM(push eax); + ASM(push IRQL_NOT_GREATER_OR_EQUAL); + ASM(call KeBugCheckEx); ok: #endif - } + ASM_END } EXPORTNUM(130) KIRQL XBOXAPI KeRaiseIrqlToSynchLevel() @@ -48,23 +48,23 @@ EXPORTNUM(160) KIRQL FASTCALL KfRaiseIrql { // This function must update the irql atomically, so we use inline assembly - __asm { - movzx eax, byte ptr [KiPcr].Irql // clear the high bits to avoid returning a bogus irql - mov byte ptr [KiPcr].Irql, cl + ASM_BEGIN + ASM(movzx eax, byte ptr [KiPcr].Irql); // clear the high bits to avoid returning a bogus irql + ASM(mov byte ptr [KiPcr].Irql, cl); #if _DEBUG // Only bug check in debug builds - cmp al, cl - jle ok - movzx ecx, cl - push 0 - push 0 - push ecx - push eax - push IRQL_NOT_GREATER_OR_EQUAL - call KeBugCheckEx + ASM(cmp al, cl); + ASM(jle ok); + ASM(movzx ecx, cl); + ASM(push 0); + ASM(push 0); + ASM(push ecx); + ASM(push eax); + ASM(push IRQL_NOT_GREATER_OR_EQUAL); + ASM(call KeBugCheckEx); ok: #endif - } + ASM_END } EXPORTNUM(161) VOID FASTCALL KfLowerIrql @@ -74,29 +74,29 @@ EXPORTNUM(161) VOID FASTCALL KfLowerIrql { // This function must update the irql atomically, so we use inline assembly - __asm { - and ecx, 0xFF // clear the high bits to avoid using a bogus irql + ASM_BEGIN + ASM(and ecx, 0xFF); // clear the high bits to avoid using a bogus irql #if _DEBUG // Only bug check in debug builds - cmp byte ptr [KiPcr].Irql, cl - jge ok - xor eax, eax - mov al, byte ptr [KiPcr].Irql - mov byte ptr [KiPcr].Irql, HIGH_LEVEL - push 0 - push 0 - push ecx - push eax - push IRQL_NOT_LESS_OR_EQUAL - call KeBugCheckEx + ASM(cmp byte ptr [KiPcr].Irql, cl); + ASM(jge ok); + ASM(xor eax, eax); + ASM(mov al, byte ptr [KiPcr].Irql); + ASM(mov byte ptr [KiPcr].Irql, HIGH_LEVEL); + ASM(push 0); + ASM(push 0); + ASM(push ecx); + ASM(push eax); + ASM(push IRQL_NOT_LESS_OR_EQUAL); + ASM(call KeBugCheckEx); ok: #endif - pushfd - cli - mov byte ptr [KiPcr].Irql, cl - call HalpCheckUnmaskedInt - popfd - } + ASM(pushfd); + ASM(cli); + ASM(mov byte ptr [KiPcr].Irql, cl); + ASM(call HalpCheckUnmaskedInt); + ASM(popfd); + ASM_END } EXPORTNUM(163) __declspec(naked) VOID FASTCALL KiUnlockDispatcherDatabase @@ -104,51 +104,51 @@ EXPORTNUM(163) __declspec(naked) VOID FASTCALL KiUnlockDispatcherDatabase KIRQL OldIrql ) { - __asm { - mov eax, [KiPcr]KPCR.PrcbData.NextThread - test eax, eax - jz end_func // check to see if a new thread was selected by the scheduler - cmp cl, DISPATCH_LEVEL - jb thread_switch // check to see if we can context switch to the new thread - mov eax, [KiPcr]KPCR.PrcbData.DpcRoutineActive - jnz end_func // we can't, so request a dispatch interrupt if we are not running a DPC already - push ecx - mov cl, DISPATCH_LEVEL - call HalRequestSoftwareInterrupt - pop ecx - jmp end_func + ASM_BEGIN + ASM(mov eax, [KiPcr]KPCR.PrcbData.NextThread); + ASM(test eax, eax); + ASM(jz end_func); // check to see if a new thread was selected by the scheduler + ASM(cmp cl, DISPATCH_LEVEL); + ASM(jb thread_switch); // check to see if we can context switch to the new thread + ASM(mov eax, [KiPcr]KPCR.PrcbData.DpcRoutineActive); + ASM(jnz end_func); // we can't, so request a dispatch interrupt if we are not running a DPC already + ASM(push ecx); + ASM(mov cl, DISPATCH_LEVEL); + ASM(call HalRequestSoftwareInterrupt); + ASM(pop ecx); + ASM(jmp end_func); thread_switch: // Save non-volatile registers - push esi - push edi - push ebx - push ebp - mov edi, eax - mov esi, [KiPcr]KPCR.PrcbData.CurrentThread - mov byte ptr [esi]KTHREAD.WaitIrql, cl // we still need to lower the IRQL when this thread is switched back, so save it for later use - mov ecx, esi - call KeAddThreadToTailOfReadyList - mov [KiPcr]KPCR.PrcbData.CurrentThread, edi - mov dword ptr [KiPcr]KPCR.PrcbData.NextThread, 0 // dword ptr required or else MSVC will aceess NextThread as a byte - movzx ebx, byte ptr [esi]KTHREAD.WaitIrql - call KiSwapThreadContext // when this returns, it means this thread was switched back again - test eax, eax - mov cl, byte ptr [edi]KTHREAD.WaitIrql - jnz deliver_apc + ASM(push esi); + ASM(push edi); + ASM(push ebx); + ASM(push ebp); + ASM(mov edi, eax); + ASM(mov esi, [KiPcr]KPCR.PrcbData.CurrentThread); + ASM(mov byte ptr [esi]KTHREAD.WaitIrql, cl); // we still need to lower the IRQL when this thread is switched back, so save it for later use + ASM(mov ecx, esi); + ASM(call KeAddThreadToTailOfReadyList); + ASM(mov [KiPcr]KPCR.PrcbData.CurrentThread, edi); + ASM(mov dword ptr [KiPcr]KPCR.PrcbData.NextThread, 0); // dword ptr required or else MSVC will aceess NextThread as a byte + ASM(movzx ebx, byte ptr [esi]KTHREAD.WaitIrql); + ASM(call KiSwapThreadContext); // when this returns, it means this thread was switched back again + ASM(test eax, eax); + ASM(mov cl, byte ptr [edi]KTHREAD.WaitIrql); + ASM(jnz deliver_apc); restore_regs: // Restore non-volatile registers - pop ebp - pop ebx - pop edi - pop esi - jmp end_func + ASM(pop ebp); + ASM(pop ebx); + ASM(pop edi); + ASM(pop esi); + ASM(jmp end_func); deliver_apc: - mov cl, APC_LEVEL - call KfLowerIrql - call KiExecuteApcQueue - xor ecx, ecx // if KiSwapThreadContext signals an APC, then WaitIrql of the previous thread must have been zero - jmp restore_regs + ASM(mov cl, APC_LEVEL); + ASM(call KfLowerIrql); + ASM(call KiExecuteApcQueue); + ASM(xor ecx, ecx); // if KiSwapThreadContext signals an APC, then WaitIrql of the previous thread must have been zero + ASM(jmp restore_regs); end_func: - jmp KfLowerIrql - } + ASM(jmp KfLowerIrql); + ASM_END } diff --git a/nboxkrnl/ke/ke.hpp b/nboxkrnl/ke/ke.hpp index 115aa21..8a583ef 100644 --- a/nboxkrnl/ke/ke.hpp +++ b/nboxkrnl/ke/ke.hpp @@ -47,46 +47,46 @@ // These macros (or equivalent assembly code) should be used to access the members of KiPcr when the irql is below dispatch level, to make sure that // the accesses are atomic and thus thread-safe #define KeGetStackBase(var) \ - __asm { \ - __asm mov eax, [KiPcr].NtTib.StackBase \ - __asm mov var, eax \ - } + ASM_BEGIN \ + ASM(mov eax, [KiPcr].NtTib.StackBase); \ + ASM(mov var, eax); \ + ASM_END #define KeGetStackLimit(var) \ - __asm { \ - __asm mov eax, [KiPcr].NtTib.StackLimit \ - __asm mov var, eax \ - } + ASM_BEGIN \ + ASM(mov eax, [KiPcr].NtTib.StackLimit); \ + ASM(mov var, eax); \ + ASM_END #define KeGetExceptionHead(var) \ - __asm { \ - __asm mov eax, [KiPcr].NtTib.ExceptionList \ - __asm mov dword ptr var, eax \ - } + ASM_BEGIN \ + ASM(mov eax, [KiPcr].NtTib.ExceptionList); \ + ASM(mov dword ptr var, eax); \ + ASM_END #define KeSetExceptionHead(var) \ - __asm { \ - __asm mov eax, dword ptr var \ - __asm mov [KiPcr].NtTib.ExceptionList, eax \ - } + ASM_BEGIN \ + ASM(mov eax, dword ptr var); \ + ASM(mov [KiPcr].NtTib.ExceptionList, eax); \ + ASM_END #define KeResetExceptionHead(var) \ - __asm { \ - __asm mov eax, dword ptr var \ - __asm mov [KiPcr].NtTib.ExceptionList, eax \ - } + ASM_BEGIN \ + ASM(mov eax, dword ptr var); \ + ASM(mov [KiPcr].NtTib.ExceptionList, eax); \ + ASM_END #define KeGetDpcStack(var) \ - __asm { \ - __asm mov eax, [KiPcr].PrcbData.DpcStack \ - __asm mov var, eax \ - } + ASM_BEGIN \ + ASM(mov eax, [KiPcr].PrcbData.DpcStack); \ + ASM(mov var, eax); \ + ASM_END #define KeGetDpcActive(var) \ - __asm { \ - __asm mov eax, [KiPcr].PrcbData.DpcRoutineActive \ - __asm mov var, eax \ - } + ASM_BEGIN \ + ASM(mov eax, [KiPcr].PrcbData.DpcRoutineActive); \ + ASM(mov var, eax); \ + ASM_END #define INITIALIZE_GLOBAL_KEVENT(Event, Type, State) \ KEVENT Event = { \ diff --git a/nboxkrnl/ke/kernel.cpp b/nboxkrnl/ke/kernel.cpp index 8b333f3..6555ae3 100644 --- a/nboxkrnl/ke/kernel.cpp +++ b/nboxkrnl/ke/kernel.cpp @@ -60,18 +60,18 @@ EXPORTNUM(125) ULONGLONG XBOXAPI KeQueryInterruptTime() EXPORTNUM(126) ULONGLONG XBOXAPI KeQueryPerformanceCounter() { - __asm { - pushfd - cli - mov edx, KE_ACPI_TIME_LOW - in eax, dx - mov ecx, eax - inc edx - in eax, dx - mov edx, eax - mov eax, ecx - popfd - } + ASM_BEGIN + ASM(pushfd); + ASM(cli); + ASM(mov edx, KE_ACPI_TIME_LOW); + ASM(in eax, dx); + ASM(mov ecx, eax); + ASM(inc edx); + ASM(in eax, dx); + ASM(mov edx, eax); + ASM(mov eax, ecx); + ASM(popfd); + ASM_END } EXPORTNUM(127) ULONGLONG XBOXAPI KeQueryPerformanceFrequency() @@ -218,17 +218,17 @@ IoInfoBlock SubmitIoRequestToHost(ULONG Type, LONGLONG OffsetOrInitialSize, ULON ULONGLONG FASTCALL InterlockedIncrement64(volatile PULONGLONG Addend) { - __asm { - pushfd - cli - mov eax, [ecx] - mov edx, [ecx + 4] - add eax, 1 - adc edx, 0 - mov [ecx], eax - mov [ecx + 4], edx - popfd - } + ASM_BEGIN + ASM(pushfd); + ASM(cli); + ASM(mov eax, [ecx]); + ASM(mov edx, [ecx + 4]); + ASM(add eax, 1); + ASM(adc edx, 0); + ASM(mov [ecx], eax); + ASM(mov [ecx + 4], edx); + ASM(popfd); + ASM_END } NTSTATUS HostToNtStatus(IoStatus Status) diff --git a/nboxkrnl/ke/thread.cpp b/nboxkrnl/ke/thread.cpp index 1cb1d29..fd908d1 100644 --- a/nboxkrnl/ke/thread.cpp +++ b/nboxkrnl/ke/thread.cpp @@ -28,21 +28,21 @@ VOID XBOXAPI KiSuspendThread(PVOID NormalContext, PVOID SystemArgument1, PVOID S // This function is called from KiSwapThreadContext when a new thread is run for the first time // On entry, the esp points to a PKSTART_FRAME - __asm { - mov cl, PASSIVE_LEVEL - call KfLowerIrql - mov ecx, [KiPcr]KPCR.PrcbData.CurrentThread - movzx ecx, byte ptr [ecx]KTHREAD.HasTerminated // make sure that PsCreateSystemThreadEx actually succeeded - test ecx, ecx - jz thread_start - push 0xC0000017L // STATUS_NO_MEMORY - call PsTerminateSystemThread + ASM_BEGIN + ASM(mov cl, PASSIVE_LEVEL); + ASM(call KfLowerIrql); + ASM(mov ecx, [KiPcr]KPCR.PrcbData.CurrentThread); + ASM(movzx ecx, byte ptr [ecx]KTHREAD.HasTerminated); // make sure that PsCreateSystemThreadEx actually succeeded + ASM(test ecx, ecx); + ASM(jz thread_start); + ASM(push 0xC0000017L); // STATUS_NO_MEMORY + ASM(call PsTerminateSystemThread); thread_start: - pop ecx - call ecx // SystemRoutine should never return - push NORETURN_FUNCTION_RETURNED - call KeBugCheckLogEip // won't return - } + ASM(pop ecx); + ASM(call ecx); // SystemRoutine should never return + ASM(push NORETURN_FUNCTION_RETURNED); + ASM(call KeBugCheckLogEip); // won't return + ASM_END } // Source: Cxbx-Reloaded @@ -203,47 +203,47 @@ DWORD __declspec(naked) KiSwapThreadContext() // When the final ret instruction is executed, it will either point to the caller of this function of the next thread when it was last switched out, // or it will be the address of KiThreadStartup when the thread is executed for the first time ever - __asm { - mov [edi]KTHREAD.State, Running + ASM_BEGIN + ASM(mov [edi]KTHREAD.State, Running); // Construct a KSWITCHFRAME on the stack (note that RetAddr was pushed by the call instruction to this function) - or bl, bl // set zf in the saved eflags so that it will reflect the IRQL of the previous thread - pushfd // save eflags - push [KiPcr]KPCR.NtTib.ExceptionList // save per-thread exception list - cli - mov [esi]KTHREAD.KernelStack, esp // save esp + ASM(or bl, bl); // set zf in the saved eflags so that it will reflect the IRQL of the previous thread + ASM(pushfd); // save eflags + ASM(push [KiPcr]KPCR.NtTib.ExceptionList); // save per-thread exception list + ASM(cli); + ASM(mov [esi]KTHREAD.KernelStack, esp); // save esp // The floating state is saved in a lazy manner, because it's expensive to save it at every context switch. Instead of actually saving it here, we // only set flags in cr0 so that an attempt to use any fpu/mmx/sse instructions will cause a "no math coprocessor" exception, which is then handled // by the kernel in KiTrap7 and it's there where the float context is restored - mov ecx, [edi]KTHREAD.StackBase - sub ecx, SIZE FX_SAVE_AREA - mov [KiPcr]KPCR.NtTib.StackBase, ecx - mov eax, [edi]KTHREAD.StackLimit - mov [KiPcr]KPCR.NtTib.StackLimit, eax - mov eax, cr0 - and eax, ~(CR0_MP | CR0_EM | CR0_TS) - or eax, [ecx]FLOATING_SAVE_AREA.Cr0NpxState - mov cr0, eax - mov esp, [edi]KTHREAD.KernelStack // switch to the stack of the new thread -> it points to a KSWITCHFRAME - sti - inc [edi]KTHREAD.ContextSwitches // per-thread number of context switches - inc [KiPcr]KPCR.PrcbData.KeContextSwitches // total number of context switches - pop dword ptr [KiPcr]KPCR.NtTib.ExceptionList // restore exception list; NOTE: dword ptr required or else MSVC will aceess ExceptionList as a byte - cmp [edi]KTHREAD.ApcState.KernelApcPending, 0 - jnz kernel_apc - popfd // restore eflags - xor eax, eax - ret // load eip for the new thread + ASM(mov ecx, [edi]KTHREAD.StackBase); + ASM(sub ecx, SIZE FX_SAVE_AREA); + ASM(mov [KiPcr]KPCR.NtTib.StackBase, ecx); + ASM(mov eax, [edi]KTHREAD.StackLimit); + ASM(mov [KiPcr]KPCR.NtTib.StackLimit, eax); + ASM(mov eax, cr0); + ASM(and eax, ~(CR0_MP | CR0_EM | CR0_TS)); + ASM(or eax, [ecx]FLOATING_SAVE_AREA.Cr0NpxState); + ASM(mov cr0, eax); + ASM(mov esp, [edi]KTHREAD.KernelStack); // switch to the stack of the new thread -> it points to a KSWITCHFRAME + ASM(sti); + ASM(inc [edi]KTHREAD.ContextSwitches); // per-thread number of context switches + ASM(inc [KiPcr]KPCR.PrcbData.KeContextSwitches); // total number of context switches + ASM(pop dword ptr [KiPcr]KPCR.NtTib.ExceptionList); // restore exception list; NOTE: dword ptr required or else MSVC will aceess ExceptionList as a byte + ASM(cmp [edi]KTHREAD.ApcState.KernelApcPending, 0); + ASM(jnz kernel_apc); + ASM(popfd); // restore eflags + ASM(xor eax, eax); + ASM(ret); // load eip for the new thread kernel_apc: - popfd // restore eflags and read saved previous IRQL from zf - jz deliver_apc // if zero, then previous IRQL was PASSIVE so deliver an APC - mov cl, APC_LEVEL - call HalRequestSoftwareInterrupt - xor eax, eax - ret // load eip for the new thread + ASM(popfd); // restore eflags and read saved previous IRQL from zf + ASM(jz deliver_apc); // if zero, then previous IRQL was PASSIVE so deliver an APC + ASM(mov cl, APC_LEVEL); + ASM(call HalRequestSoftwareInterrupt); + ASM(xor eax, eax); + ASM(ret); // load eip for the new thread deliver_apc: - mov eax, 1 - ret // load eip for the new thread - } + ASM(mov eax, 1); + ASM(ret); // load eip for the new thread + ASM_END } static PKTHREAD XBOXAPI KiFindAndRemoveHighestPriorityThread(KPRIORITY LowPriority) @@ -255,10 +255,10 @@ static PKTHREAD XBOXAPI KiFindAndRemoveHighestPriorityThread(KPRIORITY LowPriori } KPRIORITY HighestPriority; - __asm { - bsr eax, KiReadyThreadMask - mov HighestPriority, eax - } + ASM_BEGIN + ASM(bsr eax, KiReadyThreadMask); + ASM(mov HighestPriority, eax); + ASM_END if (HighestPriority < LowPriority) { return nullptr; @@ -397,53 +397,53 @@ NTSTATUS __declspec(naked) XBOXAPI KiSwapThread() { // On entry, IRQL must be at DISPATCH_LEVEL - __asm { - mov eax, [KiPcr]KPCR.PrcbData.NextThread - test eax, eax - jnz thread_switch // check to see if a new thread was selected by the scheduler - push LOW_PRIORITY - call KiFindAndRemoveHighestPriorityThread - jnz thread_switch - lea eax, KiIdleThread + ASM_BEGIN + ASM(mov eax, [KiPcr]KPCR.PrcbData.NextThread); + ASM(test eax, eax); + ASM(jnz thread_switch); // check to see if a new thread was selected by the scheduler + ASM(push LOW_PRIORITY); + ASM(call KiFindAndRemoveHighestPriorityThread); + ASM(jnz thread_switch); + ASM(lea eax, KiIdleThread); thread_switch: // Save non-volatile registers - push esi - push edi - push ebx - push ebp - mov edi, eax - mov esi, [KiPcr]KPCR.PrcbData.CurrentThread - mov [KiPcr]KPCR.PrcbData.CurrentThread, edi - mov dword ptr [KiPcr]KPCR.PrcbData.NextThread, 0 // dword ptr required or else MSVC will access NextThread as a byte - movzx ebx, byte ptr [esi]KTHREAD.WaitIrql - call KiSwapThreadContext // when this returns, it means this thread was switched back again - test eax, eax - mov cl, byte ptr [edi]KTHREAD.WaitIrql - mov ebx, [edi]KTHREAD.WaitStatus - jnz deliver_apc + ASM(push esi); + ASM(push edi); + ASM(push ebx); + ASM(push ebp); + ASM(mov edi, eax); + ASM(mov esi, [KiPcr]KPCR.PrcbData.CurrentThread); + ASM(mov [KiPcr]KPCR.PrcbData.CurrentThread, edi); + ASM(mov dword ptr [KiPcr]KPCR.PrcbData.NextThread, 0); // dword ptr required or else MSVC will access NextThread as a byte + ASM(movzx ebx, byte ptr [esi]KTHREAD.WaitIrql); + ASM(call KiSwapThreadContext); // when this returns, it means this thread was switched back again + ASM(test eax, eax); + ASM(mov cl, byte ptr [edi]KTHREAD.WaitIrql); + ASM(mov ebx, [edi]KTHREAD.WaitStatus); + ASM(jnz deliver_apc); restore_regs: - call KfLowerIrql - mov eax, ebx + ASM(call KfLowerIrql); + ASM(mov eax, ebx); // Restore non-volatile registers - pop ebp - pop ebx - pop edi - pop esi - jmp end_func + ASM(pop ebp); + ASM(pop ebx); + ASM(pop edi); + ASM(pop esi); + ASM(jmp end_func); deliver_apc: - mov cl, APC_LEVEL - call KfLowerIrql - call KiExecuteApcQueue - xor ecx, ecx // if KiSwapThreadContext signals an APC, then WaitIrql of the previous thread must have been zero - jmp restore_regs + ASM(mov cl, APC_LEVEL); + ASM(call KfLowerIrql); + ASM(call KiExecuteApcQueue); + ASM(xor ecx, ecx); // if KiSwapThreadContext signals an APC, then WaitIrql of the previous thread must have been zero + ASM(jmp restore_regs); end_func: - ret - } + ASM(ret); + ASM_END } EXPORTNUM(104) PKTHREAD XBOXAPI KeGetCurrentThread() { - __asm mov eax, [KiPcr]KPCR.PrcbData.CurrentThread + ASM(mov eax, [KiPcr]KPCR.PrcbData.CurrentThread); } EXPORTNUM(140) ULONG XBOXAPI KeResumeThread diff --git a/nboxkrnl/kernel.hpp b/nboxkrnl/kernel.hpp index b762ac9..5d657dd 100644 --- a/nboxkrnl/kernel.hpp +++ b/nboxkrnl/kernel.hpp @@ -181,101 +181,101 @@ PLIST_ENTRY RemoveHeadList(PLIST_ENTRY pListHead); static inline VOID CDECL outl(USHORT Port, ULONG Value) { - __asm { - mov eax, Value - mov dx, Port - out dx, eax - } + ASM_BEGIN + ASM(mov eax, Value); + ASM(mov dx, Port); + ASM(out dx, eax); + ASM_END } static inline VOID CDECL outw(USHORT Port, USHORT Value) { - __asm { - mov ax, Value - mov dx, Port - out dx, ax - } + ASM_BEGIN + ASM(mov ax, Value); + ASM(mov dx, Port); + ASM(out dx, ax); + ASM_END } static inline VOID CDECL outb(USHORT Port, BYTE Value) { - __asm { - mov al, Value - mov dx, Port - out dx, al - } + ASM_BEGIN + ASM(mov al, Value); + ASM(mov dx, Port); + ASM(out dx, al); + ASM_END } static inline ULONG CDECL inl(USHORT Port) { - __asm { - mov dx, Port - in eax, dx - } + ASM_BEGIN + ASM(mov dx, Port); + ASM(in eax, dx); + ASM_END } static inline USHORT CDECL inw(USHORT Port) { - __asm { - mov dx, Port - in ax, dx - } + ASM_BEGIN + ASM(mov dx, Port); + ASM(in ax, dx); + ASM_END } static inline BYTE CDECL inb(USHORT Port) { - __asm { - mov dx, Port - in al, dx - } + ASM_BEGIN + ASM(mov dx, Port); + ASM(in al, dx); + ASM_END } static inline VOID CDECL enable() { - __asm sti + ASM(sti); } static inline VOID CDECL disable() { - __asm cli + ASM(cli); } static inline VOID CDECL atomic_store64(LONGLONG *dst, LONGLONG val) { - __asm { - pushfd - cli - } + ASM_BEGIN + ASM(pushfd); + ASM(cli); + ASM_END *dst = val; - __asm popfd + ASM(popfd); } static inline LONGLONG CDECL atomic_load64(LONGLONG *src) { - __asm { - pushfd - cli - } + ASM_BEGIN + ASM(pushfd); + ASM(cli); + ASM_END LONGLONG val = *src; - __asm popfd + ASM(popfd); return val; } static inline VOID CDECL atomic_add64(LONGLONG *dst, LONGLONG val) { - __asm { - pushfd - cli - } + ASM_BEGIN + ASM(pushfd); + ASM(cli); + ASM_END LONGLONG temp = *dst; temp += val; *dst = temp; - __asm popfd + ASM(popfd); } diff --git a/nboxkrnl/ki/hw_exp.cpp b/nboxkrnl/ki/hw_exp.cpp index c76cec4..5b7f6ff 100644 --- a/nboxkrnl/ki/hw_exp.cpp +++ b/nboxkrnl/ki/hw_exp.cpp @@ -19,15 +19,15 @@ void __declspec(naked) XBOXAPI KiTrap0() { // NOTE: the cpu raises this exception also for division overflows, but we don't check for it and always report a divide by zero code - __asm { + ASM_BEGIN CREATE_KTRAP_FRAME_NO_CODE; - sti - mov eax, 0xC0000094 // STATUS_INTEGER_DIVIDE_BY_ZERO - mov ebx, [ebp]KTRAP_FRAME.Eip + ASM(sti); + ASM(mov eax, 0xC0000094); // STATUS_INTEGER_DIVIDE_BY_ZERO + ASM(mov ebx, [ebp]KTRAP_FRAME.Eip); CREATE_EXCEPTION_RECORD_ARG0; HANDLE_EXCEPTION; EXIT_EXCEPTION; - } + ASM_END } // Debug breakpoint @@ -71,36 +71,36 @@ void __declspec(naked) XBOXAPI KiTrap7() { // If CurrentThread->NpxState == NPX_STATE_NOT_LOADED, then we are here to load the floating state for this thread. Otherwise, bug check in all other cases - __asm { + ASM_BEGIN CREATE_KTRAP_FRAME_NO_CODE; - mov edx, [KiPcr]KPCR.PrcbData.CurrentThread - cmp byte ptr [edx]KTHREAD.NpxState, NPX_STATE_LOADED - je unexpected_exp - mov eax, cr0 - and eax, ~(CR0_MP | CR0_EM | CR0_TS) // allow executing fpu instructions - mov cr0, eax - mov eax, [KiPcr]KPCR.PrcbData.NpxThread - test eax, eax - jz no_npx_thread // NpxThread can be nullptr when no thread has loaded the floating state - mov ecx, [eax]KTHREAD.StackBase - sub ecx, SIZE FX_SAVE_AREA // points to FLOATING_SAVE_AREA of NpxThread - fxsave [ecx] - mov [eax]KTHREAD.NpxState, NPX_STATE_NOT_LOADED + ASM(mov edx, [KiPcr]KPCR.PrcbData.CurrentThread); + ASM(cmp byte ptr [edx]KTHREAD.NpxState, NPX_STATE_LOADED); + ASM(je unexpected_exp); + ASM(mov eax, cr0); + ASM(and eax, ~(CR0_MP | CR0_EM | CR0_TS)); // allow executing fpu instructions + ASM(mov cr0, eax); + ASM(mov eax, [KiPcr]KPCR.PrcbData.NpxThread); + ASM(test eax, eax); + ASM(jz no_npx_thread); // NpxThread can be nullptr when no thread has loaded the floating state + ASM(mov ecx, [eax]KTHREAD.StackBase); + ASM(sub ecx, SIZE FX_SAVE_AREA); // points to FLOATING_SAVE_AREA of NpxThread + ASM(fxsave [ecx]); + ASM(mov [eax]KTHREAD.NpxState, NPX_STATE_NOT_LOADED); no_npx_thread: - mov ecx, [edx]KTHREAD.StackBase - sub ecx, SIZE FX_SAVE_AREA // points to FLOATING_SAVE_AREA of CurrentThread - fxrstor [ecx] - and dword ptr [edx]FLOATING_SAVE_AREA.Cr0NpxState, ~(CR0_MP | CR0_EM | CR0_TS) // allow executing fpu instructions for this thread only - mov [KiPcr]KPCR.PrcbData.NpxThread, edx - mov byte ptr [edx]KTHREAD.NpxState, NPX_STATE_LOADED - jmp exit_exp + ASM(mov ecx, [edx]KTHREAD.StackBase); + ASM(sub ecx, SIZE FX_SAVE_AREA); // points to FLOATING_SAVE_AREA of CurrentThread + ASM(fxrstor [ecx]); + ASM(and dword ptr [edx]FLOATING_SAVE_AREA.Cr0NpxState, ~(CR0_MP | CR0_EM | CR0_TS)); // allow executing fpu instructions for this thread only + ASM(mov [KiPcr]KPCR.PrcbData.NpxThread, edx); + ASM(mov byte ptr [edx]KTHREAD.NpxState, NPX_STATE_LOADED); + ASM(jmp exit_exp); unexpected_exp: - sti - push KERNEL_UNHANDLED_EXCEPTION - call KeBugCheckLogEip // won't return + ASM(sti); + ASM(push KERNEL_UNHANDLED_EXCEPTION); + ASM(call KeBugCheckLogEip); // won't return exit_exp: EXIT_EXCEPTION; - } + ASM_END } // Double fault @@ -136,19 +136,19 @@ void __declspec(naked) XBOXAPI KiTrap13() // Page fault void __declspec(naked) XBOXAPI KiTrap14() { - __asm { + ASM_BEGIN CREATE_KTRAP_FRAME_WITH_CODE; - push [ebp]KTRAP_FRAME.Eip - mov edx, cr2 - push edx - call MiPageFaultHandler - sti - mov eax, 0xC0000005 // STATUS_ACCESS_VIOLATION - mov ebx, [ebp]KTRAP_FRAME.Eip + ASM(push [ebp]KTRAP_FRAME.Eip); + ASM(mov edx, cr2); + ASM(push edx); + ASM(call MiPageFaultHandler); + ASM(sti); + ASM(mov eax, 0xC0000005); // STATUS_ACCESS_VIOLATION + ASM(mov ebx, [ebp]KTRAP_FRAME.Eip); CREATE_EXCEPTION_RECORD_ARG0; HANDLE_EXCEPTION; EXIT_EXCEPTION; - } + ASM_END } // Math fault @@ -188,13 +188,13 @@ VOID __declspec(naked) KiContinueService(PCONTEXT ContextRecord, BOOLEAN TestAle // ecx -> ContextRecord // edx -> TestAlert - __asm { + ASM_BEGIN CREATE_KTRAP_FRAME_NO_CODE; - sti - push ebp - call KiContinue + ASM(sti); + ASM(push ebp); + ASM(call KiContinue); EXIT_EXCEPTION; - } + ASM_END } VOID FASTCALL KiRaiseException(PEXCEPTION_RECORD ExceptionRecord, PCONTEXT ContextRecord, BOOLEAN FirstChance, PKTRAP_FRAME TrapFrame); @@ -205,41 +205,41 @@ VOID __declspec(naked) KiRaiseExceptionService(PEXCEPTION_RECORD ExceptionRecord // edx -> ContextRecord // eax -> FirstChance - __asm { + ASM_BEGIN CREATE_KTRAP_FRAME_NO_CODE; - sti - push ebp - push eax - call KiRaiseException + ASM(sti); + ASM(push ebp); + ASM(push eax); + ASM(call KiRaiseException); EXIT_EXCEPTION; - } + ASM_END } // XXX This should probably be moved in a file specific for float support static VOID KiFlushNPXState() { - __asm { - pushfd - cli - mov edx, [KiPcr]KPCR.PrcbData.CurrentThread - cmp byte ptr [edx]KTHREAD.NpxState, NPX_STATE_LOADED - jne not_loaded - mov eax, cr0 - test eax, (CR0_MP | CR0_EM | CR0_TS) - jz no_fpu_exp - and eax, ~(CR0_MP | CR0_EM | CR0_TS) - mov cr0, eax + ASM_BEGIN + ASM(pushfd); + ASM(cli); + ASM(mov edx, [KiPcr]KPCR.PrcbData.CurrentThread); + ASM(cmp byte ptr [edx]KTHREAD.NpxState, NPX_STATE_LOADED); + ASM(jne not_loaded); + ASM(mov eax, cr0); + ASM(test eax, (CR0_MP | CR0_EM | CR0_TS)); + ASM(jz no_fpu_exp); + ASM(and eax, ~(CR0_MP | CR0_EM | CR0_TS)); + ASM(mov cr0, eax); no_fpu_exp: - mov ecx, [KiPcr]KPCR.NtTib.StackBase - fxsave [ecx] - mov byte ptr [edx]KTHREAD.NpxState, NPX_STATE_NOT_LOADED - mov [KiPcr]KPCR.PrcbData.NpxThread, 0 - or eax, NPX_STATE_NOT_LOADED - or dword ptr [ecx]FLOATING_SAVE_AREA.Cr0NpxState, NPX_STATE_NOT_LOADED // block executing fpu instructions for this thread only - mov cr0, eax + ASM(mov ecx, [KiPcr]KPCR.NtTib.StackBase); + ASM(fxsave [ecx]); + ASM(mov byte ptr [edx]KTHREAD.NpxState, NPX_STATE_NOT_LOADED); + ASM(mov [KiPcr]KPCR.PrcbData.NpxThread, 0); + ASM(or eax, NPX_STATE_NOT_LOADED); + ASM(or dword ptr [ecx]FLOATING_SAVE_AREA.Cr0NpxState, NPX_STATE_NOT_LOADED); // block executing fpu instructions for this thread only + ASM(mov cr0, eax); not_loaded: - popfd - } + ASM(popfd); + ASM_END } static VOID KiCopyKframeToContext(PKTRAP_FRAME TrapFrame, PCONTEXT ContextRecord) diff --git a/nboxkrnl/ki/hw_exp.hpp b/nboxkrnl/ki/hw_exp.hpp index 07307ac..233c0c2 100644 --- a/nboxkrnl/ki/hw_exp.hpp +++ b/nboxkrnl/ki/hw_exp.hpp @@ -41,122 +41,122 @@ using PKTRAP_FRAME = KTRAP_FRAME *; // the handler. ErrCode is only pushed by the cpu for exceptions that use it, for the others an additional push must be done separately #define CREATE_KTRAP_FRAME \ - __asm { \ - __asm push ebp \ - __asm push ebx \ - __asm push esi \ - __asm push edi \ - __asm mov ebx, dword ptr fs:[0] \ - __asm push ebx \ - __asm push eax \ - __asm push ecx \ - __asm push edx \ - __asm sub esp, 24 \ - __asm mov ebp, esp \ - __asm cld \ - __asm mov ebx, [ebp]KTRAP_FRAME.Ebp \ - __asm mov edi, [ebp]KTRAP_FRAME.Eip \ - __asm mov [ebp]KTRAP_FRAME.DbgArgPointer, 0 \ - __asm mov [ebp]KTRAP_FRAME.DbgArgMark, 0xDEADBEEF \ - __asm mov [ebp]KTRAP_FRAME.DbgEip, edi \ - __asm mov [ebp]KTRAP_FRAME.DbgEbp, ebx \ - } + ASM_BEGIN \ + ASM(push ebp); \ + ASM(push ebx); \ + ASM(push esi); \ + ASM(push edi); \ + ASM(mov ebx, dword ptr fs:[0]); \ + ASM(push ebx); \ + ASM(push eax); \ + ASM(push ecx); \ + ASM(push edx); \ + ASM(sub esp, 24); \ + ASM(mov ebp, esp); \ + ASM(cld); \ + ASM(mov ebx, [ebp]KTRAP_FRAME.Ebp); \ + ASM(mov edi, [ebp]KTRAP_FRAME.Eip); \ + ASM(mov [ebp]KTRAP_FRAME.DbgArgPointer, 0); \ + ASM(mov [ebp]KTRAP_FRAME.DbgArgMark, 0xDEADBEEF); \ + ASM(mov [ebp]KTRAP_FRAME.DbgEip, edi); \ + ASM(mov [ebp]KTRAP_FRAME.DbgEbp, ebx); \ + ASM_END #define CREATE_KTRAP_FRAME_WITH_CODE \ - __asm { \ - __asm mov word ptr [esp + 2], 0 \ + ASM_BEGIN \ + ASM(mov word ptr [esp + 2], 0); \ CREATE_KTRAP_FRAME \ - } + ASM_END #define CREATE_KTRAP_FRAME_NO_CODE \ - __asm { \ - __asm push 0 \ + ASM_BEGIN \ + ASM(push 0); \ CREATE_KTRAP_FRAME \ - } + ASM_END // dword ptr required or else MSVC will aceess ExceptionList as a byte #define CREATE_KTRAP_FRAME_FOR_INT \ - __asm { \ + ASM_BEGIN \ CREATE_KTRAP_FRAME_NO_CODE \ - __asm mov dword ptr [KiPcr]KPCR.NtTib.ExceptionList, EXCEPTION_CHAIN_END2 \ - } + ASM(mov dword ptr [KiPcr]KPCR.NtTib.ExceptionList, EXCEPTION_CHAIN_END2); \ + ASM_END #define CREATE_EXCEPTION_RECORD_ARG0 \ - __asm { \ - __asm sub esp, SIZE EXCEPTION_RECORD \ - __asm mov [esp]EXCEPTION_RECORD.ExceptionCode, eax \ - __asm mov [esp]EXCEPTION_RECORD.ExceptionFlags, 0 \ - __asm mov [esp]EXCEPTION_RECORD.ExceptionRecord, 0 \ - __asm mov [esp]EXCEPTION_RECORD.ExceptionAddress, ebx \ - __asm mov [esp]EXCEPTION_RECORD.NumberParameters, 0 \ - __asm mov [esp]EXCEPTION_RECORD.ExceptionInformation[0], 0 \ - __asm mov [esp]EXCEPTION_RECORD.ExceptionInformation[1], 0 \ - } + ASM_BEGIN \ + ASM(sub esp, SIZE EXCEPTION_RECORD); \ + ASM(mov [esp]EXCEPTION_RECORD.ExceptionCode, eax); \ + ASM(mov [esp]EXCEPTION_RECORD.ExceptionFlags, 0); \ + ASM(mov [esp]EXCEPTION_RECORD.ExceptionRecord, 0); \ + ASM(mov [esp]EXCEPTION_RECORD.ExceptionAddress, ebx); \ + ASM(mov [esp]EXCEPTION_RECORD.NumberParameters, 0); \ + ASM(mov [esp]EXCEPTION_RECORD.ExceptionInformation[0], 0); \ + ASM(mov [esp]EXCEPTION_RECORD.ExceptionInformation[1], 0); \ + ASM_END #define HANDLE_EXCEPTION \ - __asm { \ - __asm mov ecx, esp \ - __asm mov edx, ebp \ - __asm push TRUE \ - __asm call offset KiDispatchException \ - } + ASM_BEGIN \ + ASM(mov ecx, esp); \ + ASM(mov edx, ebp); \ + ASM(push TRUE); \ + ASM(call offset KiDispatchException); \ + ASM_END #define EXIT_EXCEPTION \ - __asm { \ - __asm cli \ - __asm mov edx, [ebp]KTRAP_FRAME.ExceptionList \ - __asm mov dword ptr fs:[0], edx \ - __asm test [ebp]KTRAP_FRAME.SegCs, SELECTOR_MASK \ - __asm jz esp_changed \ - __asm mov eax, [ebp]KTRAP_FRAME.Eax \ - __asm mov edx, [ebp]KTRAP_FRAME.Edx \ - __asm mov ecx, [ebp]KTRAP_FRAME.Ecx \ - __asm lea esp, [ebp]KTRAP_FRAME.Edi \ - __asm pop edi \ - __asm pop esi \ - __asm pop ebx \ - __asm pop ebp \ - __asm add esp, 4 \ - __asm iretd \ - __asm esp_changed: \ - __asm mov ebx, [ebp]KTRAP_FRAME.TempSegCs \ - __asm mov [ebp]KTRAP_FRAME.SegCs, ebx \ - __asm mov ebx, [ebp]KTRAP_FRAME.TempEsp \ - __asm sub ebx, 12 \ - __asm mov [ebp]KTRAP_FRAME.ErrCode, ebx \ - __asm mov esi, [ebp]KTRAP_FRAME.EFlags \ - __asm mov [ebx + 8], esi \ - __asm mov esi, [ebp]KTRAP_FRAME.SegCs \ - __asm mov [ebx + 4], esi \ - __asm mov esi, [ebp]KTRAP_FRAME.Eip \ - __asm mov [ebx], esi \ - __asm mov eax, [ebp]KTRAP_FRAME.Eax \ - __asm mov edx, [ebp]KTRAP_FRAME.Edx \ - __asm mov ecx, [ebp]KTRAP_FRAME.Ecx \ - __asm lea esp, [ebp]KTRAP_FRAME.Edi \ - __asm pop edi \ - __asm pop esi \ - __asm pop ebx \ - __asm pop ebp \ - __asm mov esp, [esp] \ - __asm iretd \ - } + ASM_BEGIN \ + ASM(cli); \ + ASM(mov edx, [ebp]KTRAP_FRAME.ExceptionList); \ + ASM(mov dword ptr fs:[0], edx); \ + ASM(test [ebp]KTRAP_FRAME.SegCs, SELECTOR_MASK); \ + ASM(jz esp_changed); \ + ASM(mov eax, [ebp]KTRAP_FRAME.Eax); \ + ASM(mov edx, [ebp]KTRAP_FRAME.Edx); \ + ASM(mov ecx, [ebp]KTRAP_FRAME.Ecx); \ + ASM(lea esp, [ebp]KTRAP_FRAME.Edi); \ + ASM(pop edi); \ + ASM(pop esi); \ + ASM(pop ebx); \ + ASM(pop ebp); \ + ASM(add esp, 4); \ + ASM(iretd); \ + ASM(esp_changed:); \ + ASM(mov ebx, [ebp]KTRAP_FRAME.TempSegCs); \ + ASM(mov [ebp]KTRAP_FRAME.SegCs, ebx); \ + ASM(mov ebx, [ebp]KTRAP_FRAME.TempEsp); \ + ASM(sub ebx, 12); \ + ASM(mov [ebp]KTRAP_FRAME.ErrCode, ebx); \ + ASM(mov esi, [ebp]KTRAP_FRAME.EFlags); \ + ASM(mov [ebx + 8], esi); \ + ASM(mov esi, [ebp]KTRAP_FRAME.SegCs); \ + ASM(mov [ebx + 4], esi); \ + ASM(mov esi, [ebp]KTRAP_FRAME.Eip); \ + ASM(mov [ebx], esi); \ + ASM(mov eax, [ebp]KTRAP_FRAME.Eax); \ + ASM(mov edx, [ebp]KTRAP_FRAME.Edx); \ + ASM(mov ecx, [ebp]KTRAP_FRAME.Ecx); \ + ASM(lea esp, [ebp]KTRAP_FRAME.Edi); \ + ASM(pop edi); \ + ASM(pop esi); \ + ASM(pop ebx); \ + ASM(pop ebp); \ + ASM(mov esp, [esp]); \ + ASM(iretd); \ + ASM_END #define EXIT_INTERRUPT \ - __asm { \ - __asm mov edx, [ebp]KTRAP_FRAME.ExceptionList \ - __asm mov dword ptr fs:[0], edx \ - __asm mov eax, [ebp]KTRAP_FRAME.Eax \ - __asm mov edx, [ebp]KTRAP_FRAME.Edx \ - __asm mov ecx, [ebp]KTRAP_FRAME.Ecx \ - __asm lea esp, [ebp]KTRAP_FRAME.Edi \ - __asm pop edi \ - __asm pop esi \ - __asm pop ebx \ - __asm pop ebp \ - __asm add esp, 4 \ - __asm iretd \ - } + ASM_BEGIN \ + ASM(mov edx, [ebp]KTRAP_FRAME.ExceptionList); \ + ASM(mov dword ptr fs:[0], edx); \ + ASM(mov eax, [ebp]KTRAP_FRAME.Eax); \ + ASM(mov edx, [ebp]KTRAP_FRAME.Edx); \ + ASM(mov ecx, [ebp]KTRAP_FRAME.Ecx); \ + ASM(lea esp, [ebp]KTRAP_FRAME.Edi); \ + ASM(pop edi); \ + ASM(pop esi); \ + ASM(pop ebx); \ + ASM(pop ebp); \ + ASM(add esp, 4); \ + ASM(iretd); \ + ASM_END VOID XBOXAPI KiTrap0(); VOID XBOXAPI KiTrap1(); diff --git a/nboxkrnl/ki/seh.cpp b/nboxkrnl/ki/seh.cpp index 982edf1..8c1a2ad 100644 --- a/nboxkrnl/ki/seh.cpp +++ b/nboxkrnl/ki/seh.cpp @@ -21,13 +21,13 @@ EXCEPTION_DISPOSITION CDECL _nested_unwind_handler(EXCEPTION_RECORD *pExceptionR static inline void CDECL call_ebp_func(void *func, void *_ebp) { - __asm { - mov eax, func - push ebp - mov ebp, _ebp - call eax - pop ebp - } + ASM_BEGIN + ASM(mov eax, func); + ASM(push ebp); + ASM(mov ebp, _ebp); + ASM(call eax); + ASM(pop ebp); + ASM_END } void _local_unwind2(EXCEPTION_REGISTRATION_SEH *pRegistrationFrame, int stop) @@ -70,19 +70,19 @@ void _global_unwind2(EXCEPTION_REGISTRATION_SEH *pRegistrationFrame) // NOTE: RtlUnwind will trash all the non-volatile registers (save for ebp) despite being stdcall. This happens because the register context is captured with RtlCaptureContext // only after some of the function has already executed, and at that point the non-volatile registers are likely already trashed - __asm { - push ebx - push esi - push edi - push 0 - push 0 - push 0 - push pRegistrationFrame - call RtlUnwind - pop edi - pop esi - pop ebx - } + ASM_BEGIN + ASM(push ebx); + ASM(push esi); + ASM(push edi); + ASM(push 0); + ASM(push 0); + ASM(push 0); + ASM(push pRegistrationFrame); + ASM(call RtlUnwind); + ASM(pop edi); + ASM(pop esi); + ASM(pop ebx); + ASM_END } // This function must use extern "C" so that MSVC can link against our implementation of _except_handler3 when we use __try / __except in the kernel. It's also necessary @@ -92,7 +92,7 @@ extern "C" EXCEPTION_DISPOSITION CDECL _except_handler3(EXCEPTION_RECORD* pExce { // Clear the direction flag - the function triggering the exception might // have modified it, but it's expected to not be set - __asm cld + ASM(cld); if (pExceptionRecord->ExceptionFlags & (EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND)) { // We're in an unwinding pass, so unwind all local scopes @@ -120,14 +120,14 @@ extern "C" EXCEPTION_DISPOSITION CDECL _except_handler3(EXCEPTION_RECORD* pExce const DWORD _ebp = (DWORD)&pRegistrationFrame->_ebp; LONG filterResult; - __asm { - mov eax, filterFunclet - push ebp - mov ebp, _ebp - call eax - pop ebp - mov filterResult, eax - } + ASM_BEGIN + ASM(mov eax, filterFunclet); + ASM(push ebp); + ASM(mov ebp, _ebp); + ASM(call eax); + ASM(pop ebp); + ASM(mov filterResult, eax); + ASM_END if (filterResult != EXCEPTION_CONTINUE_SEARCH) { if (filterResult == EXCEPTION_CONTINUE_EXECUTION) { @@ -144,11 +144,11 @@ extern "C" EXCEPTION_DISPOSITION CDECL _except_handler3(EXCEPTION_RECORD* pExce _local_unwind2(pRegistrationFrame, currentTrylevel); pRegistrationFrame->TryLevel = newTrylevel; - __asm { - mov eax, handlerFunclet - mov ebp, scopeEbp - jmp eax // won't return - } + ASM_BEGIN + ASM(mov eax, handlerFunclet); + ASM(mov ebp, scopeEbp); + ASM(jmp eax); // won't return + ASM_END } } diff --git a/nboxkrnl/ki/seh.hpp b/nboxkrnl/ki/seh.hpp index 47c784e..ecfe761 100644 --- a/nboxkrnl/ki/seh.hpp +++ b/nboxkrnl/ki/seh.hpp @@ -73,10 +73,10 @@ inline PEXCEPTION_POINTERS __declspec(naked) GetExceptionInformation() // Retrieves excptPtrs written by _except_handler3 right below EXCEPTION_REGISTRATION_SEH // This function must be naked because it needs to use the ebp of its caller, not the ebp of this function - __asm { - mov eax, dword ptr [ebp - 20] - ret - } + ASM_BEGIN + ASM(mov eax, dword ptr [ebp - 20]); + ASM(ret); + ASM_END } inline NTSTATUS __declspec(naked) GetExceptionCode() @@ -84,10 +84,10 @@ inline NTSTATUS __declspec(naked) GetExceptionCode() // Retrieves the ExceptionCode member of EXCEPTION_RECORD pointed by ExceptionRecord of excptPtrs // This function must be naked because it needs to use the ebp of its caller, not the ebp of this function - __asm { - mov eax, dword ptr [ebp - 20] - mov eax, [eax] - mov eax, [eax] - ret - } + ASM_BEGIN + ASM(mov eax, dword ptr [ebp - 20]); + ASM(mov eax, [eax]); + ASM(mov eax, [eax]); + ASM(ret); + ASM_END } diff --git a/nboxkrnl/main.cpp b/nboxkrnl/main.cpp index 8787cf4..131b76b 100644 --- a/nboxkrnl/main.cpp +++ b/nboxkrnl/main.cpp @@ -11,59 +11,59 @@ // Assumptions: cs/ds/ss/es/fs/gs base=0 and flags=valid; physical memory and contiguous memory identity mapped with large pages; // protected mode and paging=on; cpl=0; stack=crypt keys; interrupts=off, df=0 - __asm { + ASM_BEGIN // Load the eeprom and certificate keys. The host should have passed them in the stack - mov esi, esp - mov edi, offset XboxEEPROMKey - mov ecx, 4 - rep movsd - mov edi, offset XboxCERTKey - mov ecx, 4 - rep movsd + ASM(mov esi, esp); + ASM(mov edi, offset XboxEEPROMKey); + ASM(mov ecx, 4); + ASM(rep movsd); + ASM(mov edi, offset XboxCERTKey); + ASM(mov ecx, 4); + ASM(rep movsd); // Use the global KiIdleThreadStack as the stack of the startup thread - xor ebp, ebp - mov esp, offset KiIdleThreadStack + KERNEL_STACK_SIZE - (SIZE FX_SAVE_AREA + SIZE KSTART_FRAME + SIZE KSWITCHFRAME) + ASM(xor ebp, ebp); + ASM(mov esp, offset KiIdleThreadStack + KERNEL_STACK_SIZE - (SIZE FX_SAVE_AREA + SIZE KSTART_FRAME + SIZE KSWITCHFRAME)); // Update cr0 - mov eax, cr0 - or eax, CR0_NE - mov cr0, eax + ASM(mov eax, cr0); + ASM(or eax, CR0_NE); + ASM(mov cr0, eax); // Initialize the CRT of the kernel executable - call InitializeCrt + ASM(call InitializeCrt); // Load the GDT from the hardcoded KiGdt - sub esp, 8 - mov ax, KiGdtLimit - mov word ptr [esp], ax - mov dword ptr [esp + 2], offset KiGdt - lgdt [esp] + ASM(sub esp, 8); + ASM(mov ax, KiGdtLimit); + ASM(mov word ptr [esp], ax); + ASM(mov dword ptr [esp + 2], offset KiGdt); + ASM(lgdt [esp]); // Load the segment selectors - push 0x8 - push reload_CS - _emit 0xCB + ASM(push 0x8); + ASM(push reload_CS); + ASM(_emit 0xCB); reload_CS: - mov ax, 0x10 - mov ds, ax - mov es, ax - mov ss, ax - mov gs, ax - mov ax, 0x18 - mov fs, ax + ASM(mov ax, 0x10); + ASM(mov ds, ax); + ASM(mov es, ax); + ASM(mov ss, ax); + ASM(mov gs, ax); + ASM(mov ax, 0x18); + ASM(mov fs, ax); // Load the tss from the hardcoded KiTss - mov ax, 0x20 - ltr ax + ASM(mov ax, 0x20); + ASM(ltr ax); // Load the IDT from the hardcoded KiIdt - mov ax, KiIdtLimit - mov word ptr [esp], ax - mov dword ptr [esp + 2], offset KiIdt - lidt [esp] - } + ASM(mov ax, KiIdtLimit); + ASM(mov word ptr [esp], ax); + ASM(mov dword ptr [esp + 2], offset KiIdt); + ASM(lidt [esp]); + ASM_END KiInitializeKernel(); // won't return } diff --git a/nboxkrnl/mm/mi.cpp b/nboxkrnl/mm/mi.cpp index e3106c6..7644cd7 100644 --- a/nboxkrnl/mm/mi.cpp +++ b/nboxkrnl/mm/mi.cpp @@ -10,15 +10,15 @@ VOID MiFlushEntireTlb() { - __asm { - mov eax, cr3 - mov cr3, eax - } + ASM_BEGIN + ASM(mov eax, cr3); + ASM(mov cr3, eax); + ASM_END } VOID MiFlushTlbForPage(PVOID Addr) { - __asm invlpg Addr + ASM(invlpg Addr); } PageType MiInsertPageInFreeListNoBusy(PFN_NUMBER Pfn) diff --git a/nboxkrnl/nt/services.cpp b/nboxkrnl/nt/services.cpp index 5f73df7..67ccfd0 100644 --- a/nboxkrnl/nt/services.cpp +++ b/nboxkrnl/nt/services.cpp @@ -7,19 +7,19 @@ VOID XBOXAPI ZwContinue(PCONTEXT ContextRecord, BOOLEAN TestAlert) { - __asm { - mov ecx, ContextRecord - movzx edx, TestAlert - int IDT_SERVICE_VECTOR_BASE + 8 // calls KiContinueService - } + ASM_BEGIN + ASM(mov ecx, ContextRecord); + ASM(movzx edx, TestAlert); + ASM(int IDT_SERVICE_VECTOR_BASE + 8); // calls KiContinueService + ASM_END } VOID XBOXAPI ZwRaiseException(PEXCEPTION_RECORD ExceptionRecord, PCONTEXT ContextRecord, BOOLEAN FirstChance) { - __asm { - mov ecx, ExceptionRecord - mov edx, ContextRecord - movzx eax, FirstChance - int IDT_SERVICE_VECTOR_BASE + 9 // calls KiRaiseExceptionService - } + ASM_BEGIN + ASM(mov ecx, ExceptionRecord); + ASM(mov edx, ContextRecord); + ASM(movzx eax, FirstChance); + ASM(int IDT_SERVICE_VECTOR_BASE + 9); // calls KiRaiseExceptionService + ASM_END } diff --git a/nboxkrnl/ps/ps.cpp b/nboxkrnl/ps/ps.cpp index f29839d..c4ad56c 100644 --- a/nboxkrnl/ps/ps.cpp +++ b/nboxkrnl/ps/ps.cpp @@ -161,7 +161,7 @@ EXPORTNUM(258) DLLEXPORT VOID XBOXAPI PsTerminateSystemThread } KeEnterCriticalRegion(); - __asm mov byte ptr [kThread]KTHREAD.ApcState.ApcQueueable, FALSE + ASM(mov byte ptr [kThread]KTHREAD.ApcState.ApcQueueable, FALSE); // TODO: resume thread if it was suspended KeLeaveCriticalRegion(); diff --git a/nboxkrnl/rtl/exp_sup.cpp b/nboxkrnl/rtl/exp_sup.cpp index 890ea5a..9a8e391 100644 --- a/nboxkrnl/rtl/exp_sup.cpp +++ b/nboxkrnl/rtl/exp_sup.cpp @@ -88,27 +88,27 @@ EXPORTNUM(302) __declspec(naked) VOID XBOXAPI RtlRaiseException PEXCEPTION_RECORD ExceptionRecord ) { - __asm { - push ebp - mov ebp, esp - sub esp, SIZE CONTEXT - push esp - call RtlCaptureContext - add [esp]CONTEXT.Esp, 4 // pop ExceptionRecord argument - mov [esp]CONTEXT.ContextFlags, CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS // set ContextFlags member of CONTEXT - mov eax, [ebp + 8] - mov ecx, [ebp + 4] - mov [eax]EXCEPTION_RECORD.ExceptionAddress, ecx // set ExceptionAddress member of ExceptionRecord argument to caller's eip - mov ecx, esp - push TRUE - push ecx - push [ebp + 8] - call ZwRaiseException + ASM_BEGIN + ASM(push ebp); + ASM(mov ebp, esp); + ASM(sub esp, SIZE CONTEXT); + ASM(push esp); + ASM(call RtlCaptureContext); + ASM(add [esp]CONTEXT.Esp, 4); // pop ExceptionRecord argument + ASM(mov [esp]CONTEXT.ContextFlags, CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS); // set ContextFlags member of CONTEXT + ASM(mov eax, [ebp + 8]); + ASM(mov ecx, [ebp + 4]); + ASM(mov [eax]EXCEPTION_RECORD.ExceptionAddress, ecx); // set ExceptionAddress member of ExceptionRecord argument to caller's eip + ASM(mov ecx, esp); + ASM(push TRUE); + ASM(push ecx); + ASM(push [ebp + 8]); + ASM(call ZwRaiseException); // ZwRaiseException should never return. It would only be possible if KiRaiseException fails before copying the CONTEXT to the KTRAP_FRAME, but the // function right now always succeeds - push NORETURN_FUNCTION_RETURNED - call KeBugCheckLogEip // won't return - } + ASM(push NORETURN_FUNCTION_RETURNED); + ASM(call KeBugCheckLogEip); // won't return + ASM_END } BOOLEAN XBOXAPI RtlDispatchException(PEXCEPTION_RECORD ExceptionRecord, PCONTEXT ContextRecord) @@ -204,10 +204,10 @@ EXPORTNUM(312) __declspec(noinline) VOID XBOXAPI RtlUnwind ExceptionRecord->ExceptionFlags = 0; ExceptionRecord->ExceptionRecord = nullptr; ExceptionRecord->NumberParameters = 0; - __asm { - mov eax, dword ptr [ebp + 4] - mov dword ptr [LocalExceptionRecord].ExceptionAddress, eax - } + ASM_BEGIN + ASM(mov eax, dword ptr [ebp + 4]); + ASM(mov dword ptr [LocalExceptionRecord].ExceptionAddress, eax); + ASM_END } ExceptionRecord->ExceptionFlags |= EXCEPTION_UNWINDING; @@ -280,11 +280,11 @@ EXPORTNUM(312) __declspec(noinline) VOID XBOXAPI RtlUnwind } } - __asm { - mov eax, [RegistrationPointer] - mov eax, [eax] - mov dword ptr [KiPcr].NtTib.ExceptionList, eax - } + ASM_BEGIN + ASM(mov eax, [RegistrationPointer]); + ASM(mov eax, [eax]); + ASM(mov dword ptr [KiPcr].NtTib.ExceptionList, eax); + ASM_END RegistrationPointer = RegistrationPointer->Prev; } diff --git a/nboxkrnl/rtl/rtl.cpp b/nboxkrnl/rtl/rtl.cpp index ac00888..8e7f7eb 100644 --- a/nboxkrnl/rtl/rtl.cpp +++ b/nboxkrnl/rtl/rtl.cpp @@ -49,7 +49,7 @@ EXPORTNUM(264) VOID XBOXAPI RtlAssert // NOTE: this should check for the presence of a guest debugger on the host side (such as lib86dbg) and, if present, communicate that it should hook // the breakpoint exception handler that int3 generates, so that it can take over us and start a debugging session - __asm int 3 + ASM(int 3); } EXPORTNUM(265) __declspec(naked) VOID XBOXAPI RtlCaptureContext @@ -59,33 +59,33 @@ EXPORTNUM(265) __declspec(naked) VOID XBOXAPI RtlCaptureContext { // NOTE: this function sets esp and ebp to the values they had in the caller's caller. For example, when called from RtlUnwind, it will set them to // the values used in _global_unwind2. To achieve this effect, the caller must use __declspec(noinline) and #pragma optimize("y", off) - __asm { - push ebx - mov ebx, [esp + 8] // ebx = ContextRecord; - - mov [ebx]CONTEXT.Eax, eax // ContextRecord->Eax = eax; - mov eax, [esp] // eax = original value of ebx - mov [ebx]CONTEXT.Ebx, eax // ContextRecord->Ebx = original value of ebx - mov [ebx]CONTEXT.Ecx, ecx // ContextRecord->Ecx = ecx; - mov [ebx]CONTEXT.Edx, edx // ContextRecord->Edx = edx; - mov [ebx]CONTEXT.Esi, esi // ContextRecord->Esi = esi; - mov [ebx]CONTEXT.Edi, edi // ContextRecord->Edi = edi; - - mov word ptr [ebx]CONTEXT.SegCs, cs // ContextRecord->SegCs = cs; - mov word ptr [ebx]CONTEXT.SegSs, ss // ContextRecord->SegSs = ss; - pushfd - pop [ebx]CONTEXT.EFlags // ContextRecord->EFlags = flags; - - mov eax, [ebp] // eax = old ebp; - mov [ebx]CONTEXT.Ebp, eax // ContextRecord->Ebp = ebp; - mov eax, [ebp + 4] // eax = return address; - mov [ebx]CONTEXT.Eip, eax // ContextRecord->Eip = return address; - lea eax, [ebp + 8] - mov [ebx]CONTEXT.Esp, eax // ContextRecord->Esp = original esp value; - - pop ebx - ret 4 - } + ASM_BEGIN + ASM(push ebx); + ASM(mov ebx, [esp + 8]); // ebx = ContextRecord; + + ASM(mov [ebx]CONTEXT.Eax, eax); // ContextRecord->Eax = eax; + ASM(mov eax, [esp]); // eax = original value of ebx + ASM(mov [ebx]CONTEXT.Ebx, eax); // ContextRecord->Ebx = original value of ebx + ASM(mov [ebx]CONTEXT.Ecx, ecx); // ContextRecord->Ecx = ecx; + ASM(mov [ebx]CONTEXT.Edx, edx); // ContextRecord->Edx = edx; + ASM(mov [ebx]CONTEXT.Esi, esi); // ContextRecord->Esi = esi; + ASM(mov [ebx]CONTEXT.Edi, edi); // ContextRecord->Edi = edi; + + ASM(mov word ptr [ebx]CONTEXT.SegCs, cs); // ContextRecord->SegCs = cs; + ASM(mov word ptr [ebx]CONTEXT.SegSs, ss); // ContextRecord->SegSs = ss; + ASM(pushfd); + ASM(pop [ebx]CONTEXT.EFlags); // ContextRecord->EFlags = flags; + + ASM(mov eax, [ebp]); // eax = old ebp; + ASM(mov [ebx]CONTEXT.Ebp, eax); // ContextRecord->Ebp = ebp; + ASM(mov eax, [ebp + 4]); // eax = return address; + ASM(mov [ebx]CONTEXT.Eip, eax); // ContextRecord->Eip = return address; + ASM(lea eax, [ebp + 8]); + ASM(mov [ebx]CONTEXT.Esp, eax); // ContextRecord->Esp = original esp value; + + ASM(pop ebx); + ASM(ret 4); + ASM_END } // Source: Cxbx-Reloaded @@ -148,31 +148,31 @@ EXPORTNUM(277) VOID XBOXAPI RtlEnterCriticalSection { // This function must update the members of CriticalSection atomically, so we use assembly - __asm { - mov ecx, CriticalSection - mov eax, [KiPcr]KPCR.PrcbData.CurrentThread - inc [ecx]RTL_CRITICAL_SECTION.LockCount - jnz already_owned - mov [ecx]RTL_CRITICAL_SECTION.OwningThread, eax - mov [ecx]RTL_CRITICAL_SECTION.RecursionCount, 1 - jmp end_func + ASM_BEGIN + ASM(mov ecx, CriticalSection); + ASM(mov eax, [KiPcr]KPCR.PrcbData.CurrentThread); + ASM(inc [ecx]RTL_CRITICAL_SECTION.LockCount); + ASM(jnz already_owned); + ASM(mov [ecx]RTL_CRITICAL_SECTION.OwningThread, eax); + ASM(mov [ecx]RTL_CRITICAL_SECTION.RecursionCount, 1); + ASM(jmp end_func); already_owned: - cmp [ecx]RTL_CRITICAL_SECTION.OwningThread, eax - jz owned_by_self - push eax - push 0 - push FALSE - push KernelMode - push WrExecutive - push ecx - call KeWaitForSingleObject - pop [ecx]RTL_CRITICAL_SECTION.OwningThread - mov [ecx]RTL_CRITICAL_SECTION.RecursionCount, 1 - jmp end_func + ASM(cmp [ecx]RTL_CRITICAL_SECTION.OwningThread, eax); + ASM(jz owned_by_self); + ASM(push eax); + ASM(push 0); + ASM(push FALSE); + ASM(push KernelMode); + ASM(push WrExecutive); + ASM(push ecx); + ASM(call KeWaitForSingleObject); + ASM(pop [ecx]RTL_CRITICAL_SECTION.OwningThread); + ASM(mov [ecx]RTL_CRITICAL_SECTION.RecursionCount, 1); + ASM(jmp end_func); owned_by_self: - inc [ecx]RTL_CRITICAL_SECTION.RecursionCount + ASM(inc [ecx]RTL_CRITICAL_SECTION.RecursionCount); end_func: - } + ASM_END } EXPORTNUM(278) VOID XBOXAPI RtlEnterCriticalSectionAndRegion @@ -282,22 +282,22 @@ EXPORTNUM(294) VOID XBOXAPI RtlLeaveCriticalSection { // This function must update the members of CriticalSection atomically, so we use assembly - __asm { - mov ecx, CriticalSection - dec [ecx]RTL_CRITICAL_SECTION.RecursionCount - jnz dec_count - dec [ecx]RTL_CRITICAL_SECTION.LockCount - mov [ecx]RTL_CRITICAL_SECTION.OwningThread, 0 - jl end_func - push FALSE - push PRIORITY_BOOST_EVENT - push ecx - call KeSetEvent - jmp end_func + ASM_BEGIN + ASM(mov ecx, CriticalSection); + ASM(dec [ecx]RTL_CRITICAL_SECTION.RecursionCount); + ASM(jnz dec_count); + ASM(dec [ecx]RTL_CRITICAL_SECTION.LockCount); + ASM(mov [ecx]RTL_CRITICAL_SECTION.OwningThread, 0); + ASM(jl end_func); + ASM(push FALSE); + ASM(push PRIORITY_BOOST_EVENT); + ASM(push ecx); + ASM(call KeSetEvent); + ASM(jmp end_func); dec_count: - dec [ecx]RTL_CRITICAL_SECTION.LockCount + ASM(dec [ecx]RTL_CRITICAL_SECTION.LockCount); end_func: - } + ASM_END } EXPORTNUM(295) VOID XBOXAPI RtlLeaveCriticalSectionAndRegion @@ -308,24 +308,24 @@ EXPORTNUM(295) VOID XBOXAPI RtlLeaveCriticalSectionAndRegion // NOTE: this must check RecursionCount only once, so that it can unconditionally call KeLeaveCriticalRegion if the counter is zero regardless of // its current value. This, to guard against the case where a thread switch happens after the counter is updated but before KeLeaveCriticalRegion is called - __asm { - mov ecx, CriticalSection - dec [ecx]RTL_CRITICAL_SECTION.RecursionCount - jnz dec_count - dec [ecx]RTL_CRITICAL_SECTION.LockCount - mov [ecx]RTL_CRITICAL_SECTION.OwningThread, 0 - jl not_signalled - push FALSE - push PRIORITY_BOOST_EVENT - push ecx - call KeSetEvent + ASM_BEGIN + ASM(mov ecx, CriticalSection); + ASM(dec [ecx]RTL_CRITICAL_SECTION.RecursionCount); + ASM(jnz dec_count); + ASM(dec [ecx]RTL_CRITICAL_SECTION.LockCount); + ASM(mov [ecx]RTL_CRITICAL_SECTION.OwningThread, 0); + ASM(jl not_signalled); + ASM(push FALSE); + ASM(push PRIORITY_BOOST_EVENT); + ASM(push ecx); + ASM(call KeSetEvent); not_signalled: - call KeLeaveCriticalRegion - jmp end_func + ASM(call KeLeaveCriticalRegion); + ASM(jmp end_func); dec_count: - dec [ecx]RTL_CRITICAL_SECTION.LockCount + ASM(dec [ecx]RTL_CRITICAL_SECTION.LockCount); end_func: - } + ASM_END } // Source: Cxbx-Reloaded @@ -496,7 +496,7 @@ EXPORTNUM(319) ULONG XBOXAPI RtlWalkFrameChain ULONG_PTR Stack; /* Get current EBP */ - __asm mov Stack, ebp + ASM(mov Stack, ebp); /* Get the actual stack limits */ PKTHREAD Thread = KeGetCurrentThread(); @@ -635,5 +635,5 @@ EXPORTNUM(352) VOID XBOXAPI RtlRip ULONG RtlpBitScanForward(ULONG Value) { - __asm bsf eax, Value + ASM(bsf eax, Value); } diff --git a/nboxkrnl/types.hpp b/nboxkrnl/types.hpp index 78a2250..24d9e23 100644 --- a/nboxkrnl/types.hpp +++ b/nboxkrnl/types.hpp @@ -4,6 +4,12 @@ #pragma once +// Workaround fix for using clang-format with WhitespaceSensitiveMacros option +// However, clang-format will not format inside the parentheses bracket. +#define ASM(...) __asm __VA_ARGS__ +#define ASM_BEGIN __asm { +#define ASM_END } + #include #include #include "bug_codes.hpp" diff --git a/nboxkrnl/xe/xe.cpp b/nboxkrnl/xe/xe.cpp index d0d3132..d75c770 100644 --- a/nboxkrnl/xe/xe.cpp +++ b/nboxkrnl/xe/xe.cpp @@ -43,22 +43,22 @@ static NTSTATUS XeLoadXbe() else { // NOTE: we cannot just assume that the XBE name from the DVD drive is called "default.xbe", because the user might have renamed it ULONG PathSize; - __asm { - mov edx, XE_XBE_PATH_LENGTH - in eax, dx - mov PathSize, eax - } + ASM_BEGIN + ASM(mov edx, XE_XBE_PATH_LENGTH); + ASM(in eax, dx); + ASM(mov PathSize, eax); + ASM_END PCHAR PathBuffer = (PCHAR)ExAllocatePoolWithTag(PathSize, 'PebX'); if (!PathBuffer) { return STATUS_INSUFFICIENT_RESOURCES; } - __asm { - mov edx, XE_XBE_PATH_ADDR - mov eax, PathBuffer - out dx, eax - } + ASM_BEGIN + ASM(mov edx, XE_XBE_PATH_ADDR); + ASM(mov eax, PathBuffer); + ASM(out dx, eax); + ASM_END XeImageFileName.Buffer = PathBuffer; XeImageFileName.Length = (USHORT)PathSize;