+GetApicId:\r
+ mov eax, 0\r
+ cpuid\r
+ cmp eax, 0bh\r
+ jb NoX2Apic ; CPUID level below CPUID_EXTENDED_TOPOLOGY\r
+\r
+ mov eax, 0bh\r
+ xor ecx, ecx\r
+ cpuid\r
+ test ebx, 0ffffh\r
+ jz NoX2Apic ; CPUID.0BH:EBX[15:0] is zero\r
+\r
+ ; Processor is x2APIC capable; 32-bit x2APIC ID is already in EDX\r
+ jmp GetProcessorNumber\r
+\r
+NoX2Apic:\r
+ ; Processor is not x2APIC capable, so get 8-bit APIC ID\r
+ mov eax, 1\r
+ cpuid\r
+ shr ebx, 24\r
+ mov edx, ebx\r
+\r
+GetProcessorNumber:\r
+ ;\r
+ ; Get processor number for this AP\r
+ ; Note that BSP may become an AP due to SwitchBsp()\r
+ ;\r
+ xor ebx, ebx\r
+ lea eax, [esi + CpuInfoLocation]\r
+ mov edi, [eax]\r
+\r
+GetNextProcNumber:\r
+ cmp [edi], edx ; APIC ID match?\r
+ jz ProgramStack\r
+ add edi, 20\r
+ inc ebx\r
+ jmp GetNextProcNumber \r