Page 1 of 2
Test kernels refuses to print to screen
Posted: Wed Apr 27, 2005 9:40 pm
by HeronMarked
I've been following along with Bran's kernel tutorial and just put the basic vga driver together. Everything compiles and links fine but when I boot it in Bochs and Vmware it does nothing aside from clearing the screen. I tried another test kernel from Bona Fide with the same results, cls works fine but actually displaying characters doesn't. However, if I add something like:
mov word [0B8000h],9F44h
to the start.asm and comment out the calls to main, a white D with a blue background will display. My development environment is Gentoo, using ld and gcc. Here are my link.ld and makefile contents:
link.ld
Code: Select all
OUTPUT_FORMAT("binary")
ENTRY(start)
phys = 0x00100000;
SECTIONS
{
.text phys : AT(phys) {
code = .;
*(.text)
. = ALIGN(4096);
}
.data : AT(phys + (data - code))
{
data = .;
*(.data)
. = ALIGN(4096);
}
.bss : AT(phys + (bss - code))
{
bss = .;
*(.bss)
. = ALIGN(4096);
}
end = .;
}
makefile:
Code: Select all
nasm -f aout -o start.o start.asm
gcc -Wall -O -fleading-underscore -fstrength-reduce -fomit-frame-pointer -finline-functions -nostdinc -fno-builtin -I./include -c -o main.o main.c
gcc -Wall -O -fleading-underscore -fstrength-reduce -fomit-frame-pointer -finline-functions -nostdinc -fno-builtin -I./include -c -o scrn.o scrn.c
ld -T link.ld -o kernel.bin start.o main.o scrn.o
I can attach a zip file of both test kernels I'm attempting to use. I've just been banging my head against a wall over this all day.
Re:Test kernels refuses to print to screen
Posted: Thu Apr 28, 2005 12:17 am
by AR
How are you writing to the screen (it is very odd that you ask why your output code doesn't work when you haven't shown us what the code is)? I don't know what tutorials you're refering to so I'll just show how it should work:
Code: Select all
char *FrameBuffer = 0xB8000;
int CursorPos;
void print(char *msg)
{
while(*msg)
{
putchar(*msg);
++msg;
}
}
void putchar(char c)
{
switch(c)
{
case '\n':
CursorPos += 160;
break;
default:
FrameBuffer[CursorPos] = c;
++CursorPos;
FrameBuffer[CursorPos] = 0x07;
++CursorPos;
}
if(CursorPos > 4000)
{
memcpy(FrameBuffer, FrameBuffer+160, 3840);
CursorPos -= 160;
}
}
Have you set the attribute byte? If the attribute byte is 0 then you aren't going to see anything
Re:Test kernels refuses to print to screen
Posted: Thu Apr 28, 2005 7:45 am
by HeronMarked
I've tried two different methods
Code: Select all
#define WHITE_TXT 0x07
unsigned int k_printf(char *message, unsigned int line) // the message and then
the line #
{
char *vidmem = (char *) 0xb8000;
unsigned int i=0;
i=(line*80*2);
while(*message!=0)
{
if(*message=='\n') // check for a new line
{
line++;
i=(line*80*2);
*message++;
} else {
vidmem[i]=*message;
*message++;
i++;
vidmem[i]=WHITE_TXT;
i++;
};
};
return(1);
};
and from Barn's tutorial
Code: Select all
unsigned short *textmemptr;
int attrib = 0x0F;
int csr_x = 0, csr_y = 0;
void putch(unsigned char c)
{
unsigned short *where;
unsigned att = attrib << 8;
if(c == 0x08)
{
if(csr_x != 0) csr_x--;
}
else if(c == 0x09)
{
csr_x = (csr_x + 8) & ~(8 - 1);
}
else if(c == '\r')
{
csr_x = 0;
}
else if(c == '\n')
{
csr_x = 0;
csr_y++;
}
else if(c >= ' ')
{
where = textmemptr + (csr_y * 80 + csr_x);
*where = c | att;
csr_x++;
}
if(csr_x >= 80)
{
csr_x = 0;
csr_y++;
}
scroll();
move_csr();
}
I've even tried downloading the zipped code archives that come with the tutorials and compiling that. They give the same results.
Re:Test kernels refuses to print to screen
Posted: Thu Apr 28, 2005 8:19 am
by Colonel Kernel
HeronMarked wrote:
Code: Select all
if(*message=='\n') // check for a new line
{
line++;
i=(line*80*2);
*message++;
} else {
vidmem[i]=*message;
*message++;
i++;
vidmem[i]=WHITE_TXT;
i++;
};
For one thing, *message++ increments the character pointed to by message, rather than moving message to point to the next character. You want message++, not *message++.
Re:Test kernels refuses to print to screen
Posted: Thu Apr 28, 2005 8:55 am
by HeronMarked
I tried your fix Colonel. Same results, the weird thing is the clear screen functions work. If I comment out the clear screen though I get the usual Multiboot kludge message and then a non-blinking cursor. What gets me is that it happens with multiple kernels from tutorials. It makes me wonder if I'm doing something wrong.
Re:Test kernels refuses to print to screen
Posted: Thu Apr 28, 2005 9:52 am
by HeronMarked
Haha, I feel like an idiot. -fwriteable-strings fixed it. I assumed the link.ld scripts were correct, that'll teach me.
Re:Test kernels refuses to print to screen
Posted: Thu Apr 28, 2005 10:04 pm
by proxy
For one thing, *message++ increments the character pointed to by message, rather than moving message to point to the next character. You want message++, not *message++.
sorry, but this is horribly incorrect, it does in fact increment message. here's what _really_ happens.
++ always has a higher presidence than * unless parens alter that, so that goes first. however, portfix ++/-- is a little unusual. it will increment, but return the _old_ value.
so...
the code:
is technically the same as
Code: Select all
int *p = <something>;
int *temp = p;
++p;
*temp = 5;
fortunately, pretty much all compilers are smart enough to optimize this into just a plain post increment, yeilding assembly which would be analogous to the following code.
Code: Select all
int *p = <something>;
*p = 5;
++p;
proof of concept. i've implemented MANY memory copy loops like so:
plus any operator presidence chart like here:
http://www.cppreference.com/operator_precedence.html
will show both -- and ++ to have a higher precidence than derefence.
finally one thing to note is that
by itself is just silly, you are incrementing p, and dereferencing it..but you do nothing with that dereference value which is nothing more than a waste of cpu cycles.
if you intend to just increment a pointer just do:
the first one being prefered especially in c++ because sometimes (particularly with objects with overloaded ++ operators) compilers can't eliminate the temp in the post increment/decrement.
proxy
Re:Test kernels refuses to print to screen
Posted: Thu Apr 28, 2005 10:07 pm
by proxy
also a better solution than adding -fwriteable-strings is to add
*(.rodata*)
to the .data section so your string constants go in there too.
proxy
Re:Test kernels refuses to print to screen
Posted: Fri Apr 29, 2005 12:23 am
by Colonel Kernel
proxy wrote:
sorry, but this is horribly incorrect, it does in fact increment message. here's what _really_ happens.
D'oh! Serves me right for trying to be helpful before 9:00 AM.
BTW, calling it "incorrect" without the adjective would have been sufficient.
finally one thing to note is that
by itself is just silly
Which is exactly why it caught my attention in the first place. But of course you're right, I have written my share of copy loops as well. It's one of those things that becomes so automatic, you just don't think about it after a while.
I'm curious though... Do parens affect when the post-increment happens? In other words, is this:
different than this:
or do they do the same thing?
Re:Test kernels refuses to print to screen
Posted: Fri Apr 29, 2005 2:35 am
by Farmer
Speaking of Bran's tutorial, which I am currently using:
In the early sections of the tutorial that I am still on, Bran wants me to code my own memcpy() function. I seem to be having trouble getting this code to work. I would appreciate any input as to why???
void *memcpy(void *dest, const void *src, int count)
{
char *destptr = (char *)dest;
const char *srcptr = (const char *)src;
int i = 0;
while(i < count){
*destptr = *srcptr;
destptr++;
srcptr++;
i++;
}
}
Re:Test kernels refuses to print to screen
Posted: Fri Apr 29, 2005 8:10 am
by proxy
are the same thing, because like i said, the ++ goes first by default anyway
if you want to increment what it points to:
will do nicely
proxy
Re:Test kernels refuses to print to screen
Posted: Fri Apr 29, 2005 8:13 am
by proxy
Farmer I don't see anything wrong with it at first glance besides the fact that you define the function as returning a void * and return nothing (which means whatever happens to be in eax when it's done will be returned...)
here's what my memcpy looks like
Code: Select all
void *memcpy(void *dest, const void *src, size_t n) {
char *d_ptr = dest;
const char *s_ptr = src;
assert(dest != 0);
assert(src != 0);
while(n--) {
*d_ptr++ = *s_ptr++;
}
return dest;
}
Re:Test kernels refuses to print to screen
Posted: Mon May 02, 2005 4:37 am
by Solar
proxy wrote:
also a better solution than adding -fwriteable-strings is to add
*(.rodata*)
to the .data section so your string constants go in there too.
Actually that is the
only solution that will still work with GCC 4.x, which no longer accepts -fwriteable-strings.
Re:Test kernels refuses to print to screen
Posted: Tue Oct 11, 2005 2:03 pm
by TheChuckster
I fixed it by changing the linker script to link to an ELF file.
Re:Test kernels refuses to print to screen
Posted: Thu Oct 27, 2005 11:38 am
by dan
I have the same problem described in the origonal post.
Im not sure exactly where to add *(.rodata*) to, I tried adding it in the .data section of my linker script, but it didn't fix the problem.
My linker script looks pretty much the exact same as the one in the origonal post. Any help would be greatly appreciated.
By the way, it seems to work if I push the address of the first character of my string onto the stack and manually call my puts function from the assembly code, but if I call it from the C code, it will not work.