Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

16-bit real mode for the x86 code #1

Open
tkchia opened this issue Aug 23, 2019 · 3 comments
Open

16-bit real mode for the x86 code #1

tkchia opened this issue Aug 23, 2019 · 3 comments

Comments

@tkchia
Copy link

tkchia commented Aug 23, 2019

Hello @indigoparadox,

It seems to me you wish to get the kmain () routine to run in real mode on an x86.

One way you can do this is to get the startup code to return from 32-bit protected mode to real mode (because the Multiboot mechanism in /mboot.c32 will put the machine in 32-bit protected mode). E.g.

diff --git a/src/x86/boot.s b/src/x86/boot.s
index 213d0b8..318cff3 100644
--- a/src/x86/boot.s
+++ b/src/x86/boot.s
@@ -25,11 +25,40 @@ stack_top:
 .global _start
 _start:
 
-movl  $stack_top, %esp
-call kmain
-
-# If the kernel returns, disable interrupts (cli) and spin forever.
-cli
-hang:
-hlt
-jmp hang
+lgdt %cs:gdtr16
+lidt %cs:idtr16
+ljmp $8, $cont
+cont:
+.code16
+movw $0x10, %ax
+movw %ax, %ds
+movw %ax, %es
+movw %ax, %ss
+movw $stack_top, %sp
+movl %cr0, %eax
+andb $~1, %al
+movl %eax, %cr0
+jmp cont2
+cont2:
+xorw %ax, %ax
+movw %ax, %ds
+movw %ax, %es
+movw %ax, %ss
+ljmp $0, $kmain
+
+.balign 8
+# 16-bit GDTR
+gdtr16:
+.hword gdt16end-gdt16
+.long gdt16
+
+# GDT with 16-bit code segment and data segment descriptor
+.set gdt16, .-8
+.quad 0x008f9b000000ffff
+.quad 0x008f93000000ffff
+gdt16end:
+
+# Real mode IDTR
+idtr16:
+.hword 0x3ff
+.long 0

Alternatively, a more direct way might be to modify your src/syslinux.cfg to not use /mboot.c32. If I understand things correctly, this should directly load your binary code as a 16-bit program.

I hope the above helps. Thank you!

@tkchia
Copy link
Author

tkchia commented Aug 24, 2019

Hello @indigoparadox,

Also note that the syslinux bootloader code uses some 80386-specific instructions (e.g. lfs) even though it runs in real mode. If you ultimately wish to have your code work on an 8086, you may want to use a different bootloader.

Thank you!

@indigoparadox
Copy link
Owner

Thank you! And sorry for not noticing this sooner!

It's been a little while, but I believe I had realized that syslinux or grub would leave me in protected mode after flailing around for a bit, and then the realization that I wouldn't be able to quickly or easily "cheat" by using multiboot caused me to drop it for the moment. Returning from protected mode seemed a bit more complicated than I was prepared to deal with.

Your code is a bullseye, though! I dropped it into boot.s and put everything together, started it with bochs and it just worked. I'll be sure to study it thoroughly. I truly appreciate it! Ultimately, I would like to write my own 16-bit bootloader so I could run this on an 8086. Though that might be a ways off.

Thank you again!

@tkchia
Copy link
Author

tkchia commented Sep 7, 2019

Hello @indigoparadox,

Your code is a bullseye, though! I dropped it into boot.s and put everything together, started it with bochs and it just worked. I'll be sure to study it thoroughly. I truly appreciate it!

Thank you, and you are welcome. 🙂

A quick explanation of my code: for switching to protected mode to real mode, it is normally necessary to at least

  • change the "bitness" of %cs and %ss from 32-bit to 16-bit, and
  • also reset the interrupt table register (IDTR) to point to address 0.

Without these, the processor will likely end up in a weird state (e.g. real mode but with code in 32-bit mode), which will not be very conducive to interfacing with the ROM BIOS.

If you are interested, there is a more complete procedure and sample code for the mode switch at the OSDev wiki.

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants