OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 2:33 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 5 posts ] 
Author Message
 Post subject: x86 MBR - int 1Ch triggers in qemu/bochs, not in virtualbox
PostPosted: Tue Jun 01, 2021 9:24 am 
Offline

Joined: Wed May 19, 2021 10:32 am
Posts: 2
I'm trying to build an MBR that uses a timer to do some display stuff. So far it works fine when running under qemu or bochs, but when I try to run it under VirtualBox, the timer interrupt does not trigger at all.

I've created a very small test program that prints an "x" on the screen every second (ish);

Code:
CPU 386      ; Architecture we're using
BITS 16      ; MBRs are 16-bit code
org 7C00h   ; The location the BIOS loads the MBR

; Offset of int 0x1C - 4 bytes per entry
%define TIMER_IVT_OFFSET 0x1C * 4

main:
   ; Perform this jump to make sure cs is set to 0x0000 and ip is set to 0x7c00(ish) - in line with our org.
   ; BIOS behaviour on this is unpredictable
   jmp 0x0000:setcs

   print_char db 0      ; Flag to see if we need to print or not
   tick_count db 0      ; Tick count for 1Ch

setcs:
   ; Base setup

   cld         ; Set the direction flag forward, used for movs, stos, etc.
            ; Setting this forward will increment cx on operations instead of decrementing it.

   xor ax, ax      ; Set ES=DS=0 - this can be changed later for rep operations
   mov ds, ax
   mov es, ax

   mov ss, ax      ; Stack segment is 0
   mov sp, 0x7c00      ; This sets the stack (with segment 0, so ss:sp = 0000:7c00) to grow below the
            ; bootloader. Nothing is relocated or loaded there, so this should be fine.


   ; Set up the screen for displaying error messages and load the remaining sectors
   ; These calls could be defined as callable functions, but since they are only used once, it doesn't
   ; make that much sense to add that overhead and complexity.

   ; Clear the screen
   mov ah, 0x07   ; Function 0x07: scroll window
   mov al, 0x00   ; Clear entire window
   mov bh, 0x07   ; White on black
   mov cx, 0x00   ; Specifies top left of screen as (0,0)
   mov dh, 0x18   ; 18h = 24 rows of chars
   mov dl, 0x4f   ; 4fh = 79 cols of chars
   int 0x10   ; Video interrupt


   ; Move cursor to position 0,0
   mov ah, 0x02   ; Function 0x02: set cursor position
   mov dh, 0x00   ; Row 0
   mov dl, 0x00   ; Col 0
   mov bh, 0x00   ; Page 0
   int 0x10   ; Video interrupt

   ; Stop all interrupts while we change an entry
   cli

   ; IVT in real mode is at 0x0000:0x0000
   ; Each entry is 2 words; offset and address with address first,
   ; then offset. We are using offset 0 in this entire MBR and the
   ; address is the defined anim_timer_isr below.
   mov word [TIMER_IVT_OFFSET], tick
   mov word [TIMER_IVT_OFFSET+2], 0x0000

   ; Enable interrupts again
   sti

main_loop:
   cmp byte [print_char], 1
   je .print_char
   jmp main_loop

.print_char:
   mov byte [print_char], 0
   mov bh, 0
   mov bl, 0
   mov ah, 0Eh
   mov al, 'x'
   int 10h
   jmp main_loop
   

tick:
   ; If we're on tick 5
   cmp byte [tick_count], 5
   je .set_print

   ; Increase tick count
   inc byte [tick_count]

   jmp .end_tick

.set_print:
   ; Set print_char to true and reset tick count
   mov byte [tick_count], 0
   mov byte [print_char], 1

.end_tick:
   iret


; Padding bytes until the partition table.
; $$ = address of start of section, $ = current position, $-$$ = length of section thus far.
; We use 510, so the last 2 bytes can be specifically set (total sector size = 512).
times 510-($-$$) db 0

; MBR signature
db 55h, 0AAh


I compile this with
Code:
nasm -fbin mbr.asm -o mbr.bin
and then run it with qemu like so;
Code:
qemu-system-i386 -drive "format=raw,file=mbr.bin,if=floppy"

This works fine, it boots and I see an x printed on the screen roughly every second.

When I create a VirtualBox disk, like so;
Code:
VBoxManage internalcommands createrawvmdk -filename ./mbr.vmdk -rawdisk ./mbr.bin
and then create a virtual machine of type Other > VirtualBox Bootsector Test, it boots, but nothing is printed.

The actual MBR is far more complex and uses the timer for some animations. When I saw that didn't work, I suspected it might be because VirtualBox does not handle 1Ch. I've searched around for other cases of this issue, but could not find any.

Am I missing something here? Is there a way to fix this, or another way to get a timer working inside VirtualBox?

I also tried int 08h with the same result...


Top
 Profile  
 
 Post subject: Re: x86 MBR - int 1Ch triggers in qemu/bochs, not in virtual
PostPosted: Tue Jun 01, 2021 12:35 pm 
Offline
Member
Member

Joined: Wed Aug 30, 2017 8:24 am
Posts: 1593
In the interrupt handler, you cannot assume the values of any segments except CS. This means you must either save DS and restore it on exit, or use CS overrides for all memory accesses in the interrupt handler. This is especially important for a BIOS called interrupt, because you cannot assume a whole lot about what BIOS is doing to its segments. If it was interrupt 8 you were intercepting, this would be a little bit different, since there is no BIOS layer between the main program and the interrupt handler in that case. Still, it is better to reset DS in the interrupt handler, or only reference CS.

You can however assume that CS is 0, because you set it 0 in the IVT. This does not hold for the main bootloader, where after setting DS the opposite is true.

_________________
Carpe diem!


Top
 Profile  
 
 Post subject: Re: x86 MBR - int 1Ch triggers in qemu/bochs, not in virtual
PostPosted: Tue Jun 01, 2021 1:08 pm 
Offline
Member
Member

Joined: Wed Oct 01, 2008 1:55 pm
Posts: 3192
The BIOS used to call int 0x1C as part of handling the timer interrupt, so I suspect this is what you see.


Top
 Profile  
 
 Post subject: Re: x86 MBR - int 1Ch triggers in qemu/bochs, not in virtual
PostPosted: Tue Jun 01, 2021 1:27 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5100
nullplan wrote:
If it was interrupt 8 you were intercepting, this would be a little bit different, since there is no BIOS layer between the main program and the interrupt handler in that case.

Interrupt 8 can occur while the BIOS is servicing another interrupt, so there really is no case where you can trust registers other than CS to hold particular values.

I think some CS overrides would be the easiest way to fix it.


Top
 Profile  
 
 Post subject: Re: x86 MBR - int 1Ch triggers in qemu/bochs, not in virtual
PostPosted: Wed Jun 02, 2021 4:42 am 
Offline

Joined: Wed May 19, 2021 10:32 am
Posts: 2
This was exactly the issue! After prefixing all addresses with cs:, or setting ds to 0 in the top of the handler, it works fine in VirtualBox!

Thanks for the insight, everyone. I can continue now :)


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

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot], Google [Bot] and 78 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