check_a20_wraparound: .prolog: push dword esi sub esp, 64 mov esi, esp ; EAX is used for the return value, ; so it doesn't have to be preserved. mov [esi + (64 - 8)], ebx mov [esi + (64 - 12)], edi .test_a20: ; Save the values which are going to be overwritten mov edi, 0x0800 mov eax, [edi] mov edi, 0x00100800 mov ebx, [edi] ; Write to two locations which, if A20 wraps around, ; will both be written to by the second statement. ; Write 0 to 0x08000 to avoid the unlikely case that ; those bytes are there coincidentally and A20 is on. mov edi, 0x0800 mov [edi], dword 0x00000000 mov edi, 0x00100800 mov [edi], dword 0xffaa00dd ; Check the lower address (which should NOT contain) ; this value for the value. If it does contain it, the ; memory space wraps around to 0 every 2^19 bytes. cmp [0x0800], dword 0xffaa00dd je .return_a20_not_enabled ; If the value at 0x0800 ; was written to instead ; (or at the same time) of ; writing to 0x100800, ; the A20 wasn't enabled. ; Reset the values at the addresses to which the test ; values were written znd return that A20 is enabled. mov edi, 0x0800 mov [edi], eax mov edi, 0x00100800 mov [edi], ebx .return_a20_enabled: mov eax, 1 ; Restore the one used register which ; doesn't contain the return value. mov ebx, [esi + (64 - 8)] add esp, 64 pop dword esi ret .return_a20_not_enabled: ; It's only necessary to write to one of the addresses ; as both of them are equal either way. mov edi, 0x0800 mov [edi], eax mov eax, 0 ; Restore the one used register which ; doesn't contain the return value. mov ebx, [esi + (64 - 12)] mov edi, [esi + (64 - 8)] add esp, 64 pop dword esi ret enable_a20_through_keyboard_controller: .prolog: push dword esi sub esp, 64 mov esi, esp mov [esi + (64 - 8)], ebx mov [esi + (64 - 12)], ecx mov [esi + (64 - 16)], edx mov [esi + (64 - 20)], edi .epilog: mov ebx, [esi + (64 - 8)] mov ecx, [esi + (64 - 12)] mov edx, [esi + (64 - 16)] mov edi, [esi + (64 - 20)] add esp, 64 pop dword esi ret