OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 6:10 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 9 posts ] 
Author Message
 Post subject: [SOLVED] Problem with a bootloader written in GNU-Assembler
PostPosted: Sun Dec 19, 2021 2:45 pm 
Offline
Member
Member

Joined: Sat Jun 12, 2021 4:13 pm
Posts: 46
Hey everyone, as the title says, I'm writing a bootloader using GNU-Assembler with intel syntax. But I have a problem after loading sectors into memory and jumping to that address. Here I'm loading sectors to '0x9000'. Here is my bootloader :

Code:
.intel_syntax noprefix
.code16 # use 16 bits
.global _init
.global _startup
.text

_init:
  .org 80 # Some BIOSes need a BPB, therefore we fill up space for a fake one

  jmp 0x0000, _startup # in case BIOS set cs to 0x7c00. We work with cs:ip

_startup:

  cld
  mov bp, 0x8000
  mov sp, bp  # 0x0000:0x7c00 below bootloader

  xor ax, ax
  mov ds, ax
  mov ss, ax
  mov es, ax

  movb [BOOT_DRIVE], dl

  mov bx, offset flat:start_16_str
  call print

  mov bx, offset flat:read_disk_str
  call print

  mov dh, 0x1
  mov bx, 0x9000 # memory location to load disk to
  call load_disk

  mov bx, offset flat:read_disk_success_str
  call print

  call check_lm

  mov bx, 0x9000 # Loading test strig from second sectors
  call print # It works perfectly
 
  jmp .

check_lm:
  pusha

  # Check if CPU support Long mode (64 bits)
  mov eax, 0x80000001
  cpuid
  test edx, (1 << 29)
  jz .lm_error
  mov bx, offset flat:lm_success_str
  call print
  jmp .lm_done


.lm_error:
  mov bx, offset flat:lm_error_str
  call print
  jmp .lm_done

.lm_done:
  popa
  ret


.include "print_16.S"
.include "read_disk.S"

start_16_str:
  .asciz "Starting in 16-bit mode"
read_disk_str:
  .asciz "Loading disk into memory"

read_disk_success_str:
  .asciz "Loaded disk successfully !"

lm_error_str:
  .asciz "ERROR: FATAL: CPU does not support Long Mode"

lm_success_str:
  .asciz "CPU support Long mode "
.set BOOT_DRIVE, 0
.space 510-(.-_init), 0 # add zeroes to make it 510 bytes long
.word 0xaa55 # magic bytes that tell BIOS that this is bootable

msg:
.asciz "Test string"



As Wrote in comment, after calling load_disk, we have loaded sector 2 to 0x0000:0x9000, which is fine as I can access the string. But here is the thing, I want to jump to that address but I can't. In other words, after setting BX to 0x9000 and calling 0x13, I want to go straight to that address. So for example, modifying my bootloader as this :

Code:
...
.space 510-(.-_init), 0 # add zeroes to make it 510 bytes long
.word 0xaa55 # magic bytes that tell BIOS that this is bootable
#Beginning of second sector loaded to 0x0000:0x9000
mov bx, offset flat:msg
call print

msg:
.asciz "Test string"



I'm also leaving my linker script below :

Code:
ENTRY(_init)
OUTPUT_FORMAT(binary)
SECTIONS {
    . = 0x7c00;
    .text : {
        *(.text*)
    }
    .rodata : {
        *(.rodata*)
    }
    .data : {
        *(.data*)
    }
    .bss : {
        *(.bss*)
    }
}


I know I'm doing something wrong but I can't figure out what the issue... Please be kind to me, I'm new to this topic and I'm really looking forward to learn new stuff !
Thank you all !


Last edited by liwinux on Mon Dec 20, 2021 7:25 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: Problem with a bootloader written using GNU-Assembler
PostPosted: Sun Dec 19, 2021 4:55 pm 
Offline
Member
Member

Joined: Mon Jul 05, 2021 6:57 pm
Posts: 118
What is "jmp ." supposed to be? Why don't you just jump to the intended address? 0x9200 or whatever (since you have a string at 0x9000 I guess the code is elsewhere, 0x9200 is an example, you need to use the correct value according to where the code is).

(More generally, when you say "I want to jump to that address but I can't", what do you mean by you can't? What exactly did you try, in what way did it fail?)


Top
 Profile  
 
 Post subject: Re: Problem with a bootloader written using GNU-Assembler
PostPosted: Sun Dec 19, 2021 6:57 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5099
You're loading the second sector at 0x9000, but you told the assembler that the second sector will be loaded at 0x7e00. Addresses calculated by the assembler won't work if you do that.

Also, I don't see a near or short JMP at the beginning of your fake BPB. Are you executing the BPB?


Top
 Profile  
 
 Post subject: Re: Problem with a bootloader written using GNU-Assembler
PostPosted: Sun Dec 19, 2021 7:53 pm 
Offline
Member
Member

Joined: Sat Jun 12, 2021 4:13 pm
Posts: 46
davmac314 wrote:
What is "jmp ." supposed to be? Why don't you just jump to the intended address? 0x9200 or whatever (since you have a string at 0x9000 I guess the code is elsewhere, 0x9200 is an example, you need to use the correct value according to where the code is).


" jmp. " was used for debugging purpose. I used GDB in order to have a look at registers and stuff.

davmac314 wrote:
(More generally, when you say "I want to jump to that address but I can't", what do you mean by you can't? What exactly did you try, in what way did it fail?)


My bad, what I wanted to say by this was, I couldn’t get to that particular address and continue executing my bootloader


Top
 Profile  
 
 Post subject: Re: Problem with a bootloader written using GNU-Assembler
PostPosted: Sun Dec 19, 2021 8:02 pm 
Offline
Member
Member

Joined: Sat Jun 12, 2021 4:13 pm
Posts: 46
Octocontrabass wrote:
You're loading the second sector at 0x9000, but you told the assembler that the second sector will be loaded at 0x7e00. Addresses calculated by the assembler won't work if you do that.


I must be blind, but I don’t see where I tell my assembler to load my second sector at 0x7e00 ?

Octocontrabass wrote:
Also, I don't see a near or short JMP at the beginning of your fake BPB. Are you executing the BPB?


No, I’m not executing it in fact, it’s because I have a buggy BIOS that looks after a BPB, and if doesn’t find anyone, well It refused to execute my bootloader, so I’m king of faking it with zeros ..

As for my issue, I found some more informations. So my code was actually correct, but the problem here, is that I can’t print anything since labels after the first sector are not at 0x9000 for the assembler, so if I ask to load the address of “msg” well, it won’t load it from the memory segment es:bx but from 0x7exx since I’m using a linker script. So the goal is to tell my assembler that I load my second stage at 0x9000 and therefore labels that are in my second stage should be calculate correctly and not thinking that my second stage will be at 0x7e00

Maybe it’s not possible and therefore I have to load my second stage at 0x7e00 ?


Top
 Profile  
 
 Post subject: Re: Problem with a bootloader written using GNU-Assembler
PostPosted: Sun Dec 19, 2021 8:42 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5099
liwinux wrote:
I must be blind, but I don’t see where I tell my assembler to load my second sector at 0x7e00 ?

You told it to start at 0x7c00 and put the second sector 0x200 bytes later. That adds up to 0x7e00.

liwinux wrote:
Maybe it’s not possible and therefore I have to load my second stage at 0x7e00 ?

It's possible, but you need to put each sector into its own section (or file) and update your linker script to tell the linker how they'll be laid out on disk and in memory. You'll end up with something that looks a bit like this.

Or like this:

Code:
SECTIONS
{
   .sector1 0x7c00 : AT(0) {
      *(.sector1)
   }
   .sector2 0x9000 : AT(0x200) {
      *(.sector2)
   }
}

(I haven't tested this one.)


Top
 Profile  
 
 Post subject: Re: Problem with a bootloader written using GNU-Assembler
PostPosted: Sun Dec 19, 2021 8:48 pm 
Offline
Member
Member
User avatar

Joined: Fri Oct 27, 2006 9:42 am
Posts: 1925
Location: Athens, GA, USA
liwinux wrote:
Octocontrabass wrote:
You're loading the second sector at 0x9000, but you told the assembler that the second sector will be loaded at 0x7e00. Addresses calculated by the assembler won't work if you do that.


I must be blind, but I don’t see where I tell my assembler to load my second sector at 0x7e00 ?


It isn't what you are telling the assembler to do, but what you aren't telling it.
Code:
.space 510-(.-_init), 0 # add zeroes to make it 510 bytes long
.word 0xaa55 # magic bytes that tell BIOS that this is bootable

msg:
.asciz "Test string"


As this stands, msg and the data following it is being generated at the first byte past the boot sector, which is at 0000:7e00.

_________________
Rev. First Speaker Schol-R-LEA;2 LCF ELF JAM POEE KoR KCO PPWMTF
Ordo OS Project
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.


Top
 Profile  
 
 Post subject: Re: Problem with a bootloader written using GNU-Assembler
PostPosted: Mon Dec 20, 2021 5:40 am 
Offline
Member
Member

Joined: Sat Jun 12, 2021 4:13 pm
Posts: 46
Schol-R-LEA wrote:
liwinux wrote:
Octocontrabass wrote:
You're loading the second sector at 0x9000, but you told the assembler that the second sector will be loaded at 0x7e00. Addresses calculated by the assembler won't work if you do that.


I must be blind, but I don’t see where I tell my assembler to load my second sector at 0x7e00 ?


It isn't what you are telling the assembler to do, but what you aren't telling it.
Code:
.space 510-(.-_init), 0 # add zeroes to make it 510 bytes long
.word 0xaa55 # magic bytes that tell BIOS that this is bootable

msg:
.asciz "Test string"


As this stands, msg and the data following it is being generated at the first byte past the boot sector, which is at 0000:7e00.


Now I see where my error was, that's what I thought would happen. So I was kind of correct but I didn't know how to fix it. Thank you !


Top
 Profile  
 
 Post subject: Re: Problem with a bootloader written using GNU-Assembler
PostPosted: Mon Dec 20, 2021 5:48 am 
Offline
Member
Member

Joined: Sat Jun 12, 2021 4:13 pm
Posts: 46
Octocontrabass wrote:
liwinux wrote:
I must be blind, but I don’t see where I tell my assembler to load my second sector at 0x7e00 ?

You told it to start at 0x7c00 and put the second sector 0x200 bytes later. That adds up to 0x7e00.


As I wrote previously, I now see where my error was !

Octocontrabass wrote:
liwinux wrote:
Maybe it’s not possible and therefore I have to load my second stage at 0x7e00 ?

It's possible, but you need to put each sector into its own section (or file) and update your linker script to tell the linker how they'll be laid out on disk and in memory. You'll end up with something that looks a bit like this.

Or like this:

Code:
SECTIONS
{
   .sector1 0x7c00 : AT(0) {
      *(.sector1)
   }
   .sector2 0x9000 : AT(0x200) {
      *(.sector2)
   }
}

(I haven't tested this one.)


Now, for this linker script part, I can't be sure if it's a problem with your linker script or not, because I've already tried something similar but after the linking part, the linker part doesn't produce any data within the final file. And it's the same story for the one you gave me !

So for example having this in the bootloader won't produce anything:
Code:
.section .sector1
... some code ...
space 510-(.-_start), 0
.word 0xaa55


but having it like this is not an issue :

Code:
.text
... some code ...
space 510-(.-_start), 0
.word 0xaa55


And I can't figure out why it does that


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 9 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot] and 55 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group