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.
For those of you who were helping me set up GCC on windows recently, I just wanted to say thanks for the help, but I switched to linux. It was just pissing me way to much.. Anyway, now that I know how to boot a basic floppy image, I'm trying to understand the code. First of all, I know what's all of this about a multiboot header in the bare bones tutorial loader.s? What is a multiboot header? Then there's the code:
Offset should be a number that shows where the current position on screen is. You can also find it by creating cursor_x and y variables that keeps track of the x, y position.
piranha wrote:Yeah, sure. But that wasn't supposed to be copied, that was just an example. Proper implementation should be done.
OP: Adding on what piranha said, a slightly more proper implementation must have at least a newline handler (print \r\n when \n is encountered) a method of calculating the offset from 0xB8000 using the cursor position, and updating the cursor. I'd say a fully complete implementation of string printing is a working printf() function.
Solar wrote:It keeps stunning me how friendly we - as a community - are towards people who start programming "their first OS" who don't even have a solid understanding of pointers, their compiler, or how a OS is structured.
int x=0, y=0;
void puts(const char *str) {
while(*str) {
if(*str == '\n')
{ //Handle newline
str++;
x=0;y++;
}
videoram[y*80+x] = *str; /* character */
videoram[y*80+x+1] = 0x07; /* forground, background color. */
x++;
if(x > 80)
{ //If we reached to edge of the screen
x=0;
y++;
}
str++;
}
}
int main() {
...
puts("Hi\n");
...
}
Note: You should also add code for scrolling, so when the code gets to the bottom of the screen it scrolls up one line. That can be done by copying all lines of memory back the length of one line.
And about the multiboot header, is it's purpose so that you can boot different types of OS's from that one bootloader? What do the operations 1<<0 and 1<<1 do in assembly? I couldn't find them in any tutorials...
// monitor.h -- Defines the interface for monitor.h
// From JamesM's kernel development tutorials.
#ifndef MONITOR_H
#define MONITOR_H
#include "common.h"
int cursor_x, cursor_y = 0;
unsigned char *video_memory = (unsigned char *) 0xb8000;
// Scrolls the text on the screen up by one line.
static void scroll()
{
// Get a space character with the default colour attributes.
u8int attributeByte = (0 /*black*/ << 4) | (15 /*white*/ & 0x0F);
u16int blank = 0x20 /* space */ | (attributeByte << 8);
// Row 25 is the end, this means we need to scroll up
if(cursor_y >= 25)
{
// Move the current text chunk that makes up the screen
// back in the buffer by a line
int i;
for (i = 0*80; i < 24*80; i++)
{
video_memory[i] = video_memory[i+80];
}
// The last line should now be blank. Do this by writing
// 80 spaces to it.
for (i = 24*80; i < 25*80; i++)
{
video_memory[i] = blank;
}
// The cursor should now be on the last line.
cursor_y = 24;
}
// Updates the hardware cursor.
static void move_cursor()
{
// The screen is 80 characters wide...
u16int cursorLocation = cursor_y * 80 + cursor_x;
outb(0x3D4, 14); // Tell the VGA board we are setting the high cursor byte.
outb(0x3D5, cursorLocation >> 8); // Send the high cursor byte.
outb(0x3D4, 15); // Tell the VGA board we are setting the low cursor byte.
outb(0x3D5, cursorLocation); // Send the low cursor byte.
}
// Clears the screen, by copying lots of spaces to the framebuffer.
void monitor_clear()
{
// Make an attribute byte for the default colours
u8int attributeByte = (0 /*black*/ << 4) | (15 /*white*/ & 0x0F);
u16int blank = 0x20 /* space */ | (attributeByte << 8);
int i;
for (i = 0; i < 80*25; i++)
{
video_memory[i] = blank;
}
// Move the hardware cursor back to the start.
cursor_x = 0;
cursor_y = 0;
move_cursor();
}
// Writes a single character out to the screen.
void monitor_put(char c)
{
// The background colour is black (0), the foreground is white (15).
u8int backColour = 0;
u8int foreColour = 15;
// The attribute byte is made up of two nibbles - the lower being the
// foreground colour, and the upper the background colour.
u8int attributeByte = (backColour << 4) | (foreColour & 0x0F);
// The attribute byte is the top 8 bits of the word we have to send to the
// VGA board.
u16int attribute = attributeByte << 8;
u16int *location;
// Handle a backspace, by moving the cursor back one space
if (c == 0x08 && cursor_x)
{
cursor_x--;
}
// Handle a tab by increasing the cursor's X, but only to a point
// where it is divisible by 8.
else if (c == 0x09)
{
cursor_x = (cursor_x+8) & ~(8-1);
}
// Handle carriage return
else if (c == '\r')
{
cursor_x = 0;
}
// Handle newline by moving cursor back to left and increasing the row
else if (c == '\n')
{
cursor_x = 0;
cursor_y++;
}
// Handle any other printable character.
else if(c >= ' ')
{
location = video_memory + (cursor_y*80 + cursor_x);
*location = c | attribute;
cursor_x++;
}
// Check if we need to insert a new line because we have reached the end
// of the screen.
if (cursor_x >= 80)
{
cursor_x = 0;
cursor_y ++;
}
// Scroll the screen if needed.
scroll();
// Move the hardware cursor.
move_cursor();
}
// Outputs a null-terminated ASCII string to the monitor.
void monitor_write(char *c)
{
int i = 0;
while (c[i])
{
monitor_put(c[i++]);
}
}
#endif // MONITOR_H
In file included from Source Files/kernel.c:2:
/home/gulshan/Documents/OS/monitor.h: In function ‘scroll’:
/home/gulshan/Documents/OS/monitor.h:43: error: invalid storage class for function ‘move_cursor’
/home/gulshan/Documents/OS/monitor.h: In function ‘monitor_put’:
/home/gulshan/Documents/OS/monitor.h:114: warning: assignment from incompatible pointer type
Source Files/kernel.c: In function ‘scroll’:
Source Files/kernel.c:9: error: expected declaration or statement at end of input
Source Files/kernel.c: At top level:
Source Files/kernel.c:5: warning: unused parameter ‘mbd’
Source Files/kernel.c:5: warning: unused parameter ‘magic’
// The cursor should now be on the last line.
cursor_y = 24;
}
} // <- You forgot to add this.
// Updates the hardware cursor.
static void move_cursor()
Apart from that, I wouldn't recommend having that code in a header (usually you just put prototypes of the functions you need to access from other source files)... But for now it will do, I suppose.
Classes don't exist in C. You'll have to do without them.
Solar wrote:It keeps stunning me how friendly we - as a community - are towards people who start programming "their first OS" who don't even have a solid understanding of pointers, their compiler, or how a OS is structured.