flat assembler
Message board for the users of flat assembler.
Index
> OS Construction > How does bootloader call kernel stub? Goto page 1, 2 Next |
Author |
|
revolution 10 Oct 2021, 05:24
Data from the disk is loaded to 0x0100000 and it then blindly jumps to the first address.
The stack is blindly placed at 0x00200000, and assumes the memory is already mapped. I guess the bootloader has properly mapped all the memory pages so it all works. |
|||
10 Oct 2021, 05:24 |
|
FlierMate 10 Oct 2021, 06:16
revolution wrote: Data from the disk is loaded to 0x0100000 and it then blindly jumps to the first address. Thanks for pointing this out. I still have doubt, suppose I have two binary image: 1) boot.img 2) kernel.img How do I transfer call to kernel.img from boot.img? If I understand correctly, boot.img is at sector 0, and kernel.img is at sector 1? Or above 1MB is protected mode? I try to combine both boot.asm and kernel.asm together, but the VM keeps booting itself. Looks like I am missing something obvious here.[/code] |
|||
10 Oct 2021, 06:16 |
|
revolution 10 Oct 2021, 06:19
If boot.img is one sector, then it's job is to load all sectors of kernel.img to somewhere in memory, then jump to the first address where it loaded kernel.img.
You showed this in the first post where the code loads 100 sectors to 0x0100000 and jump to it. |
|||
10 Oct 2021, 06:19 |
|
macomics 10 Oct 2021, 08:16
revolution wrote: If boot.img is one sector, then it's job is to load all sectors of kernel.img to somewhere in memory, then jump to the first address where it loaded kernel.img. |
|||
10 Oct 2021, 08:16 |
|
FlierMate 10 Oct 2021, 09:21
revolution wrote: If boot.img is one sector, then it's job is to load all sectors of kernel.img to somewhere in memory, then jump to the first address where it loaded kernel.img. Thanks. macomics wrote:
Thanks. Hi , I changed the code, I use Int 13h to read the first two sectors (512-byte boot.img and 512-byte kernel.img combined). An inconsistent behavior is observed, Code: mov ax,1 ;start sector mov bx, 0x7c00 ;offset of buffer mov cx,2 ;number of sectors (512 bytes each) xor dx, dx call _load ; load some sectors from disk to a buffer in memory jmp 0:0x7e00 ;2nd stage Sometimes, I get the Welcome message (successful) but most of the times I don't . If it succeeded, BIOS will print 4-digit hex value (as shown in one of the screenshot). I am not sure which segment:offset I should call the second-stage module after reading from disk? Code: jmp 0:0x7c00+512 ; or 0x7e00 Is this correct?
|
|||||||||||||||||||
10 Oct 2021, 09:21 |
|
revolution 10 Oct 2021, 09:26
The BIOS has already loaded the first sector (your boot sector) to 0:7c00 so if you overwrite that address block then bad things will happen. Your boot code is already running at that address.
|
|||
10 Oct 2021, 09:26 |
|
FlierMate 10 Oct 2021, 09:33
revolution wrote: The BIOS has already loaded the first sector (your boot sector) to 0:7c00 so if you overwrite that address block then bad things will happen. Your boot code is already running at that address. Thank you so much, it saves my effort!! Code: mov ax,1 ;start sector mov bx, 0x7e00 ;offset of buffer mov cx,1 ;number of sectors (512 bytes each) xor dx, dx call _load jmp 0:0x7e00 ;2nd stage Now it works wonder. (But I can only read one sector, otherwise error ) |
|||
10 Oct 2021, 09:33 |
|
FlierMate 10 Oct 2021, 09:45
I think I'll just paste it on here as backup (still no value to publish on GitHub):
Some of the code were taken (and modified a little) from Redox OS GitLab repo (bootsector.asm and print.asm): Code: ; ; An experimental bootloader for x86 with second stage ; by FlierMate (Oct 10, 2021) ; ; With reference to Redox OS bootsector.asm ; format binary as 'img' org 7C00h start: cli xor ax, ax mov ds, ax mov es, ax mov ss, ax mov sp, 0x7c00 sti mov [disk], dl mov byte [0b8000h],'W' mov byte [0b8000h+1],10 mov byte [0b8000h+2],'o' mov byte [0b8000h+3],10 mov byte [0b8000h+4],'w' mov byte [0b8000h+5],10 mov byte [0b8000h+6],32 mov byte [0b8000h+7],7 mov byte [0b8000h+8],'O' mov byte [0b8000h+9],10 mov byte [0b8000h+10],'S' mov byte [0b8000h+11],10 mov byte [0b8000h+12],32 mov byte [0b8000h+13],7 mov byte [0b8000h+14],32 mov byte [0b8000h+15],7 mov ax,1 ;start sector mov bx, 0x7e00 ;offset of buffer mov cx,1 ;number of sectors (512 bytes each) xor dx, dx call _load jmp 0:0x7e00 ;2nd stage ;Reference: Redox OS bootsector.asm ; load some sectors from disk to a buffer in memory ; buffer has to be below 1MiB ; IN ; ax: start sector ; bx: offset of buffer ; cx: number of sectors (512 Bytes each) ; dx: segment of buffer ; CLOBBER ; ax, bx, cx, dx, si ; TODO rewrite to (eventually) move larger parts at once ; if that is done increase buffer_size_sectors in startup-common to that (max 0x80000 - startup_end) ;Reference: Redox OS bootsector.asm _load: mov dword [DAPACK.addr], eax mov [DAPACK.buf], bx mov [DAPACK.count], cx mov [DAPACK.seg], dx call print_dapack mov dl, [disk] mov si, DAPACK mov ah, 0x42 int 0x13 jc error ret ;Reference: Redox OS bootsector.asm print_dapack: mov bx, [DAPACK.addr + 2] call print_hex mov bx, [DAPACK.addr] call print_hex mov al, ' ' call print_char mov bx, [DAPACK.count] call print_hex mov al, ' ' call print_char mov bx, [DAPACK.seg] call print_hex mov al, ' ' call print_char mov bx, [DAPACK.buf] call print_hex ret ;Reference: Redox OS bootsector.asm ; print a character print_char: pusha mov bx, 7 mov ah, 0x0e int 0x10 popa ret ;Reference: Redox OS bootsector.asm ; print a number in hex print_hex: mov cx, 4 .lp: mov al, bh shr al, 4 cmp al, 0xA jb .below_0xA add al, 'A' - 0xA - '0' .below_0xA: add al, '0' call print_char shl bx, 4 loop .lp ret error: mov byte [0b8000h+2000],'E' mov byte [0b8000h+2001],12 mov byte [0b8000h+2002],'r' mov byte [0b8000h+2003],12 mov byte [0b8000h+2004],'r' mov byte [0b8000h+2005],12 mov byte [0b8000h+2006],'o' mov byte [0b8000h+2007],12 mov byte [0b8000h+2008],'r' mov byte [0b8000h+2009],12 mov byte [0b8000h+2010],32 mov byte [0b8000h+2011],7 mov byte [0b8000h+2012],32 mov byte [0b8000h+2013],7 mov byte [0b8000h+2014],32 mov byte [0b8000h+2015],7 ;Reference: Redox OS bootsector.asm .halt: cli hlt jmp .halt disk db 0 ;Reference: Redox OS bootsector.asm DAPACK: db 0x10 db 0 .count dw 0 ; int 13 resets this to # of blocks actually read/written .buf dw 0 ; memory buffer destination address (0:7c00) .seg dw 0 ; in memory page zero .addr dw 0 ; put the lba to read in this spot .addr2 dw 0 db 7C00h+510-$ DUP (0) dw 0AA55h ;db 0x0100000-($ - $$) DUP (0) ; ; 2nd sector ; start2: ;Reference: Redox OS bootsector.asm ; enable A20-Line via IO-Port 92, might not work on all motherboards in al, 0x92 or al, 2 out 0x92, al ;call kernel_main mov byte [0b8000h+2000],'W' mov byte [0b8000h+2001],10 mov byte [0b8000h+2002],'e' mov byte [0b8000h+2003],10 mov byte [0b8000h+2004],'l' mov byte [0b8000h+2005],10 mov byte [0b8000h+2006],'c' mov byte [0b8000h+2007],10 mov byte [0b8000h+2008],'o' mov byte [0b8000h+2009],10 mov byte [0b8000h+2010],'m' mov byte [0b8000h+2011],10 mov byte [0b8000h+2012],'e' mov byte [0b8000h+2013],10 mov byte [0b8000h+2014],32 mov byte [0b8000h+2015],7 jmp $ db 512-($ - start2) DUP (0)
|
||||||||||
10 Oct 2021, 09:45 |
|
macomics 10 Oct 2021, 13:23
Code: mov byte [0b8000h],'W' mov byte [0b8000h+1],10 mov byte [0b8000h+2],'o' mov byte [0b8000h+3],10 mov byte [0b8000h+4],'w' mov byte [0b8000h+5],10 mov byte [0b8000h+6],32 mov byte [0b8000h+7],7 mov byte [0b8000h+8],'O' mov byte [0b8000h+9],10 mov byte [0b8000h+10],'S' mov byte [0b8000h+11],10 mov byte [0b8000h+12],32 mov byte [0b8000h+13],7 mov byte [0b8000h+14],32 mov byte [0b8000h+15],7 ... mov byte [0b8000h+2000],'E' mov byte [0b8000h+2001],12 mov byte [0b8000h+2002],'r' mov byte [0b8000h+2003],12 mov byte [0b8000h+2004],'r' mov byte [0b8000h+2005],12 mov byte [0b8000h+2006],'o' mov byte [0b8000h+2007],12 mov byte [0b8000h+2008],'r' mov byte [0b8000h+2009],12 mov byte [0b8000h+2010],32 mov byte [0b8000h+2011],7 mov byte [0b8000h+2012],32 mov byte [0b8000h+2013],7 mov byte [0b8000h+2014],32 mov byte [0b8000h+2015],7 ... mov byte [0b8000h+2000],'W' mov byte [0b8000h+2001],10 mov byte [0b8000h+2002],'e' mov byte [0b8000h+2003],10 mov byte [0b8000h+2004],'l' mov byte [0b8000h+2005],10 mov byte [0b8000h+2006],'c' mov byte [0b8000h+2007],10 mov byte [0b8000h+2008],'o' mov byte [0b8000h+2009],10 mov byte [0b8000h+2010],'m' mov byte [0b8000h+2011],10 mov byte [0b8000h+2012],'e' mov byte [0b8000h+2013],10 mov byte [0b8000h+2014],32 mov byte [0b8000h+2015],7 I do not know who wrote it, but after loading you are in real mode, and even more so after Code: xor ax, ax mov ds, ax mov es, ax mov ss, ax In order to avoid such errors, it is worth starting by studying the operation of processors in various memory addressing modes. P. S. And each of the commands using direct 32-bit addressing is very wasteful to the extremely limited space of the boot sector Code: mov byte [0b8000h+2000],'W' ; 5 byte each ; total: 155 bytes or 7 bytes prepare + 3 + 120 bytes all = 130 bytes total push 0xB800 ; 3 byte single pop ds ; 1 byte single mov bx, 2000 ; 3 byte single mov [ds:bx+0],"W" ; 3 byte single mov [ds:bx+1],10 ; 4 byte each ; or 12 bytes + 10 bytes + 13 bytes = 35 bytes total mov si, msg0 ; 3 byte double call tty_write ; 3 byte double @@: mov ah, 14 ; 2 byte single int 16 ; 2 byte single tty_write: lodsb ; 1 byte single test al, al ; 2 byte single jnz @b ; 2 byte single retn ; 1 byte single msg0 db 'Wow OS',0 ; 7 bytes single msg1 db 'Error', 0 ; 6 bytes single ; or 6 bytes + 12 bytes + 7 bytes + 13 bytes = 39 bytes push 0xB800 ; 3 bytes single pop es ; 1 byte single xor di, di ; 2 bytes single mov ah, 7 mov si, msg0 ; 3 bytes double call write_buf ; 3 bytes double @@: stosw ; 1 byte write_buf: lodsb ; 1 byte test al, al ; 2 bytes jnz @b ; 2 bytes retn ; 1 byte msg0 db 'Wow OS',0 ; 7 bytes single msg1 db 'Error', 0 ; 6 bytes single Last edited by macomics on 10 Oct 2021, 14:07; edited 1 time in total |
|||
10 Oct 2021, 13:23 |
|
FlierMate 10 Oct 2021, 14:05
macomics wrote:
I saw it also on this forum section (https://board.flatassembler.net/topic.php?t=21367) , but maybe edfed's code was executed after enabling protected mode? (I am still newbie to OS development) macomics wrote:
I think that's 1MB limit of real mode. macomics wrote:
Good to know this. I didn't know that 0xB8000 is equivalent to B800:0. macomics wrote:
Part of me always want to experiment first, i.e. learn by doing. macomics wrote:
That's nice. I did this in DOS programming, but somehow when come to OS development (real and protected mode), my focus is on something else. And I also thought I could optimize the code later. Thank you, macomics, for your frank comments, I like your correction. I still have another important question, how do I call kernel stub that is not in the same binary image? E.g. I plan to mix Assembly (bootsector) and Pascal (kernel). How do I transfer call from bootloader to OS kernel written in HLL? I refer to https://wiki.osdev.org/Pascal_Bare_Bones, but it doesn't explain how to move from bootloader to kernel stub, though, I found the linker script: Code: ENTRY(kstart) SECTIONS { .text 0x100000 : { text = .; _text = .; __text = .; *(.text) . = ALIGN(4096); } .data : { data = .; _data = .; __data = .; *(.data) .... .... Do you know how to do this using FASM? I see it reserves 1MB for real mode at the beginning, and I guess the Pascal kernel is right after that? Sorry for asking noob question. |
|||
10 Oct 2021, 14:05 |
|
macomics 10 Oct 2021, 14:13
FlierMate wrote: I saw it also on this forum section (https://board.flatassembler.net/topic.php?t=21367) , but maybe edfed's code was executed after enabling protected mode? (I am still newbie to OS development) ADD: Code: .code=$-gdt ; first entry in gdt (8*1) dw -1,0 ; 4Gbytes, start at linear 0 db 0,9ah,0cfh,0 ; granularity = 64Kbytes, code segment, ring 0, read only,etc... .data=$-gdt ; second entry in gdt (8*2) dw -1,0 ; 4Gbytes, start at linear 0 db 0,92h,0cfh,0 ; granularity = 64Kbytes, data segment, ring 0, read/write,etc... Code: lgdt fword [gdt.size] Last edited by macomics on 10 Oct 2021, 14:51; edited 3 times in total |
|||
10 Oct 2021, 14:13 |
|
macomics 10 Oct 2021, 14:20
FlierMate wrote: I still have another important question, how do I call kernel stub that is not in the same binary image? |
|||
10 Oct 2021, 14:20 |
|
macomics 10 Oct 2021, 14:28
Judging by the code already available in this topic
Code: load32: mov eax, 1 ; starting sector mov ecx, 100 ; total number of sectors mov edi, 0x0100000 ;1 meg call ata_lba_read jmp CODE_SEG:0x0100000 ... mov ebp, 0x00200000 mov esp, ebp it is enough to simply load the code to the address 1 MB and transfer control to it. But here Code: in al, 0x92 or al, 2 out 0x92, al Code: mov edi, 0x0100000 ;1 meg ... jmp CODE_SEG:0x0100000 |
|||
10 Oct 2021, 14:28 |
|
FlierMate 07 Jan 2022, 12:59
Hello again, I revisit this topic, and this piece of code cannot be compiled:
Code: format binary as 'img' org 7C00h extrn '_kmain' as kmain use16 start: ..... ..... kmain is defined as Code: procedure kmain(mbinfo: Pmultiboot_info_t; mbmagic: DWORD); stdcall; ....in Pascal. The FASM complained: Code: boo@debian:~/fasm$ ./fasm wowos.asm flat assembler version 1.73.28 (16384 kilobytes memory) wowos.asm [18]: extrn '_kmain' as kmain processed: extrn '_kmain' as kmain error: illegal instruction. Someone please help! |
|||
07 Jan 2022, 12:59 |
|
revolution 07 Jan 2022, 14:17
Binary format doesn't have any export table to define external names, so fasm can't define any extrn label.
You'll need to supply the raw address where kmain is loaded. Usually the boot sector loads in other sectors to a known address and jmps to the first instruction. Similar to how the first post in this thread shows. |
|||
07 Jan 2022, 14:17 |
|
FlierMate 08 Jan 2022, 12:04
revolution wrote: Binary format doesn't have any export table to define external names, so fasm can't define any extrn label. I need the "extrn" label so that it can link to the entry point of my Pascal program. Since FASM generates binary image directly, I end up using NASM temporarily for this project, and it has been done, a "hello world" OS kernel written in Pascal! --- On a side notes, I did not know we have to handling caps lock ourselves in the OS kernel, (" Lecture 121 - Handling caps lock, upper case and lower case letters ") Am not sure what everyone think of this Udemy course "Developing a Multithreaded Kernel From Scratch!" (https://dragonzap.com/course/developing-a-multithreaded-kernel-from-scratch?coupon=GITHUBDISCOUNT , it is not my intention to promote his online course. Just take a look at the course outline) --- Again, many OSes kernel are written in C, mine is an example showing it is also possible with Pascal (though the binary image is larger than C). https://github.com/FlierMateX/osfp (Pascal example) https://github.com/FlierMateX/osc ( C example)
Last edited by FlierMate on 15 Jan 2022, 08:49; edited 1 time in total |
|||||||||||
08 Jan 2022, 12:04 |
|
revolution 08 Jan 2022, 12:40
FlierMate wrote: On a side notes, I did not know we have to handling caps lock ourselves in the OS kernel, (" Lecture 121 - Handling caps lock, upper case and lower case letters ") So you can use "R" as caps-lock if you wanted to. And use caps-lock to be the "+" character. Or any other combination you choose. The user will probably hate you though. "Foreign" language keyboards generate the same codes for each key position, only the printing on the key-tops is changed. So if you change the key-tops on a French keyboard to match the English layout then it becomes an English keyboard. You just need to make sure the OS is set to English mode and no one will know the difference. |
|||
08 Jan 2022, 12:40 |
|
FlierMate 10 Jan 2022, 14:13
Yeah, it is fun, @revolution, I just added PS/2 keyboard support for my Pascal kernel.
It is port 0x60 and 0x64, for keyboard hardware. No wonder, then, some OSes in the beginning only support PS/2. I think for USB 1.1 keyboard, must write a driver for that? My keyboard support in Pascal kernel still in early stage, cannot detect caps lock and num lock, so all alphabets are treated as uppercase letter, and arrow keys are in numerical digit.
|
||||||||||
10 Jan 2022, 14:13 |
|
FlierMate1 05 Jul 2022, 10:21
I am attaching old version of Pascal kernel, and a simplified version of C kernel, because I saw quite many have downloaded my osfp2.zip above.
The difference between this osfp.zip and osfp2.zip above: osfp.zip contains - Pascal kernel without PCI enumeration (just PS/2 keyboard support) - additional C kernel osfp2.zip above contains - just Pascal kernel with both PS/2 keyboard support and PCI enumeration
|
|||||||||||
05 Jul 2022, 10:21 |
|
Goto page 1, 2 Next < Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.