0

Looking at https://github.com/cfenollosa/os-tutorial/blob/master/07-bootsector-disk/boot_sect_main.asm I saw BP is init with 0x8000. But what is the correct strategy to set BP ?

  1. Should we set it to the maximum address available ?
  2. How to know (when the stack grows) that stack is not overlapping data/code from memory below ?
  3. What is the best to do ?
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
8HoLoN
  • 1,122
  • 5
  • 14
  • In 32 or 64-bit user-space, if's common for `_start` to set it to `0` as a way to detect the end of the linked-list of stack frames you get from traditional frame-pointer usage, since `_start` doesn't itself need a frame pointer. Any value that's not a valid pointer, or I guess in real mode *unlikely* to be a valid pointer, is what you want for use as a sentinel. You didn't include the code you're talking about, only link to it, so I'm assuming this value is separate from the initial SS:SP value. – Peter Cordes Nov 17 '21 at 10:00
  • How could BP be set to 0 since stack pointer decrements when it is used ?? – 8HoLoN Nov 17 '21 at 10:17
  • BP doesn't decrement when used, SP does. Looks like the code you linked is just setting SP from that initial BP, though, not doing `push 0` / `mov bp, sp` or something to terminate a linked-list of stack frames. So you're actually asking about the initial SS:SP setting. That boot sector is bad, it only sets SP without setting SS first. It could actually end up making SS:SP overlap with the 512 bytes of code, depending on what SS was. – Peter Cordes Nov 17 '21 at 10:19
  • You can't assume anything about SS or DS (or ES), and only that CS is either 0 or 0x7c0 on entry to a BIOS MBR boot sector. See [Michael Petch's bootloader tips](https://stackoverflow.com/questions/32701854/boot-loader-doesnt-jump-to-kernel-code), and [How to properly setup SS, BP and SP in x86 Real Mode?](https://stackoverflow.com/q/57237499) – Peter Cordes Nov 17 '21 at 10:22
  • Yep I have edit my answer meanwhile concerning SP decrementing. Concerning the link, it is said BP should be "high enough" so SP would never interact with other used addresses. But what is the "high enough" definition ? – 8HoLoN Nov 17 '21 at 10:23
  • Go read the answers on the linked duplicate, they explain initial ss:sp setting in detail. A good place for your stack is *below* linear address 7C00, so it grows downward toward memory you aren't using. (But most bootloaders don't need much stack space, like 512 or 4096 bytes would be more than fine for most.). As I said, whatever tutorial you're following is not a good one, it's making big assumptions about segment-register values so it probably also has other problems. Also, you haven't actually edited your question. – Peter Cordes Nov 17 '21 at 10:28
  • ok thank you for the link! (I edited my comment which said BP decrementing, the Question look fine ?) – 8HoLoN Nov 17 '21 at 10:42
  • Your question is still talking about initializing BP, not SP. It seems your real question is about where to put the stack, SS:SP. If you're just using push/pop and don't need random access to the stack, you could set BP to anything. Or you might want to use an initial sentinel value in BP which you push before setting BP=SP, like I said in my first comment. Without that code that does it "backwards" that you linked (setting BP first), there's no reason to assume that a BP value will become the initial SP value, so it would be a lot clearer to just ask about SP. – Peter Cordes Nov 17 '21 at 11:54
  • Of course your question would still be a duplicate, so it's maybe not worth the extra effort. It'll likely get deleted eventually. – Peter Cordes Nov 17 '21 at 11:55
  • Ok , I thought setting BP was mandatory so the cpu know when sp equals bp meaning the stack is empty. So you said at initialization bp has not to be (as an obligation) set with the same value as sp ? – 8HoLoN Nov 17 '21 at 13:20
  • Right, the CPU doesn't know the meaning of a concept like "the stack is empty". If you execute more pop instructions than pushes, then SP will have a higher value than it did initially, but the CPU doesn't know or care about the past. Every instruction has a well-defined effect on the architectural state (register values and memory contents) and stack operations like push/pop/call/ret, and hardware interrupts, have zero interaction with BP, just SS:SP. See https://www.felixcloutier.com/x86/pop and [how does push and pop work in assembly](https://stackoverflow.com/q/26026174) – Peter Cordes Nov 17 '21 at 13:24
  • So if when you say "If you're just using push/pop and don't need random access to the stack, you could set BP to anything", the sp address could be sub optimal ? Because if I understand well, with too many push, sp could reach 0x0000 address (and I suppose the cpu throw an interupt exception ?). So to be sure to have a known stack size, is it better to set manually bp and sp ? – 8HoLoN Nov 17 '21 at 13:28
  • Setting BP has *nothing* to do with running out of stack space or not. If you want to use local variables on the stack, x86-16 doesn't let you use addressing modes like `mov ax, [sp + 4]` so the only good way is to have BP point at stack memory as well. But as I just said, the BP value is totally unrelated to what the machine does if you `push` with SP=0. (Or the CPU pushes interrupt-return info asynchronously). – Peter Cordes Nov 17 '21 at 13:31
  • If that means SP wraps around, so be it. `pop reg` can't throw an exception in real mode, not even if `SP = 0xFFFF`. `#SS` exceptions are only possible in protected or long mode. And yes, `push` or an interrupt can wrap SP the other direction, from 0 to 0xFFFE. See [PUSH To a FULL Stack 8086 Assembly](https://stackoverflow.com/q/34563615) – Peter Cordes Nov 17 '21 at 13:34
  • Ok thank, I will need to manipulate to assimilate thoses info, before getting more details, Thank for your time! – 8HoLoN Nov 17 '21 at 13:35

0 Answers0