--- /dev/null
+ TITLE CpuAsm.asm:\r
+;------------------------------------------------------------------------------\r
+;*\r
+;* Copyright 2006 - 2009, Intel Corporation\r
+;* All rights reserved. This program and the accompanying materials\r
+;* are licensed and made available under the terms and conditions of the BSD License\r
+;* which accompanies this distribution. The full text of the license may be found at\r
+;* http://opensource.org/licenses/bsd-license.php\r
+;*\r
+;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+;*\r
+;* CpuAsm.asm\r
+;*\r
+;* Abstract:\r
+;*\r
+;------------------------------------------------------------------------------\r
+\r
+ .686\r
+ .model flat,C\r
+ .code\r
+\r
+EXTRN mErrorCodeFlag:DWORD ; Error code flags for exceptions\r
+\r
+;\r
+; point to the external interrupt vector table\r
+;\r
+ExternalVectorTablePtr DWORD 0\r
+\r
+InitializeExternalVectorTablePtr PROC PUBLIC\r
+ mov eax, [esp+4]\r
+ mov ExternalVectorTablePtr, eax\r
+ ret\r
+InitializeExternalVectorTablePtr ENDP\r
+\r
+;------------------------------------------------------------------------------\r
+; VOID\r
+; SetCodeSelector (\r
+; UINT16 Selector\r
+; );\r
+;------------------------------------------------------------------------------\r
+SetCodeSelector PROC PUBLIC\r
+ mov ecx, [esp+4]\r
+ sub esp, 0x10\r
+ lea eax, setCodeSelectorLongJump\r
+ mov [esp], eax\r
+ mov [esp+4], cx\r
+ jmp fword ptr [esp]\r
+setCodeSelectorLongJump:\r
+ add esp, 0x10\r
+ ret\r
+SetCodeSelector ENDP\r
+\r
+;------------------------------------------------------------------------------\r
+; VOID\r
+; SetDataSelectors (\r
+; UINT16 Selector\r
+; );\r
+;------------------------------------------------------------------------------\r
+SetDataSelectors PROC PUBLIC\r
+ mov ecx, [esp+4]\r
+ mov ss, cx\r
+ mov ds, cx\r
+ mov es, cx\r
+ mov fs, cx\r
+ mov gs, cx\r
+ ret\r
+SetDataSelectors ENDP\r
+\r
+;---------------------------------------;\r
+; CommonInterruptEntry ;\r
+;---------------------------------------;\r
+; The follow algorithm is used for the common interrupt routine.\r
+\r
+CommonInterruptEntry PROC PUBLIC\r
+ cli\r
+ ;\r
+ ; All interrupt handlers are invoked through interrupt gates, so\r
+ ; IF flag automatically cleared at the entry point\r
+ ;\r
+\r
+ ;\r
+ ; Calculate vector number\r
+ ;\r
+ ; Get the return address of call, actually, it is the\r
+ ; address of vector number.\r
+ ;\r
+ xchg ecx, [esp]\r
+ mov cx, [ecx]\r
+ and ecx, 0FFFFh\r
+ cmp ecx, 32 ; Intel reserved vector for exceptions?\r
+ jae NoErrorCode\r
+ bt mErrorCodeFlag, ecx\r
+ jc HasErrorCode\r
+\r
+NoErrorCode:\r
+\r
+ ;\r
+ ; Stack:\r
+ ; +---------------------+\r
+ ; + EFlags +\r
+ ; +---------------------+\r
+ ; + CS +\r
+ ; +---------------------+\r
+ ; + EIP +\r
+ ; +---------------------+\r
+ ; + ECX +\r
+ ; +---------------------+ <-- ESP\r
+ ;\r
+ ; Registers:\r
+ ; ECX - Vector Number\r
+ ;\r
+\r
+ ;\r
+ ; Put Vector Number on stack\r
+ ;\r
+ push ecx\r
+\r
+ ;\r
+ ; Put 0 (dummy) error code on stack, and restore ECX\r
+ ;\r
+ xor ecx, ecx ; ECX = 0\r
+ xchg ecx, [esp+4]\r
+\r
+ jmp ErrorCodeAndVectorOnStack\r
+\r
+HasErrorCode:\r
+\r
+ ;\r
+ ; Stack:\r
+ ; +---------------------+\r
+ ; + EFlags +\r
+ ; +---------------------+\r
+ ; + CS +\r
+ ; +---------------------+\r
+ ; + EIP +\r
+ ; +---------------------+\r
+ ; + Error Code +\r
+ ; +---------------------+\r
+ ; + ECX +\r
+ ; +---------------------+ <-- ESP\r
+ ;\r
+ ; Registers:\r
+ ; ECX - Vector Number\r
+ ;\r
+\r
+ ;\r
+ ; Put Vector Number on stack and restore ECX\r
+ ;\r
+ xchg ecx, [esp]\r
+\r
+ ;\r
+ ; Fall through to join main routine code\r
+ ; at ErrorCodeAndVectorOnStack\r
+ ;\r
+@@:\r
+ jmp @B\r
+\r
+ErrorCodeAndVectorOnStack:\r
+ push ebp\r
+ mov ebp, esp\r
+\r
+ ;\r
+ ; Stack:\r
+ ; +---------------------+\r
+ ; + EFlags +\r
+ ; +---------------------+\r
+ ; + CS +\r
+ ; +---------------------+\r
+ ; + EIP +\r
+ ; +---------------------+\r
+ ; + Error Code +\r
+ ; +---------------------+\r
+ ; + Vector Number +\r
+ ; +---------------------+\r
+ ; + EBP +\r
+ ; +---------------------+ <-- EBP\r
+ ;\r
+\r
+ ;\r
+ ; Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32\r
+ ; is 16-byte aligned\r
+ ;\r
+ and esp, 0fffffff0h\r
+ sub esp, 12\r
+\r
+;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;\r
+ push eax\r
+ push ecx\r
+ push edx\r
+ push ebx\r
+ lea ecx, [ebp + 6 * 4]\r
+ push ecx ; ESP\r
+ push dword ptr [ebp] ; EBP\r
+ push esi\r
+ push edi\r
+\r
+;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;\r
+ mov eax, ss\r
+ push eax\r
+ movzx eax, word ptr [ebp + 4 * 4]\r
+ push eax\r
+ mov eax, ds\r
+ push eax\r
+ mov eax, es\r
+ push eax\r
+ mov eax, fs\r
+ push eax\r
+ mov eax, gs\r
+ push eax\r
+\r
+;; UINT32 Eip;\r
+ mov eax, [ebp + 3 * 4]\r
+ push eax\r
+\r
+;; UINT32 Gdtr[2], Idtr[2];\r
+ sub esp, 8\r
+ sidt [esp]\r
+ mov eax, [esp + 2]\r
+ xchg eax, [esp]\r
+ and eax, 0FFFFh\r
+ mov [esp+4], eax\r
+\r
+ sub esp, 8\r
+ sgdt [esp]\r
+ mov eax, [esp + 2]\r
+ xchg eax, [esp]\r
+ and eax, 0FFFFh\r
+ mov [esp+4], eax\r
+\r
+;; UINT32 Ldtr, Tr;\r
+ xor eax, eax\r
+ str ax\r
+ push eax\r
+ sldt ax\r
+ push eax\r
+\r
+;; UINT32 EFlags;\r
+ mov eax, [ebp + 5 * 4]\r
+ push eax\r
+\r
+;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;\r
+ mov eax, cr4\r
+ or eax, 208h\r
+ mov cr4, eax\r
+ push eax\r
+ mov eax, cr3\r
+ push eax\r
+ mov eax, cr2\r
+ push eax\r
+ xor eax, eax\r
+ push eax\r
+ mov eax, cr0\r
+ push eax\r
+\r
+;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+ mov eax, dr7\r
+ push eax\r
+;; clear Dr7 while executing debugger itself\r
+ xor eax, eax\r
+ mov dr7, eax\r
+\r
+ mov eax, dr6\r
+ push eax\r
+;; insure all status bits in dr6 are clear...\r
+ xor eax, eax\r
+ mov dr6, eax\r
+\r
+ mov eax, dr3\r
+ push eax\r
+ mov eax, dr2\r
+ push eax\r
+ mov eax, dr1\r
+ push eax\r
+ mov eax, dr0\r
+ push eax\r
+\r
+;; FX_SAVE_STATE_IA32 FxSaveState;\r
+ sub esp, 512\r
+ mov edi, esp\r
+ db 0fh, 0aeh, 07h ;fxsave [edi]\r
+\r
+;; UINT32 ExceptionData;\r
+ push dword ptr [ebp + 2 * 4]\r
+\r
+;; call into exception handler\r
+ mov eax, ExternalVectorTablePtr ; get the interrupt vectors base\r
+ or eax, eax ; NULL?\r
+ jz nullExternalExceptionHandler\r
+\r
+ mov ecx, [ebp + 4]\r
+ mov eax, [eax + ecx * 4]\r
+ or eax, eax ; NULL?\r
+ jz nullExternalExceptionHandler\r
+\r
+;; Prepare parameter and call\r
+ mov edx, esp\r
+ push edx\r
+ mov edx, dword ptr [ebp + 1 * 4]\r
+ push edx\r
+\r
+ ;\r
+ ; Call External Exception Handler\r
+ ;\r
+ call eax\r
+ add esp, 8\r
+\r
+nullExternalExceptionHandler:\r
+\r
+ cli\r
+;; UINT32 ExceptionData;\r
+ add esp, 4\r
+\r
+;; FX_SAVE_STATE_IA32 FxSaveState;\r
+ mov esi, esp\r
+ db 0fh, 0aeh, 0eh ; fxrstor [esi]\r
+ add esp, 512\r
+\r
+;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+ pop eax\r
+ mov dr0, eax\r
+ pop eax\r
+ mov dr1, eax\r
+ pop eax\r
+ mov dr2, eax\r
+ pop eax\r
+ mov dr3, eax\r
+;; skip restore of dr6. We cleared dr6 during the context save.\r
+ add esp, 4\r
+ pop eax\r
+ mov dr7, eax\r
+\r
+;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;\r
+ pop eax\r
+ mov cr0, eax\r
+ add esp, 4 ; not for Cr1\r
+ pop eax\r
+ mov cr2, eax\r
+ pop eax\r
+ mov cr3, eax\r
+ pop eax\r
+ mov cr4, eax\r
+\r
+;; UINT32 EFlags;\r
+ pop dword ptr [ebp + 5 * 4]\r
+\r
+;; UINT32 Ldtr, Tr;\r
+;; UINT32 Gdtr[2], Idtr[2];\r
+;; Best not let anyone mess with these particular registers...\r
+ add esp, 24\r
+\r
+;; UINT32 Eip;\r
+ pop dword ptr [ebp + 3 * 4]\r
+\r
+;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;\r
+;; NOTE - modified segment registers could hang the debugger... We\r
+;; could attempt to insulate ourselves against this possibility,\r
+;; but that poses risks as well.\r
+;;\r
+ pop gs\r
+ pop fs\r
+ pop es\r
+ pop ds\r
+ pop dword ptr [ebp + 4 * 4]\r
+ pop ss\r
+\r
+;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;\r
+ pop edi\r
+ pop esi\r
+ add esp, 4 ; not for ebp\r
+ add esp, 4 ; not for esp\r
+ pop ebx\r
+ pop edx\r
+ pop ecx\r
+ pop eax\r
+\r
+ mov esp, ebp\r
+ pop ebp\r
+ add esp, 8\r
+ iretd\r
+\r
+CommonInterruptEntry ENDP\r
+\r
+END\r