Failed to print string

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.
User avatar
zhiayang
Member
Member
Posts: 368
Joined: Tue Dec 27, 2011 7:57 am
Libera.chat IRC: zhiayang

Failed to print string

Post 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

Code: Select all

xor ax, ax
mov ds, ax
mov es, ax
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...?
User avatar
DavidCooper
Member
Member
Posts: 1150
Joined: Wed Oct 27, 2010 4:53 pm
Location: Scotland

Re: Failed to print string

Post 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.
Help the people of Laos by liking - https://www.facebook.com/TheSBInitiative/?ref=py_c

MSB-OS: http://www.magicschoolbook.com/computing/os-project - direct machine code programming
User avatar
Blue
Member
Member
Posts: 31
Joined: Thu Aug 02, 2007 6:34 am
Location: on the stack

Re: Failed to print string

Post 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 $".
User avatar
iansjack
Member
Member
Posts: 4711
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Failed to print string

Post 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.)
User avatar
DavidCooper
Member
Member
Posts: 1150
Joined: Wed Oct 27, 2010 4:53 pm
Location: Scotland

Re: Failed to print string

Post 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.
Help the people of Laos by liking - https://www.facebook.com/TheSBInitiative/?ref=py_c

MSB-OS: http://www.magicschoolbook.com/computing/os-project - direct machine code programming
User avatar
iansjack
Member
Member
Posts: 4711
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Failed to print string

Post 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.
User avatar
Kazinsal
Member
Member
Posts: 559
Joined: Wed Jul 13, 2011 7:38 pm
Libera.chat IRC: Kazinsal
Location: Vancouver
Contact:

Re: Failed to print string

Post 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.
User avatar
zhiayang
Member
Member
Posts: 368
Joined: Tue Dec 27, 2011 7:57 am
Libera.chat IRC: zhiayang

Re: Failed to print string

Post 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?
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Re: Failed to print string

Post 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.
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
User avatar
zhiayang
Member
Member
Posts: 368
Joined: Tue Dec 27, 2011 7:57 am
Libera.chat IRC: zhiayang

Re: Failed to print string

Post 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.

Code: Select all

Booting from floppy...
That's it.
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: Failed to print string

Post 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).
If a trainstation is where trains stop, what is a workstation ?
User avatar
iansjack
Member
Member
Posts: 4711
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Failed to print string

Post 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.
Last edited by iansjack on Sun Jul 01, 2012 4:03 am, edited 2 times in total.
User avatar
Kazinsal
Member
Member
Posts: 559
Joined: Wed Jul 13, 2011 7:38 pm
Libera.chat IRC: Kazinsal
Location: Vancouver
Contact:

Re: Failed to print string

Post 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.
User avatar
zhiayang
Member
Member
Posts: 368
Joined: Tue Dec 27, 2011 7:57 am
Libera.chat IRC: zhiayang

Re: Failed to print string

Post 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.
Nable
Member
Member
Posts: 453
Joined: Tue Nov 08, 2011 11:35 am

Re: Failed to print string

Post 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.
Post Reply