No string output

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
User avatar
quanganht
Member
Member
Posts: 301
Joined: Fri May 16, 2008 7:13 pm
Location: Hanoi, Vietnam

No string output

Post by quanganht »

First, I have to say that I even "Googled" all over OSdev forums and found no answer.

And this is my problem: My bootloader will load stage 2, then stage 2 load the kernel. Everything work just fine, except for I get absolutely no output to the screen.

This is my bootloader:

Code: Select all

ORG 0x7c00

	jmp 0x0000:start			; sync weird bios segment:offset pairs on bootup 
start:
	cli					; disable interrupts until we enter unreal mode

    	xor ax, ax				; zero all the segment registers
    	mov ds, ax
    	mov es, ax
    	mov fs, ax
    	mov gs, ax
    	mov ss, ax
    
    	mov byte [drvnum] , dl			; save the boot device ID in the FAT BPB

enable_a20_fast:				; use the fast method to enable A20 gate access
    	in al, 0x92 
    	or al, 0x02
    	out 0x92, al  

init_stack:
    	mov esp, 0x7C00				; set up our stack to 0x7C00
    	mov bp, sp

    	sti

;load stage2
reset:
	MOV AH, 0
	MOV DL, [drvnum]
	INT 0x13

	JC reset


	MOV AH, 0x02   
	MOV AL, 4   
	MOV CH, 0   
	MOV CL, 0x02   
	MOV DH, 0   
	MOV DL, [drvnum]   
	MOV BX, 0x7E0
	MOV ES, BX  
	MOV BX, 0

	INT 0x13

	JC reset

	;MOV AX, 0x7E0
	;MOV DS, AX

	MOV AH, byte [drvnum]
	MOV AL, 0
	PUSH AX

	JMP 0x7E0:0000


drvnum DB 0

times 510-($-$$) db 0

	dw 0xAA55
And this is the second stage:

Code: Select all

ORG 0x7E00
	

	POP AX
	MOV byte [drvnum], AH

;load kernel
reset:
	LEA SI,[msg]
	call print
	
	MOV AH, 0
	MOV DL, [drvnum]
	INT 0x13

	JC reset


	MOV AH, 0x02   
	MOV AL, 25
	MOV CH, 0   
	MOV CL, 0x06  
	MOV DH, 0   
	MOV DL, [drvnum]   
	MOV BX, 0x1000
	MOV ES, BX  
	MOV BX, 0

	INT 0x13

	JC reset

	MOV AX, 0x0
	MOV DS, AX

	jmp enter_pmode

	jmp $

print:
   	LODSB
   	OR AL, AL
  	JZ done
   	MOV AH, 0x0E
	INT 0x10
   	JMP print
done:
	ret

drvnum DB 0

msg  DB  "Running Stage 2 ...", 13, 10, 0



; ========================================

    

enter_pmode:                            ; leave unreal mode, and enter PMode]

    cli                                 ; no more interrupts for us!

    lgdt [GDT_SEL]                      ; load the GDT

    mov eax, cr0

    or al, 1                            ; turn on protection in CR0

    mov cr0, eax

    jmp 0x08:pmode                      ; far jump to set CS to 0x08 (GDT:CODE32)



[BITS 32]

pmode:
    cli

    mov eax, 0x10                       ; set segment registers to 0x10 (DATA32)  

    mov ds, ax

    mov es, ax

    mov fs, ax

    mov gs, ax

    mov ss, ax  

    

    call parse_elf                      ; get info about kernel.elf
    mov esp, 0x7C00
    mov ebp, esp

    
    xor ebx, ebx
    xor ecx, ecx
    xor edx, edx
    xor esi, esi
    xor edi, edi
    mov eax, dword [ENTRY]              ; EAX = elf entry point
    

    call eax                             ; jump to our kernel

    

ENTRY   dd  0



; ========================================

    

parse_elf:

    pusha

    

    mov ebx, 0x10000                    ; EBX = where kernel.elf starts

    mov eax, ebx                        ; EAX = EBX
    

    add ebx, 24                         ; offset to EH->ENTRY (24)

    mov edx, dword [ebx]                ; EDX = EH->ENTRY

    mov dword [ENTRY], edx              ; save the value

    

    add ebx, 4                          ; offset to EH->PH_OFF (28)

    add eax, dword [ebx]                ; EAX = EH->PH_OFF



    add ebx, 16                         ; offset to EH->PH_NUM (44)

    mov cx, word [ebx]                  ; CX = EH->PH_NUM


    mov ebx, eax                        ; EBX = EH->PH_OFF + 0x10000
    
 .find_type:
    push ecx                            ; save ECX
    push ebx                            ; save where we are
    
    mov eax, 0x01                       ; EAX = PH_TYPE_LOAD
    cmp eax, dword [ebx]                ; if the PH->TYPE == PH_TYPE_LOAD, copy the addresses
    jne .skip

    add ebx, 4                          ; offset to PH->OFFSET

    mov esi, dword [ebx]                ; ESI = PH->OFFSET

    add esi, 0x10000                    ; ESI += where the kernel.elf is loaded (0x10000)

    

    add ebx, 8                          ; offset to PH->PHYSADDR

    mov edi, dword [ebx]                ; EDI = PH->PHYSADDR

    

    add ebx, 8                          ; offset to PH->MEMSIZE

    mov ecx, dword [ebx]                ; ECX = PH->MEMSIZE

    

    rep movsb                           ; memcopy!
    
 .skip:
    pop ebx                             ; restore the start of the header
    add ebx, 32                         ; skip to the next
    pop ecx                             ; restore ECX
    dec cx                              ; counter--
    cmp cx, 0                           ; if the counter has reached 0, we're done
    jna .done                           ; else, keep parsing headers
    jmp .find_type    

 .done:
 

    popa

    ret    

; ==========  GDT Segment Selector  ==========

align 4

GDT_SEL:

    dw GDT_DESC_END-GDT_DESC-1

    dd GDT_DESC

    

; ========== GDT Segment Descriptor ========== 

align 8 

GDT_DESC:

  .NULL:   

    dq 0x0000000000000000               ; null segment

  .CODE32:

    dq 0x00CF9A000000FFFF               ; limit = 4GB, D/B = 32-bit, DPL = 0, type = code r/w

  .DATA32:

    dq 0x00CF92000000FFFF               ; limit = 4GB, D/B = 32-bit, DPL = 0, type = data r/w

GDT_DESC_END:

TIMES 2048-($-$$) db 0
So, if I make a kernel like the C Barebones, it print an 'A' just like expected. But if I make a kernel like, say JamesM tutorial 3, it prints nothing.
Hope that I will get some good answers...
"Programmers are tools for converting caffeine into code."
User avatar
yemista
Member
Member
Posts: 299
Joined: Fri Dec 26, 2008 12:31 pm
Location: Boston
Contact:

Re: No string output

Post by yemista »

I dont know if how your doing it is wrong, but I do know its different from the way I learned using this tutorial: http://osdever.net/tutorials/hello_btldr.php

The difference is that the tutorial loads some values into the bx register to supply int 10h with a little more info, and they actually used mov si, string, rather than lea si, [string]. I dont know much about lea, but your instruction seems to be saying load the number stored at the address string as an address.
User avatar
quanganht
Member
Member
Posts: 301
Joined: Fri May 16, 2008 7:13 pm
Location: Hanoi, Vietnam

Re: No string output

Post by quanganht »

No. I don't ask about printing code in bootloader nor stage2. They works just fine. What I'm asking is why print a string in *kernel* is not working. And the kernel is written in C, link as an ELF executable.
For example:

Code: Select all

kprint("Hello");
"Programmers are tools for converting caffeine into code."
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: No string output

Post by Solar »

Try printing a single character, not a string. I.e., kputc( 'A' ) (or whatever your character-print-function is named) instead of kprint( "Hello" ).

If that works, you're probably not linking .rodata* into the kernel binary...
Every good solution is obvious once you've found it.
User avatar
quanganht
Member
Member
Posts: 301
Joined: Fri May 16, 2008 7:13 pm
Location: Hanoi, Vietnam

Re: No string output

Post by quanganht »

Oh, I forgot to say kput is working. I'm using the linker script from C Barebones. How could it be wrong?
"Programmers are tools for converting caffeine into code."
quok
Member
Member
Posts: 490
Joined: Wed Oct 18, 2006 10:43 pm
Location: Kansas City, KS, USA

Re: No string output

Post by quok »

quanganht wrote:Oh, I forgot to say kput is working. I'm using the linker script from C Barebones. How could it be wrong?
That's hard to say without seeing your linker script! Could you post it for us to review?
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: No string output

Post by Solar »

quanganht wrote:I'm using the linker script from C Barebones.
Ah! See? Had I known, I wouldn't've asked. But you didn't exactly tell us until now...

I'm still fuzzy as to what the problem is. Could you give us the (minimal) code you use to reproduce your problem - one kernel that prints and one that doesn't, which are as similar as possible otherwise?

(I'm trying to talk you into systematic debugging...)
Every good solution is obvious once you've found it.
User avatar
quanganht
Member
Member
Posts: 301
Joined: Fri May 16, 2008 7:13 pm
Location: Hanoi, Vietnam

Re: No string output

Post by quanganht »

I don't have my code right now ( I'm using Windoze with UltraSurf because i'm blacklisted and can't post on Ubuntu). But u can use James Molloy's kernel code from tutorial number 3 to test. Do raw writes to floppy: bootloader -> stage2 -> kernel. Maybe I'll try to post my code later...
"Programmers are tools for converting caffeine into code."
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: No string output

Post by Solar »

No, please, don't "post your code".

<rant mode="meta"> <!-- Meaning, not angry at you in particular, but at a general pattern, and not only on this board. Don't take this personally. -->

Post only the absolute minimal snippet of code required to reproduce the behaviour you describe.

We don't want to see your FAT drivers, your task switching, or even your Makefile. We would like to see two small, almost identical pieces of code, one that prints correctly, and one that doesn't; where you say you cannot make the two snippets any more similar and still reproduce the problem.

See, you take the BareBones tutorial code, and the JamesM tutorial code, and toss everything out that's not strictly related to booting and printing. Check if they still compile, run, and behave as expected (i.e., one prints, the other doesn't).

Then look at the differences in the source (and linker scripts, and Makefiles etc.). Why are they different? Can e.g. the linker scripts be made identical, with both pieces of code still exposing the same behaviour as before? Piece by piece, eliminate differences until you have those few lines of code that make the difference (between correct and broken behaviour).

Either you understand yourself at that point, or you have those two small, almost-identical snippets of code that would make for a smart question to ask here. Be assured that someone will have an answer for you.


The process above is called debugging. It's not the only way to do it, but it's one way. It's a boring, tiresome process, and that is why you are the one who should have the courtesy to do it, not every single one on this board trying to help you.

Debugging is a skill, something that distinguishes the script kid / tutorial copy & paster from a "real" developer. It is a requirement for OS related work...

</rant>
Every good solution is obvious once you've found it.
User avatar
quanganht
Member
Member
Posts: 301
Joined: Fri May 16, 2008 7:13 pm
Location: Hanoi, Vietnam

Re: No string output

Post by quanganht »

Ok, good news here: I found this page http://wiki.osdev.org/Bran%27s_Known_Bugs, and I used the link script in it. Now, it can print out "Hello!" but not like what I expected: It clears the screen ( I guess) and write string near bottom of the screen.
Take my minimal code in the attached file

Edit: Talking about debugging, I know what it is.
Attachments
test.tar.bz2
(5.5 KiB) Downloaded 72 times
"Programmers are tools for converting caffeine into code."
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: No string output

Post by Solar »

quanganht wrote:It clears the screen ( I guess) and write string near bottom of the screen.
From a quick glance at monitor.c, I'd say that's the way it has been designed.
Take my minimal code...
...even including backups of most files in the archive...
...in the attached file
And do what?
Edit: Talking about debugging, I know what it is.
Then why don't you do it? :wink:
Every good solution is obvious once you've found it.
User avatar
yemista
Member
Member
Posts: 299
Joined: Fri Dec 26, 2008 12:31 pm
Location: Boston
Contact:

Re: No string output

Post by yemista »

quanganht, is this bootloader for the exokernel youve been working on?
User avatar
quanganht
Member
Member
Posts: 301
Joined: Fri May 16, 2008 7:13 pm
Location: Hanoi, Vietnam

Re: No string output

Post by quanganht »

yemista wrote:quanganht, is this bootloader for the exokernel youve been working on?
Yes. I'm still stuck with this bootloader. So only Coby work with the C kernel so far, and I don't have much time to check his code.

EDIT: Coby confirmed he make his code to print like that. So my bootloader is actually bootable now! :D
"Programmers are tools for converting caffeine into code."
Post Reply