Page 1 of 3
MBR Relocation
Posted: Tue Mar 20, 2012 5:04 am
by mark3094
I'm developing an MBR on x86, and I'm having some trouble getting it to successfully relocate itself in memory. I'm using NASM as the assembler
So far, I have this:
Code: Select all
mov si, Code ;set SI to code area
mov di, 0x0600 ;set DI to some location (destination)
push word 0x0000 ;segment
push word 0x0600 ;offset
cld
mov cx, 0x0200
rep movsb
retf
Code:
[i]More code here - print to screen and hang[/i]
There is also an 'ORG 0x7c00' and some stack setup preceeding this.
This seems to work fine, as it prints to screen and hangs as expected.
The problem comes with my next phase. I am using int13 and ah=42h to read a sector into memory. This is just a 'garbage' sector for now (I don't jump to it), as I'm just testing. Whenever I read a sector to 0x7c00, it doesn't print to screen, or prints garbage. Reading to other locations is fine.
I think I'm not relocating my boot sector correctly, and int13 is overwriting running code in memory. Does this sound right? Any pointers to get me in the right direction?
For reference, here is the DAP:
Code: Select all
DAPSize db 0x10 ;byte - size of packet (16 bytes)
DAPNULL db 0x00 ;byte - NULL
DAPSectors dw 0x0001 ;word - number of sectors to transfer
DAPOffset dw 0x7e00 ;dword - buffer (segment:offset) - remember little-endian, and align to word boundary
DAPSegment dw 0x0000
DAPLBA dd 0x0000003f ;dword - starting LBA
DAPLBA48 dd 0x00000000 ;dword - used for 48-bit LBA
Re: MBR Relocation
Posted: Tue Mar 20, 2012 5:40 am
by bluemoon
Let's say your Code offset is somewhere at 0x7C00 + N (N as there is code to handle movsb)
After you jump to 0x0600:0000 (which is the new Code), the CPU then disagree the offsets and thus you start accessing bogus memory - it may still be fine to output single char on screen:
So,
- The assembler assume Code: offset is 7C00+N, Data is located at 7C00+(data_label-$$)
- In reality it is 0000 + (data_label-$$-N)
Re: MBR Relocation
Posted: Tue Mar 20, 2012 6:53 am
by Yoda
In other words, for that pushes and retf you typed in, you must ORG 600h your code.
Re: MBR Relocation
Posted: Tue Mar 20, 2012 7:23 am
by bluemoon
There is more issues beside the ORG problem, but I would leave the debugging fun for the OP, hints are given.
Re: MBR Relocation
Posted: Tue Mar 20, 2012 8:39 am
by turdus
Here's one solution for relocation (can be found on wiki...)
Code: Select all
ORG 0600h
USE16
master_boot_record:
cli
xor ax, ax
mov ss, ax
mov sp, 600h
push ax
pop es
push cs
pop ds
;find our position in memory.
call .getaddress
.getaddress:
pop si
sub si, .getaddress-master_boot_record
cld
mov di, sp
mov cx, 100h
repnz movsw
jmp 0:.start
.start:
Also sets the stack (before your code) and segment registers correctly.
Re: MBR Relocation
Posted: Tue Mar 20, 2012 3:20 pm
by mark3094
Thank you everyone.
Your suggestions help a lot. I will try some debugging based on your advice.
Re: MBR Relocation
Posted: Tue Mar 20, 2012 3:28 pm
by Brendan
Hi,
turdus wrote:Code: Select all
xor ax, ax
mov ss, ax
mov sp, 600h
Probably a bad idea to have SS:SP set to 0x0000:0x0600. If more than 256 bytes of stack space is used (including "used by BIOS IRQ handlers and BIOS functions") you trash the BIOS data area that ends at 0x00000500.
I'd have a least 1 KiB of stack space reserved for BIOS (just in case); which means the lowest SS:SP I'd consider using for an MBR is 0x0000:0x0900.
Cheers,
Brendan
Re: MBR Relocation
Posted: Wed Mar 21, 2012 1:32 am
by Yoda
True.
The best location for MBR stack is 0000:7C00h, right below an old code location.
Re: MBR Relocation
Posted: Wed Mar 21, 2012 7:09 am
by turdus
Brendan wrote:Probably a bad idea to have SS:SP set to 0x0000:0x0600. If more than 256 bytes of stack space is used (including "used by BIOS IRQ handlers and BIOS functions")
That was the homework part... I've mentioned that it sets the stack before the code...
Anyway, 256 bytes could be more than enough if you know what you're doing. I do not use local variables in stack, I keep track of what I push (max 6 bytes at a time), also I have interrupts disabled in my MBR code (using stack above 800h would causes problems in my code as I load the 2nd loader and GPT there).
But you're right some BIOS functions (namely VBE) require more space on stack. As soon as my 2nd stage loader starts, it sets up it's own bigger stack (it's not an accident that in the wiki example one of the first thing my 2nd stage do is expanding the stack size to 512 bytes. I think if it's still not enough that's the reader's duty to find a new bigger place for it).
Re: MBR Relocation
Posted: Wed Mar 21, 2012 9:35 am
by invalid
turdus wrote:256 bytes could be more than enough (...) expanding the stack size to 512 bytes
I'm trying to get rid of 8-bit habits of "make all you can to save one byte/one clock cycle". Unless you develop for some embedded device, just take a full page for the stack, come on, it's 2012, there are still gigabytes left.
Re: MBR Relocation
Posted: Wed Mar 21, 2012 1:34 pm
by turdus
ydoom wrote:I'm trying to get rid of 8-bit habits of "make all you can to save one byte/one clock cycle".
That's you, not me. I think an OS must use as little of resources as possible and leave the rest for user programs. Imho.
Unless you develop for some embedded device, just take a full page for the stack, come on, it's 2012,
2012 or not, PC still boots in real mode, maximum addressable memory 64k per segments.
there are still gigabytes left.
Very bad and dangerous attitude imho. That creates huge, terribly slow bloated software like Nero (~500Mb as opposite to cdrtools which does exactly the same in 2,5Mb).
Lastly, if you think you cannot deal with 512 bytes of stack during boot, you're the reader who has to do his homework. Good luck with wasting resources.
Cheers
Re: MBR Relocation
Posted: Thu Mar 22, 2012 5:32 am
by invalid
turdus wrote:PC still boots in real mode, maximum addressable memory 64k per segments.
Good point. And that is the reasoning I respect, sir! Emotional part of your post was ignored
Re: MBR Relocation
Posted: Fri Mar 23, 2012 1:28 pm
by linguofreak
turdus wrote:2012 or not, PC still boots in real mode, maximum addressable memory 64k per segments.
At the same time, since real mode code nowadays tends to just bootstrap to protected mode and get discarded, you should have plenty of room in the 1st MB to just give your stack a full 64k (not that it's likely to use anywhere near that much).
Re: MBR Relocation
Posted: Fri Mar 23, 2012 1:49 pm
by Yoda
linguofreak wrote:since real mode code nowadays tends to just bootstrap to protected mode and get discarded, you should have plenty of room in the 1st MB
Since there are many things to do and there is a plenty of complicated file systems, devices and kernel formats, even second stage loader may become too big to fit in 1Mb. So it is not really plenty of room.
Re: MBR Relocation
Posted: Sun Mar 25, 2012 1:38 am
by mark3094
Well, I have adjusted my code, and it seems to be working.
I just wanted to drop a line to thank everyone for their input. It is much appreciated.
(PS sorry for the late reply - I flew to Melbourne to spend a few days at Cisco Live)