bochs and unreal mode

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
Lauwe
Posts: 2
Joined: Mon May 21, 2007 8:23 am
Location: Netherlands

bochs and unreal mode

Post by Lauwe »

I'm having trouble using my unreal mode bootloader in bochs. I have enabled A20, set up my GDT, switched to protected mode, changed DS and switched back to real mode. But when i try to write some data to 0x00100000 bochs doesn't seem to want to accept it.

boot.S:

Code: Select all

[BITS 16]
[ORG 0x7C00]
 
%macro   PRINTS   1
 mov  si,%1
 call print
%endmacro
 
jmp   boot
 
boot_msg db 'Starting bootloader..',13,10,0
reboot_msg  db 'Press any key to reboot..',13,10,0
noi386_msg  db 'No i386+ detected..',13,10,0
noA20_msg   db 'A20 line not enabled..',13,10,0
 
reboot:
 PRINTS(reboot_msg)
 xor  ax,ax 
 int  0x16
 db   0x0EA
 dw   0x0000
 dw   0xFFFF

print:
 mov  ax, 0x0E00
 mov  bl, 0x07
.print_nextchar:
 lodsb
 or   al, al
 jz   .print_ret
 int  0x10
 jmp  .print_nextchar
.print_ret:
 ret

wait_kbdbuf:
 in   al, 0x64
 test al, 0x02
 loopnz  wait_kbdbuf
 ret

check_i386:
 pushf
 xor  ah, ah
 push ax
 popf
 pushf
 pop  ax
 and  ah, 0xF0
 cmp  ah, 0xF0
 je   .check_i386_failed
 mov  ah, 0xF0
 push ax
 popf
 pushf
 pop  ax
 and  ah, 0xF0
 jz   .check_i386_failed
 popf
 ret
.check_i386_failed:
 PRINTS(noi386_msg)
 jmp  reboot

enable_a20:
 xor  cx, cx
 call wait_kbdbuf
 mov  al, 0xD1
 out  0x64, al
 call wait_kbdbuf
 mov  al, 0xDF
 out  0x60, al
 call wait_kbdbuf
 push ds
 push es
 xor  ax, ax
 mov  ds, ax
 dec  ax,
 mov  es, ax
 mov  ax,[es:0x10]
 not  ax
 push WORD  [0]
 mov  [0], ax
 mov  ax,[0]
 cmp  ax,[es:0x10]
 pop  WORD  [0]
 pop  es
 pop  ds
 jz   .enable_a20_failed
 ret
.enable_a20_failed:
 PRINTS(noA20_msg)
 jmp  reboot

go_unreal:
 push ds
 lgdt [gdtr]
 mov  eax, cr0
 or   al,0x01
 mov  cr0, eax
 mov  bx, 0x08
 mov  ds, bx
 and  al, 0xFE
 mov  cr0, eax
 pop  ds
 ret


boot:
 cli
 xor  ax, ax
 mov  ds, ax
 mov  es, ax
 mov  ax, 0x9000
 mov  ss, ax
 mov  sp, 0xFFFF
 PRINTS(boot_msg)
 call check_i386
 call enable_a20
 call go_unreal
 mov  bx, 0xDADA
 mov  edi, 0x100000
                                        ;next instruction causes problems
 mov  [ds:edi], bx
 jmp  reboot

gdtr:
 dw   gdt_end - gdt_null - 1
 dd   gdt_null

gdt_null:
 db   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
gdt_data:
 db   0xFF, 0xFF, 0x00, 0x00, 0x00, 10010010b, 01001111b, 0x00
gdt_end:

times 510-($-$$)  db 0
dw 0xAA55
dump_cpu gives me the following when i break just before the ' mov [ds:edi], bx':
eax:0x00000010, ebx:0x0000dada, ecx:0x0000fffd, edx:0x00000000
ebp:0x00000000, esp:0x0000ffff, esi:0x00007c1b, edi:0x00100000
eip:0x00007d33, eflags:0x00000002, inhibit_mask:0
cs:s=0x0000, dl=0x0000ffff, dh=0x00009b00, valid=1
ss:s=0x9000, dl=0x0000ffff, dh=0x00009309, valid=7
ds:s=0x0000, dl=0x0000ffff, dh=0x004f9300, valid=1
es:s=0x0000, dl=0x0000ffff, dh=0x00009300, valid=1
fs:s=0x0000, dl=0x0000ffff, dh=0x00009300, valid=1
gs:s=0x0000, dl=0x0000ffff, dh=0x00009300, valid=1
ldtr:s=0x0000, dl=0x0000ffff, dh=0x00008200, valid=1
tr:s=0x0000, dl=0x0000ffff, dh=0x00008300, valid=1
gdtr:base=0x00007d40, limit=0xf
idtr:base=0x00000000, limit=0xffff
dr0:0x00000000, dr1:0x00000000, dr2:0x00000000
dr3:0x00000000, dr6:0xffff0ff0, dr7:0x00000400
cr0:0x00000010, cr1:0x00000000, cr2:0x00000000
cr3:0x00000000, cr4:0x00000000
when executing the mov
(0) [0x00007d33] 0000:7d33 (unk. ctxt): mov word ptr ds:[edi], bx ; 3e67891f
bochs debug gives me this:
00001451421d[CPU ] write_virtual_checks(): write beyond limit (real mode)
00001451421d[CPU ] exception(0x0D)
00001451421d[CPU ] interrupt(): vector = 13, INT = 0, EXT = 1
Is it me, am i missing something or doing something completely wrong? or is it bochs? Most of the unreal-related code is taken from the babysteps-tutorial and writing the smiley to the screen like in the tutorial works without any problems.

edit: also, what are the dl, dh and valid fields next to the segment-registers in dump_cpu?
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Post by Combuster »

it has to do with what you put in the GDT. the 10010010b, 01001111b part says the following:
present (1), DPL=0 (00), data segment (10), expand-up (0), writable (1), not accessed (0)
byte-granular (0), big (1), unused(00), top 4 bits of limit(1111)

now when you load ds the limit is calculated: the limit bits are taken and concatenated: 0xfffff, making an offset of 0xfffff the highest address that can be addressed without error. the 1mb mark is 0x100000, one byte further. The result is a completely valid GPF

To change the limit to 4GB instead of 1MB you should set the granularity bit (01001111b becomes 11001111b). This multiplies the limit by 4096 so that it becomes 0xfffff * 4096 + 0xfff = 0xffffffff which is probably what you want.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
Lauwe
Posts: 2
Joined: Mon May 21, 2007 8:23 am
Location: Netherlands

Post by Lauwe »

Thank you, this was indeed the problem. I guess this is what happens when you blindly copy code without fully understanding it.
xsix
Member
Member
Posts: 59
Joined: Tue Oct 24, 2006 10:52 am

Post by xsix »

yes, that's whysometimes OS's bugs are being fixed for a very long time, cause programmer uses code, which he doesn't understand and that's why it is the best to understand and write your own code
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Post by Candy »

Lauwe wrote:Thank you, this was indeed the problem. I guess this is what happens when you blindly copy code without fully understanding it.
I think this bug is in the code on the Wiki, since I've copied that (yep - mostly the GDT) and hit the same error.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Post by Combuster »

Candy wrote:I think this bug is in the code on the Wiki, since I've copied that (yep - mostly the GDT) and hit the same error.
Went ahead and fixed it. It must've been one nasty bug to make even the guru here trip over it :D
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Post by Candy »

Combuster wrote:
Candy wrote:I think this bug is in the code on the Wiki, since I've copied that (yep - mostly the GDT) and hit the same error.
Went ahead and fixed it. It must've been one nasty bug to make even the guru here trip over it :D
Not so much the bug that caused a delay, Bochs didn't properly simulate the triple fault that should've followed. Bug report filed a week ago or so.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Post by Combuster »

I wouldn't expect a triple-fault: the segment limit > 64k, when accessing 1Mb it will GPF, the fault handler will be loaded from the IVT, which sends execution to the bios which will then try do something with that. Most likely it will halt the processor at some point.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Post by Candy »

Combuster wrote:I wouldn't expect a triple-fault: the segment limit > 64k, when accessing 1Mb it will GPF, the fault handler will be loaded from the IVT, which sends execution to the bios which will then try do something with that. Most likely it will halt the processor at some point.
At the best case, it shouldn't freeze up at that instruction. I was thinking about it for a moment, given the segment limit you'd expect a GPF, given that it's realmode you'd expect it not to give a GPF (since real mode doesn't have GPFs). That's why I expected it to somehow reboot.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Post by Combuster »

IMO lockups are better than triple-faults - they allow you to read any debug information that you have printed before the error.

Besides, locking up on an exception is afaik typical behaviour for the PC bios, so at any rate I wouldn't call it a bug. Its more like a feature. Agreed though that an error message might be more appropriate.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
Post Reply