3

I read about how to switch from default real mode to protected mode and I wonder where the switch in my code happens. Theres one part that I copied and dont fully understand, which is this:

global loader
global stack_ptr

extern main

MODULEALIGN equ 1<<0
MEMINFO equ 1<<1
FLAGS equ MODULEALIGN | MEMINFO
MAGIC equ 0x1BADB002
CHECKSUM equ -(MAGIC + FLAGS)

section .mbheader
align 4
MultiBootHeader:
  dd MAGIC
  dd FLAGS
  dd CHECKSUM

section .text

STACKSIZE equ 0x4000

loader:
  mov esp, stack+STACKSIZE
  push eax
  push ebx

  call main

  cli ;clear interrupt flag

hang:
  hlt
  jmp hang

section .bss
align 4
stack:
  resb STACKSIZE
stack_ptr:

Since I can use the 32bit registers normally and using interupts fails I guess I am in protected mode, but I dont understand where the switch happened. And I read when using protected mode you have to set up memory paging, however is this just recommended or mandatory?

  • 6
    1. Using 32-bit registers is possible even in 16-bit modes, including Real 86 Mode. They simply use o32 and a32 prefixes to encode 32-bit operands and addressing. 2. This looks like a Multiboot specification entrypoint. Multiboot sets up 32-bit Protected Mode with all flat 4 GiB segments for you already, before transferring control to your entrypoint. 3. Paging is only possible in Protected Mode generally. However, it is not mandatory. (It is mandatory for Long Mode.) Multiboot specification says cr0 PG is off: https://www.gnu.org/software/grub/manual/multiboot/multiboot.html#Machine-state – ecm Feb 16 '21 at 08:21
  • What do you mean with "Multiboot sets up ... with all flat 4 GiB segments for you already"? – Earl of Lemongrab Mar 01 '21 at 20:07
  • Each of the six segment registers `cs`, `es`, `ss`, `ds`, `fs`, `gs` has its corresponding internal base and limit. The base points to where the "segment" starts. The limit specifies the highest address accessible in the "segment". The Multiboot specification protocol requires the loader to set up descriptors (of unspecified index values) and then initialise the segment registers using selectors so that all segment bases are set to zero and all segment limits to 0FFFF_FFFFh. This is effectively a segmentation scheme that allows ignoring segmentation, by mapping all memory flatly. – ecm Mar 01 '21 at 20:20
  • The loader that I mention here is whatever sets up the environment for your kernel and then passes control to your kernel's Multiboot specification compatible entrypoint. This can for example be GNU GRUB. The specification prescribes the environment the loader has to set up in some detail, including the PG and PE bits of `cr0` and the segment bases and limits. – ecm Mar 01 '21 at 20:24
  • How can I get the start and end of the memory segments? On osdev wiki they only really explain how to get the size of memory segments in real mode, not protected mode – Earl of Lemongrab Mar 01 '21 at 21:38
  • There is generally no way to access the base. Limit can be loaded using the `lsl` instruction. But you don't need any of that, Multiboot promises that it sets the base to zero and the limit to (32-bit) minus one. – ecm Mar 01 '21 at 22:39
  • And how to I get the parts in memory than I shouldnt use? – Earl of Lemongrab Mar 02 '21 at 07:48
  • And does this mean that I can access the full 32 adress space? Like just put a value anywhere? And I cant use the base, meaning the pointer to adress 0, but i can use the memory location 1, right? Because the ram size needs less than 32 bits when I hav 4gigs for example. – Earl of Lemongrab Mar 02 '21 at 09:34
  • Or does the memory I can use start at 1mb? I read sth about that – Earl of Lemongrab Mar 02 '21 at 09:56
  • You can use the pointer (offset) with address 0. You cannot access or check or read the actual base **value** as internally present. These two are different things. And yes you can use the full 32-bit address space. The RAM needs 32-bits to access a full 4 GiB space. The question on what parts of memory you shouldn't use is beyond the scope of this question. – ecm Mar 02 '21 at 11:56
  • I am not sure if I understood you; a pointer can be zero, but I cant access the value at adress 0? – Earl of Lemongrab Mar 02 '21 at 12:17
  • You can use a pointer that is zero and access the memory at offset zero in a segment using that pointer. You just cannot learn what linear address corresponds to offset zero of the segment. That is, what the base of the segment is. But for your entrypoint you can trust that the base is zero. – ecm Mar 02 '21 at 12:41

0 Answers0