Page 1 of 2
Failed to print string
Posted: Sat Jun 30, 2012 11:26 am
by zhiayang
In the face of imminent rejection by GRUB, I have decided to try and make my own boot loader. Now beware, my ASM knowledge is not extensive.
But anyway; as you can tell from the title, I cannot print things to screen.
Code: Select all
ORG 0x7C00
BITS 16
start:
; Null segment registers
xor ax, ax
mov ds, ax
mov es, ax
mov si, msg
call Print
cli
hlt
; Funtions ---------------------------------------------------------------
Print:
lodsb
cmp al, 0
je PrintDone
mov ah, 0x0E
int 0x10
jmp Print
PrintDone:
ret ; we are done, so return
; Functions ----------------------------------------------------------------
; Data -------------------------------------------------------------------
msg db "Welcome!", 0
; Data -------------------------------------------------------------------
times 510 - ($-$$) db 0
dw 0xAA55
Nothing happens. Nothing at all... I get a
Code: Select all
Booting from DVD/CD...
0MB medium found
and that's it.
Printing a single character is a hit-and-miss; If I comment out the
I can get it to print ONE character. If I try to print more (aka)
Code: Select all
xor bx, bx
mov ah, 0x0E
mov al, 'A'
int 0x10
mov ah, 0x0E
mov al, 'B'
int 0x10
It only prints 'A'. Am I doing it wrong, or...?
Re: Failed to print string
Posted: Sat Jun 30, 2012 12:49 pm
by DavidCooper
Assembler isn't my thing either, but I'm guessing that the org directive results in the address of msg being relative to a segment that doesn't match up with the one you're loading into DS. When you miss out the part where you load DS with 0 it then works for one char because by luck DS contains the right value, but it may then get changed by the BIOS such that it loses track of where the rest of the message is to be read in from.
Edit: Having read the last part of your post more carefully, I see that you've changed the way you're printing, so I don't know why it's failing. If bx needs to be 0 for the BIOS print function to work (I've never used that function as I just write directly to the screen instead, so I don't know what bx does), maybe it's not preserving that.
Re: Failed to print string
Posted: Sat Jun 30, 2012 1:14 pm
by Blue
Hi,
I can't see anything wrong with your code as such. The only thing that comes to my mind is that QEMU will not refresh the screen if it hits "cli" followed by "hlt". So you might try replacing that bit with a loop, such as "jmp $".
Re: Failed to print string
Posted: Sat Jun 30, 2012 2:34 pm
by iansjack
Here's an excerpt of some code from my boot sector:
Code: Select all
BadBoot:
mov $MsgBadDisk, %si
call PutChars
xor %ax, %ax
int $16
int $19
PutChars:
lodsb
or %al, %al
jz Done
mov $0xe, %ah
mov $0x7, %bx
int $0x10
jmp PutChars
Done:
ret
As you can see, I set %bx to 7 before printing every character. I can't remember now but I'm guessing that the BIOS call doesn't preserve %bx. This would explain all your results. (In your first example you don't set %bx at all.)
Re: Failed to print string
Posted: Sat Jun 30, 2012 3:06 pm
by DavidCooper
From Ralf Brown's Interrupt list:-
INT 10 - VIDEO - TELETYPE OUTPUT
AH = 0Eh
AL = character to write
BH = page number
BL = foreground color (graphics modes only)
So BX=0 ought to be what's wanted here (though the content of BL won't matter - putting 7 in it won't do any harm). I'd never have guessed before that BX mattered, judging by the code of many beginners who seem to get it to work without bothering to set it to anything, but requimrar has done it properly, at least in the modified version of the printing code. I suspect the BIOS returns with it corrupted, so the second attempt to print fails.
Re: Failed to print string
Posted: Sat Jun 30, 2012 3:24 pm
by iansjack
%bx = 0 would give a foreground colour of black in graphics mode, which may not be what is required. 7 gives light-grey, but you may prefer 0xf to give white. I don't think it matters in text mode.
Re: Failed to print string
Posted: Sat Jun 30, 2012 4:52 pm
by Kazinsal
Interrupts (including external ones like the timer) depend on a stack for things such as the return address. You haven't set one up yet, so the stack is effectively in an undefined location.
Code: Select all
cli ; Disable interrupts temporarily so the stack switch doesn't mess them up
xor ax, ax
mov ss, ax ; Set the stack segment to 0x0000
mov sp, 0xF000 ; Set the stack pointer (grows downwards) to 0xF000
sti ; Enable interrupts again
This snippet of code that goes after your segment initialization will initialize a stack at 0000:F000. This should be plenty of stack space for your bootloader, seeing as the stack grows downwards.
Re: Failed to print string
Posted: Sat Jun 30, 2012 9:07 pm
by zhiayang
Based on all your suggestions, here is my new code:
Code: Select all
ORG 0x7C00
BITS 16
start:
; Null segment registers
xor ax, ax
mov ds, ax
mov es, ax
cli ; Disable interrupts temporarily so the stack switch doesn't mess them up
xor ax, ax
mov ss, ax ; Set the stack segment to 0x0000
mov sp, 0xF000 ; Set the stack pointer (grows downwards) to 0xF000
sti ; Enable interrupts again
mov si, msg
call Print
jmp $
; Funtions ---------------------------------------------------------------
Print:
lodsb
cmp al, 0
je PrintDone
mov ah, 0x0E
mov bx, 0x07
int 0x10
jmp Print
PrintDone:
ret ; we are done, so return
; Functions ----------------------------------------------------------------
; Data -------------------------------------------------------------------
msg db "Welcome!", 0
; Data -------------------------------------------------------------------
times 510 - ($-$$) db 0
dw 0xAA55
I seriously have no idea why this is not working. I'm having a lot of weird issues here; first the GRUB thing, now this refusal to print stuff... BAH.
EDIT: What's wrong with the world? I've even tried writing directly to 0xB8000... with
Code: Select all
mov al, 0x66 ; the character
mov ah, 7 ; grey-on-black
mov bx, 0xB800 ; real mode segment
mov es, bx
mov [es:0], ax ; finally write to video memory at B800:0000 == B8000
NOPE. Am I destined never to be able to code an OS, ever?
Re: Failed to print string
Posted: Sat Jun 30, 2012 10:56 pm
by neon
How are you currently building and installing the VBR? A little confused; I see from your original post that your emulator or virtual machine is booting from a CD/DVD, yet the provided VBR is not for a CD/DVD format. Based on the provided information, I am not convinced the error is where you think it is.
Re: Failed to print string
Posted: Sat Jun 30, 2012 11:16 pm
by zhiayang
neon wrote:How are you currently building and installing the VBR? A little confused; I see from your original post that your emulator or virtual machine is booting from a CD/DVD, yet the provided VBR is not for a CD/DVD format. Based on the provided information, I am not convinced the error is where you think it is.
I don't get what you mean by VBR. But yes, I'm using mkisofs...
If I modify my build script to use
Code: Select all
dd if=output/clothload.bin of=output/disk.img
following the baby steps tutorial (minus the floppy) and use -fda in to start qemu... Same thing.
That's it.
Re: Failed to print string
Posted: Sun Jul 01, 2012 1:53 am
by gerryg400
Blue wrote:Hi,
I can't see anything wrong with your code as such. The only thing that comes to my mind is that QEMU will not refresh the screen if it hits "cli" followed by "hlt". So you might try replacing that bit with a loop, such as "jmp $".
I've not used QEMU, but I understood that jmp $ with interrupts disabled would halt the simulation (in the same way that hlt with cli does).
Re: Failed to print string
Posted: Sun Jul 01, 2012 2:13 am
by iansjack
Comment withdrawn. On closer inspection, if you are just producing a default binary file using nasm your code should work. And a later post says that it does.
Re: Failed to print string
Posted: Sun Jul 01, 2012 3:08 am
by Kazinsal
I just assembled your code, padded the binary to 2880 sectors, and ran it in qemu. It worked just fine. (edit: also works fine in Bochs, VirtualBox, Virtual PC, and VMware.)
So either your computer is a massive troll or you are.
Re: Failed to print string
Posted: Sun Jul 01, 2012 5:59 am
by zhiayang
Blacklight wrote:I just assembled your code, padded the binary to 2880 sectors, and ran it in qemu. It worked just fine. (edit: also works fine in Bochs, VirtualBox, Virtual PC, and VMware.)
So either your computer is a massive troll or you are.
Accidental troll, perhaps. I just set BX to 0 and everything worked. I don't know how or why you managed to get my posted code working, but either way thanks for all your help.
Re: Failed to print string
Posted: Sun Jul 01, 2012 11:04 am
by Nable
to Blacklight
AFAIK, `mov to ss' blocks interrupts for the one next instruction automatically, so, you don't need cli/sti when setting up your stack.
For example, see IASDM vol3, chapter 21.4.2, table 21-3, row 2.