參考來源:
Intel 64 and IA-32 Architectures Software Developer Manuals
AMD64 Architecture Programmer's Manual
當前 x86架構下,CPU第一個指令執行位置是從 0xFFFF_FFF0開始。但 CPU啟動時是 Real
Mode,照理說只能定址到 1MB位置。所以其是透過 segment register(CS)中 invisible register
的機制來達成。
一般情況下 CS的 Base值會是 Selector左移 4 bits的值,但 CPU初始時會將 CS的 Selector及
Base設成 0xF000和 0xFFFF_0000。由於 EIP初始的值為 0xFFF0,如此將初始位置指向
0xFFFF_FFF0 (0xFFFF_0000 + 0xFFF0)。
0xFFFF_FFF0 是 ROM映射的位置,所以 BIOS會將 Reset Vector程式碼放在與之相應的位置。
以16 MB(0x100_0000)的BIOS來說,其會映射在0xFF00_0000 - 0xFFFF_FFFF
用 RWEverything實際看機器上 0xFFFF_FFF0位置的值
其 machine code為0x90 0x90 0xE9,後面則是 16 bits jmp address(0xC39B)。
可與EDK2中 Reset Vector程式碼對照 UefiCpuPkg\SecCore\Ia32\ResetVec.nasmb
;
; For IA32, the reset vector must be at 0xFFFFFFF0, i.e., 4G-16 byte
; Execution starts here upon power-on/platform-reset.
;
ResetHandler:
nop
nop
ApStartup:
;
; Jmp Rel16 instruction
; Use machine code directly in case of the assembler optimization
; SEC entry point relative address will be fixed up by some build tool.
;
; Typically, SEC entry point is the function _ModuleEntryPoint() defined in
; SecEntry.asm
;
DB 0e9h
DW -3
在兩個 nop後,接 near jump 0xE9,來確保 CS selector的值不會被改變。後面預留 DW
會由 build tool來填入 SEC進入點的位址。
上圖RW看到的位址是 0xC39B,此值與當前的 IP值 0xFFF5 (0xFFFF_FFF5)相加,就能找到
SEC的進入點在 0xFFFF_C390的位置。
開始的指令為0xDB 0xE3,是 FNINIT的 machine code。