title: Why does address range 0xC0000000 ~ 0xFFFFFFFF always give 0x00 or 0xFF after switching to protected mode before enabling paging?
body: <p>I'm making a custom boot loader, and currently in the stage of enabling paging after switching to protected mode. I tried to check all memory range is usable from 0x00000000 to 0xFFFFFFFF to make sure my kernel has full control over memories. Checking is done by copying value to the memory address and printing the value through video memory(0xB8000). But the address range from 0xC0000000 to 0xFFFFFFFF always contains 0x00(if executed by QEMU) or 0xFF(if executed in real hardware through legacy booting).</p>
  
  <p>I've been searching for the reason for last 3 weeks but failed to find a clear answer. From searching, I've found some clues like physical-virtual address translation, kernel mode and user mode, MMU, reserved hardware memory range.</p>
  
  <ul>
  <li>The phenomenon is due to physical-virtual address translation.
  
  <blockquote>
    <p>The boot loader is in protected mode and paging is not enabled. So the address in the code, which is virtual(= linear) address, is translated by 1:1 mapping.</p>
  </blockquote></li>
  </ul>
  
  <p>Virtual address : 0x12345678 -> Physical address : 0x12345678</p>
  
  <p>It seems it is unrelated to the phenomenon-particular address range always containing 0x00 or 0xFF.</p>
  
  <ul>
  <li>The phenomenon is due to kernel mode and user mode.
  
  <blockquote>
    <p>There were numerous articles about kernel mode and user mode especially about linux. But my boot loader hasn't done enabled paging yet.</p>
  </blockquote></li>
  </ul>
  
  <p>Therefore, there is no rule defined such as
  - user/kernel space range
  ex)
  User memory space : 0x00000000 to 0xBFFFFFFF
  Kernel memory space : 0xC0000000 to 0xFFFFFFFF
  - how virtual memory will be mapped
  virtual memory 0x00010000 -> 0xC0010000
  - pages</p>
  
  <ul>
  <li><p>The phenomenon is due to MMU</p>
  
  <blockquote>
    <p>It seems it is related to translation, and nothing to do with particular memory range containing 0x00 or 0xFF.</p>
  </blockquote></li>
  <li><p>The phenomenon is due to reserved memory.</p>
  
  <blockquote>
    <p>I thought this as highly likely the main reason, and executed memory detection by BIOS interrupt 0x15 eax 0xE820. The result 'it was not'.
    Also, checked intel datasheet.</p>
  </blockquote></li>
  </ul>
  
  <p>Now, I have no idea why is this happening.</p>
  
  <p>Why is memory range from 0xC0000000 to 0xFFFFFFFF always contains 0x00 or 0xFF? (Describing 'always contain 0x00 or 0xFF' because I am unsure about whether
  - memory is inaccessible
  - memory is not writable
  - memory is not readable
  - etc
  )</p>
  
  <p>The result and codes are posted below.</p>
  
  <p>■ BootLoader.asm</p>
  
  <pre><code>%include "MBR.asm"
  %include "BootSector2.asm"
  </code></pre>
  
  <p>■ MBR.asm</p>
  
  <pre><code>[ORG 0x0000]
  [BITS 16]
  
  ; ──────────────────────────────────────────────────
  ; EQU
  ; ──────────────────────────────────────────────────
  
  MBRBaseAddress:     equ     0x7C00
  ReadSectorCount:    equ     0x0001
  
  ; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  ; Code Section
  ; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  
  SECTION .text
  
  MBR:
  
  ; ──────────────────────────────────────────────────
  ; Initialize Registers
  ; ──────────────────────────────────────────────────
  
      jmp     0x0000:(MBRBaseAddress + 0x0005)                                ; Initialize CS (Code Segment) Register / Absolute Far Jump / set cs = 0x0000, jump to 0x07C05 (0x7C00 + 0x0005)
  
      mov     ax, word 0x0000
      mov     ds, ax                                                          ; Initialize DS (Data Segment) Register
      mov     ss, ax                                                          ; Initialize SS (Stack Segment) Register
      mov     ax, word 0x1000
      mov     es, ax                                                          ; Initialize ES (Extra Segment) Register
      mov     ax, word 0xB800
      mov     fs, ax                                                          ; Initialize FS Register
  
      mov     ax, word 0x0000                                                 ; Initialize AX (Accumulator) Register
      mov     bx, word 0x0000                                                 ; Initialize BX (Base) Register
      mov     cx, word 0x0000                                                 ; Initialize CX (Count) Register
      mov     dx, word 0x0000                                                 ; Initialize DX (Data) Register
      mov     si, word 0x0000                                                 ; Initialize SI (Source Index) Register
      mov     di, word 0x0000                                                 ; Initialize DI (Destination Index) Register
      mov     sp, word 0xFFFE                                                 ; Initialize SP (Stack Pointer) Register
      mov     bp, word 0xFFFE                                                 ; Initialize BP (Base Pointer) Register
  
  ; ──────────────────────────────────────────────────
  ; Clear Screen
  ; ──────────────────────────────────────────────────
  
  .Clear1Digit:
  
      mov     [fs:di], word 0x0A00                                            ; [0xB800:di] 0x00 / [0xB800:di + 1] 0x0A / 0 -&gt; 0000 (Background Attribute) / A -&gt; 1010 (Text Attribute)
      add     di, 2
      cmp     di, 2 * 80 * 25                                                 ; Compare di to 2 * 80 * 25 (= 4000 = 0x0FA0)
      jl      .Clear1Digit
  
      mov     di, word 0x0000                                                 ; Clear di
  
  ; ──────────────────────────────────────────────────
  ; Print String : Real Mode String
  ; ──────────────────────────────────────────────────
  
      push    RealModeString
      push    0
      call    .PrintString
      mov     sp, bp
  
  ; ──────────────────────────────────────────────────
  ; Print String : Start Reading Sectors String
  ; ──────────────────────────────────────────────────
  
      push    StartReadingSectorsString
      push    1 * 2 * 80
      call    .PrintString
      mov     sp, bp
  
  ; ──────────────────────────────────────────────────
  ; Read Sectors (via BIOS interrupt)
  ; ──────────────────────────────────────────────────
  
  .ReadSectors:
  
      mov     si, word 0x0000                                                 ; Initialize si (Read sector count)
  
      mov     al, 1                                                           ; Initialize read sector count (1)
      mov     dl, byte 0x80                                                   ; Initialize drive to read from (Hard Disk C:)
      mov     bx, word 0x0000                                                 ; Offset to read to
      mov     ah, byte 0x02                                                   ; BIOS interrupt : Read sector
  
  .Read1Sector:
  
      mov     ch, byte [MBRBaseAddress + CylinderIndex]                       ; Set cylinder value to read from
      mov     dh, byte [MBRBaseAddress + HeadIndex]                           ; Set head value to read from
      mov     cl, byte [MBRBaseAddress + SectorIndex]                         ; Set sector value to read from
  
      cmp     si, ReadSectorCount                                             ; Compare si to ReadSectorCount
      jge     .ReadSectorsEnd                                                 ; Jump to .ReadSectorsEnd if
  
      int     0x13                                                            ; Call BIOS interrupt
  
      add     si, 1
      add     cl, 1
      mov     [MBRBaseAddress + SectorIndex], cl
      add     bx, 512
      jmp     .Read1Sector
  
  .ReadSectorsEnd:
  
  ; ──────────────────────────────────────────────────
  ; Print Value : Sectors Read Count
  ; ──────────────────────────────────────────────────
  
      push    si
      push    2 * 2 * 80
      call    .PrintValue
      mov     sp, bp
  
  ; ──────────────────────────────────────────────────
  ; Print String : Sectors Read String
  ; ──────────────────────────────────────────────────
  
      push    SectorsReadString
      push    (2 * 2 * 80) + (2 * 5)
      call    .PrintString
      mov     sp, bp
  
  ; ──────────────────────────────────────────────────
  ; Switch to Protected Mode
  ; ──────────────────────────────────────────────────
  
      cli
      lgdt    [MBRBaseAddress + GDT]
      ;mov        eax, dword 0x4000003B
      mov     eax, cr0
      or      al, 1
      mov     cr0, eax
  
      jmp     dword 0x0008:0x00010000
  
  ; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  ; Functions
  ; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  
  ; ──────────────────────────────────────────────────
  ; Print Value
  ; ──────────────────────────────────────────────────
  
  .PrintValue:
  
      push    bp                                                              ; Copy current bp to memory whose address is current sp
      mov     bp, sp                                                          ; Set new bp by current sp
  
      mov     cl, byte 12                                                     ; Initialize cl (Shift right count)
      mov     di, [bp + 4]                                                    ; Initialize di (2nd argument / Video memory offset where to print)
  
  .PrintValueLoop:
  
      mov     si, [bp + 6]                                                    ; Copy 1st argument (Value to print) to si
      shr     si, cl                                                          ; Shift right si cl times
      and     si, word 0x000F                                                 ; Keep last 4 bits and discard (fill) other bytes to 0
      mov     bl, byte [MBRBaseAddress + ASCIIString + si]                    ; Copy ASCII value, corresponding to si, to bl
      mov     [fs:di], bl                                                     ; [0xB800:di] bl / Copy 1 character to video memory
  
      sub     cl, 4
      add     di, 2
      cmp     cl, 0
      jg      .PrintValueLoop
  
      mov     si, [bp + 6]                                                    ; Copy 1st argument (Value to print) to si
      and     si, word 0x000F                                                 ; Keep last 4 bits and discard (fill) other bytes to 0
      mov     bl, byte [MBRBaseAddress + ASCIIString + si]                    ; Copy ASCII value, corresponding to si, to bl
      mov     [fs:di], bl                                                     ; [0xB800:di] bl / Copy 1 character to video memory
  
  .PrintValueEnd:
  
      pop     bp                                                              ; Copy memory whose address is current sp to bp
      ret
  
  ; ──────────────────────────────────────────────────
  ; Print String
  ; ──────────────────────────────────────────────────
  
  .PrintString:
  
      push    bp                                                              ; Copy current bp to memory whose address is current sp
      mov     bp, sp                                                          ; Set new bp by current sp
  
      mov     bx, word [bp + 6]                                               ; Initialize bx (1st argument / String offset)
      mov     si, 0                                                           ; Initialize si (String index)
      mov     di, word [bp + 4]                                               ; Initialize di (2nd argument / Video memory offset where to print)
  
  .PrintStringLoop:
  
      mov     cl, byte [MBRBaseAddress + bx + si]                             ; Copy 1 character from memory (MBRBaseAddress + String offset + String index) to cl
      cmp     cl, 0                                                           ; Compare cl to 0
      je      .PrintStringEnd
      mov     [fs:di], cl                                                     ; [0xB800:di] cl / Copy 1 character to video memory
  
      add     si, 1
      add     di, 2
      jmp     .PrintStringLoop
  
  .PrintStringEnd:
  
      pop     bp                                                              ; Copy memory whose address is current sp to bp
      ret
  
  ; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  ; Data (Read Only)
  ; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  
  ; ──────────────────────────────────────────────────
  ; ASCII String
  ; ──────────────────────────────────────────────────
  
  ASCIIString:
  
      db      '0123456789ABCDEF', 0
  
  ; ──────────────────────────────────────────────────
  ; Strings
  ; ──────────────────────────────────────────────────
  
  RealModeString:
  
      db      '[Current Mode : Real Mode]', 0
  
  StartReadingSectorsString:
  
      db      'Start Reading Sectors', 0
  
  SectorsReadString:
  
      db      'Sectors Read', 0
  
  ; ──────────────────────────────────────────────────
  ; Cylinder, Head, Sector Index
  ; ──────────────────────────────────────────────────
  
  CylinderIndex:
  
      db      0x00
  
  HeadIndex:
  
      db      0x00
  
  SectorIndex:
  
      db      0x02
  
  ; ──────────────────────────────────────────────────
  ; GDT (Global Descriptor Table)
  ; ──────────────────────────────────────────────────
  
  GDTStart:
  GDTNullDescriptor:
  
      dq      0x0000000000000000
  
  GDTCodeDescriptor:
  
      dw      0xFFFF
      dw      0x0000
      db      0x00
      db      0x9A
      db      0xCF
      db      0x00
  
  GDTDataDescriptor:
  
      dw      0xFFFF
      dw      0x0000
      db      0x00
      db      0x92
      db      0xCF
      db      0x00
  
  GDTEnd:
  GDT:
  
      dw      GDTEnd - GDTStart
      dd      MBRBaseAddress + GDTStart
  
  ; ──────────────────────────────────────────────────
  ; Declare Zeros
  ; ──────────────────────────────────────────────────
  
      times   510 - ($ - $$)  db  0x00
  
  ; ──────────────────────────────────────────────────
  ; Boot Signature
  ; ──────────────────────────────────────────────────
  
      dw      0xAA55
  </code></pre>
  
  <p>■ BootSector2.asm</p>
  
  <pre><code>[BITS 32]
  
  ; ──────────────────────────────────────────────────
  ; EQU
  ; ──────────────────────────────────────────────────
  
  BootSector2BaseOffset:      equ     0x0000FE00                              ; ※ 0x00010000 (Read sector address) - 0x00000200 (Initial label offset) = 0x0000FE00 in order to use label as if it begins from 0x00000000 [ex) BootSector2Offset (0x0000FE00) + LABEL (0x000002XX) = 0x000100XX]
  VideoMemory:                equ     0x000B8000
  
  BootSector2:
  
      mov     ax, word 0x0010
      mov     ds, ax
      mov     es, ax
      mov     fs, ax
      mov     gs, ax
      mov     ss, ax
  
      mov     eax, dword 0x000B8000
      mov     ebx, dword 0x00000000
      mov     cl, 28
      mov     esi, dword 0x00000000
      mov     edi, dword VideoMemory + (3 * 2 * 80)
      mov     esp, dword 0xFFFC0004;0xBFFFFFFC;0xC0000000 + 0x00010000 + 0x000000E4
      mov     ebp, dword 0xFFFC0004;0xBFFFFFFC;0xC0000000 + 0x00010000 + 0x000000E4
  
  .Loop1:
  
      mov     esi, esp
      shr     esi, cl
      and     esi, dword 0x0000000F
  
      mov     bl, byte [MBRBaseAddress + ASCIIString + esi]
      mov     [edi], bl
  
      sub     cl, 4
      add     edi, 2
      cmp     cl, 0
      jg      .Loop1
  
      mov     esi, esp
      and     esi, dword 0x0000000F
  
      mov     bl, byte [MBRBaseAddress + ASCIIString + esi]
      mov     [edi], bl
  
  
      mov     edi, dword VideoMemory + (4 * 2 * 80)
      push    dword 0xABCD1234
      mov     cl, 28
  
  
  .Loop2:
  
      mov     esi, esp
      shr     esi, cl
      and     esi, dword 0x0000000F
  
      mov     bl, byte [MBRBaseAddress + ASCIIString + esi]
      mov     [edi], bl
  
      sub     cl, 4
      add     edi, 2
      cmp     cl, 0
      jg      .Loop2
  
      mov     esi, esp
      and     esi, dword 0x0000000F
  
      mov     bl, byte [MBRBaseAddress + ASCIIString + esi]
      mov     [edi], bl
  
  
      mov     edi, dword VideoMemory + (5 * 2 * 80)
      mov     cl, 28
  
  .Loop3:
  
      mov     esi, dword [0xFFFC0000]
      shr     esi, cl
      and     esi, dword 0x0000000F
  
      mov     bl, byte [MBRBaseAddress + ASCIIString + esi]
      mov     [edi], bl
  
      sub     cl, 4
      add     edi, 2
      cmp     cl, 0
      jg      .Loop3
  
      mov     esi, dword [0xFFFC0000]
      and     esi, dword 0x0000000F
  
      mov     bl, byte [MBRBaseAddress + ASCIIString + esi]
      mov     [edi], bl
  
      jmp     $
  
  ; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  ; Data (Read Only)
  ; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  
  ProtectedModeString:
  
      db      '[Current Mode : Protected Mode]', 0
  
  SampleValue:
  
      dd      0x12345678
  
      times   1024 - ($ - $$) db 0x00
  </code></pre>
  
  <p><a href="https://i.stack.imgur.com/Hha2e.png" rel="nofollow noreferrer">enter image description here</a></p>
  
  <p><a href="https://i.stack.imgur.com/6Xj2q.png" rel="nofollow noreferrer">enter image description here</a></p>
  
  <p><a href="https://i.stack.imgur.com/GVjYu.jpg" rel="nofollow noreferrer">enter image description here</a></p>
  
  <p><a href="https://i.stack.imgur.com/NHxGm.png" rel="nofollow noreferrer">enter image description here</a></p>