Trying to write an extremely simple MBR

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
Willdorf
Posts: 1
Joined: Wed May 18, 2016 10:55 am

Trying to write an extremely simple MBR

Post by Willdorf »

I'm trying to write an extremely simple MBR to start learning how to write an MBR/Kernel. This is what I have so far (created from pieces of other MBRs). The binary I get from using nasm and then ld to link is a bit different from just using nasm for both, but that doesn't appear to be the problem.

I first started with

Code: Select all

jmp 0:continue
but that appears to jump to 0000:7c22 (or 001d with nasm alone... i believe i didnt specify that it starts at 7c00) but im looking to jump to :7a22 or :7a1d, the address of the relocated code. I tried using just

Code: Select all

jmp continue
and then as seen uncommented below, adding the stack pointer to the continue pointer, pushing it and ret. All I get is a blinking cursor when dd'ed to my mbr. Any help is appreciated.

Code: Select all

					; nasm+ld		nasm			comment
global _start
_start:
    xor    cx, cx			; 6631c9		31c9			Set segment registers to zero
    mov    es, cx			; 8ec1			8ec1
    mov    ds, cx			; 8ed9			8ed9
    mov    ss, cx			; 8ed1			8ed1
    mov    sp, 0x7A00			; 66bc007a		bc007a			Stack
    mov    di, sp			; 6689e7		89e7			Bottom of relocation point
    mov    esi, _start			; be007c0000		66be00000000
    cld					; fc			fc
    mov    ch, 1			; b501			b501			cx = 256
    rep movsw				; f366a5		f3a5			Copy self to 0:7A00

;----------------------------------------------------------------------------------------------------------------------
    xor    eax,eax
    mov    ax, sp
    add    ax, continue

    ;jmp    0:continue			; ea227c00000000	ea1d000000		near JMP to copy of self
					; or
    ;jmp    continue			; (eb00)
    push eax
    ret
;----------------------------------------------------------------------------------------------------------------------

continue:
    sti					; fb			fb

ERROR:
    mov esi, errormsg			; be3b7c0000 (be36)	66be36000000		Error Message loc
    mov ah, 0x0E			; b40e			b40e
    mov bx, 7				; 66bb			bb0700
disp:
    lodsb				; ac			ac
    cmp ah, 0x00			; 80fc00		80fc00
    je end                              ; 7404			7404
    int 10h				; cd10			cd10
    jmp disp				; ebf6			ebf6

end:
    nop					; 90			90
    jmp end				; ebfd			ebfd			infinte loop

errormsg db 10,'YOU FUCKED UP.',13,0
 
times (0x1b8 - ($-$$)) nop		; 90			90			Padding
 
UID db 0xf5,0xbf,0x0f,0x18              					       ;Unique Disk ID

BLANK times 2 db 0

PT1 db 0x80,0x20,0x21,0x00,0x0C,0x50,0x7F,0x01,0x00,0x08,0x00,0x00,0xb0,0x43,0xF9,0x0D ;First Partition Entry
PT2 times 16 db 0								       ;Second Partition Entry
PT3 times 16 db 0								       ;Third Partition Entry
PT4 times 16 db 0								       ;Fourth Partition Entry
 
BOOTSIG dw 0xAA55								       ;Boot Signature

Thanks!
Octocontrabass
Member
Member
Posts: 5587
Joined: Mon Mar 25, 2013 7:01 pm

Re: Trying to write an extremely simple MBR

Post by Octocontrabass »

Willdorf wrote:(created from pieces of other MBRs)
I was expecting your MBR to be terrible based on this description, but it's actually not that bad. I only saw two major issues, and you kinda mentioned them already.
Willdorf wrote:The binary I get from using nasm and then ld to link is a bit different from just using nasm for both, but that doesn't appear to be the problem.
NASM by itself is generating 16-bit code. NASM with ld is generating 32-bit code. It should go without saying that 32-bit code won't run quite the way you want when the CPU is expecting 16-bit code. These sound like NASM's default behaviors, which can be overridden with command line options or directives in your code.
Willdorf wrote:im looking to jump to :7a22 or :7a1d, the address of the relocated code.
You should probably tell NASM/ld that your labels are all relative to the relocated address 0x7A00 instead of telling them that your labels are relative to the initial load address 0x7C00. This way, everything after the jump to the relocated code will have correct labels. (You only use one label before the relocation jump, and you can easily live without it.) This will also make the label in your jump work correctly, but only if you use a far jump: near jumps encode relative addresses, and NASM/ld won't know that your code started at 0x7C00 instead of 0x7A00 in order to calculate the right address. You need a far jump to set CS to a known value anyway, so it works out pretty well for you here.
User avatar
BenLunt
Member
Member
Posts: 941
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

Re: Trying to write an extremely simple MBR

Post by BenLunt »

As with the other comment, I think part of the problem is the tool chain, or rather the use of the tool chain. Be sure to tell NASM to create 16-bit straight binary.

Here are some notes:
- You know for a fact that your code currently resides at physical address 0x07C00, period. If it did not, you wouldn't be executing your code, now would you?
- Since we know the exact physical address of our code, we can make our segment:offset pointers to match.

Code: Select all

   mov  ax,07C0h
   mov  ds,ax
   mov  ax,07A0h
   mov  es,ax
   xor  si,si
   xor  di,di
   mov  cx,100h
   rep  movsw
That code will move a sector of code from 0x07C00 to 0x07A00, period, no matter the offsets the tool chain gives us.

- We need to jump to the correct place in the sector at 0x07A00. Here is were the "offset" part of the tool chain comes into play.

Code: Select all

   org 00h  ; or however NASM does it  [org 0x00] ?
   mov  ax,07C0h
   mov  ds,ax
   mov  ax,07A0h
   mov  es,ax
   xor  si,si
   xor  di,di
   mov  cx,200h
   rep  movsb
   
   push es
   push offset next_instruction   ; I think NASM uses 'push word next_instruction' but I could be wrong.
   retf
next_instruction:
   ; continue with code
At this point, the CPU's instruction pointer is at 0x07Axx where 'xx' is the offset of 'next_instruction' from 0x07A00. CS:IP -> 0x07Axx, CS = 07A0, IP = next_instruction. You have successfully moved your code out of the way.

- One thing to remember when writing a MBR. The MBR must take into account "Extended Partitions" when loading partitions and therefore may want to use a stack to navigate nested extended partition entries.

The example and description given within the book at http://www.fysnet.net/the_system_core.htm actually moves itself to 0x07E00 and starts a stack at that location. When an Extended Partition is found, it loads it to 0x08000 (0x07E00 + 200h). Then if another is found, it continues +200h. When the end of an extended partition is found and we have not found the active partition yet, it -200h and continues with the next partition entry there.

Here is the flowchart/outline example:
Image
Hope this helps.
Ben
mikegonta
Member
Member
Posts: 229
Joined: Thu May 19, 2011 5:13 am
Contact:

Re: Trying to write an extremely simple MBR

Post by mikegonta »

Willdorf wrote:

Code: Select all

errormsg db 10,'YOU F*CKED UP.',13,0
Mike Gonta
look and see - many look but few see

https://mikegonta.com
kzinti
Member
Member
Posts: 898
Joined: Mon Feb 02, 2015 7:11 pm

Re: Trying to write an extremely simple MBR

Post by kzinti »

mikegonta wrote:
Willdorf wrote:

Code: Select all

errormsg db 10,'YOU F*CKED UP.',13,0
The OP spelled it correctly.
mikegonta
Member
Member
Posts: 229
Joined: Thu May 19, 2011 5:13 am
Contact:

Re: Trying to write an extremely simple MBR

Post by mikegonta »

kzinti wrote:
mikegonta wrote:
Willdorf wrote:

Code: Select all

errormsg db 10,'YOU F*CKED UP.',13,0
The OP speeled it correctely.
My bad.
Mike Gonta
look and see - many look but few see

https://mikegonta.com
ggodw000
Member
Member
Posts: 396
Joined: Wed Nov 18, 2015 3:04 pm
Location: San Jose San Francisco Bay Area
Contact:

Re: Trying to write an extremely simple MBR

Post by ggodw000 »

i did exactly same thing just a few days ago and get it working and blogged it in my blog and working on the next phase:

http://x86arch.blogspot.in/search/label ... rogramming
Implementing bootloader
Implementing bootloader #2

However, the build environment and the way I did is much different than yours obviously, but if you got something useful, welcome to look at it.
key takeaway after spending yrs on sw industry: big issue small because everyone jumps on it and fixes it. small issue is big since everyone ignores and it causes catastrophy later. #devilisinthedetails
ggodw000
Member
Member
Posts: 396
Joined: Wed Nov 18, 2015 3:04 pm
Location: San Jose San Francisco Bay Area
Contact:

Re: Trying to write an extremely simple MBR

Post by ggodw000 »

;jmp 0:continue ; ea227c00000000 ea1d000000 near JMP to copy of self
; or
;jmp continue ; (eb00)

I have a suspiciion compiler did not compiled to jump to this address as was the case for me.
I had to single step through to nab it.
I just put a op code directly as i stated in my blog:

For example, I needed to jump to abs. addr 0000:8000
so
jmp 000:8000 or put label at 000:8000 and jump to it was not working.
during single step i found compiler compiled it as
jump 20:200h which was jump to 0:400h which was the offset relative my code segment!

so I just directly put opcode:
db 0eah, 00h, 80h, 00h, 00h
that jumped to 000:8000h but one problem was lea, offset instruction no longer worked because after cs was loaded with 0 but code segment is at 0:8000h after jump.

so, changed to following and bingo cs is loaded with 800h and instructoins such as lea cs:<label> worked!
db 0eah, 00h, 00h, 00h, 08h ; jump to 0800:0000
key takeaway after spending yrs on sw industry: big issue small because everyone jumps on it and fixes it. small issue is big since everyone ignores and it causes catastrophy later. #devilisinthedetails
mikegonta
Member
Member
Posts: 229
Joined: Thu May 19, 2011 5:13 am
Contact:

Re: Trying to write an extremely simple MBR

Post by mikegonta »

ggodw000 wrote:so, changed to following and bingo cs is loaded with 800h and instructoins such as lea cs:<label> worked!
db 0eah, 00h, 00h, 00h, 08h ; jump to 0800:0000
The segment register is not used for lea.

Code: Select all

org 0x7C00
  jmp 0:0x8000
cmd wrote:nasm -fbin bin.asm -o bin.bin -l bin.txt
list wrote:

Code: Select all

     1                                  org 0x7C00
     2 00000000 EA00800000                jmp 0:0x8000

Code: Select all

section .text
global _start
bits 16
_start:
  jmp 0:0x8000
cmd wrote:nasm -felf elf.asm -o elf.o -l elf.txt
ld -melf_i386 --oformat binary -Ttext 0x7C00 elf.o -o elf.bin
list wrote:

Code: Select all

     1                                  section .text
     2                                  global _start
     3                                  bits 16
     4                                  _start:
     5 00000000 EA00800000                jmp 0:0x8000
Nasm Manual wrote:In the distribution versions of NASM, the default is always bin
Nasm Manual wrote:Using the bin format puts NASM by default into 16-bit mode
There is no need to link a single file to get a flat binary. It's only when combining multiple object files, or mixing c and asm that it makes sense.
Mike Gonta
look and see - many look but few see

https://mikegonta.com
ggodw000
Member
Member
Posts: 396
Joined: Wed Nov 18, 2015 3:04 pm
Location: San Jose San Francisco Bay Area
Contact:

Re: Trying to write an extremely simple MBR

Post by ggodw000 »

mikegonta wrote:
ggodw000 wrote:so, changed to following and bingo cs is loaded with 800h and instructoins such as lea cs:<label> worked!
db 0eah, 00h, 00h, 00h, 08h ; jump to 0800:0000
The segment register is not used for lea.

Code: Select all

org 0x7C00
  jmp 0:0x8000
cmd wrote:nasm -fbin bin.asm -o bin.bin -l bin.txt
list wrote:

Code: Select all

     1                                  org 0x7C00
     2 00000000 EA00800000                jmp 0:0x8000
hmm, you sure about it? then will DI loaded the same value regardless of segment register in the following two examples?

Code: Select all

...
mov ax, DATA
mov ds, ax
mov ax, STACK
mov es, ax
lea di, cs:<label>
lea di, es:<label>
key takeaway after spending yrs on sw industry: big issue small because everyone jumps on it and fixes it. small issue is big since everyone ignores and it causes catastrophy later. #devilisinthedetails
Octocontrabass
Member
Member
Posts: 5587
Joined: Mon Mar 25, 2013 7:01 pm

Re: Trying to write an extremely simple MBR

Post by Octocontrabass »

ggodw000 wrote:hmm, you sure about it? then will DI loaded the same value regardless of segment register in the following two examples?
Yes.
Post Reply