I was making an os, or atleast trying to, but I stumbled upon a problem. While trying to iterate over a string to convert to char to print to screen, the returned char seemed to be empty!(I am actually new to os development); Here is the code snippet:
int offset = 0;
void clear_screen() {
unsigned char * video = 0xB8000;
for(int i = 0; i < 2000; i =2){
video[i] = ' ';
}
}
void printc(char c) {
unsigned char * video = 0xB8000;
video[offset] = c;
video[offset 1] = 0x03;
offset = 2;
}
void print(unsigned char *string) {
char * sus = '\0';
uint32 i = 0;
printc('|');
sus[0] = 'a';
printc(sus[0]); //this prints "a" correctly
string[i] = 'c';
while (string[i] != '\0') {
printc(string[i]); //this while loop is only called once
i ; //it prints " " only once and exits
}
printc('|');
}
int bootup(void)
{
clear_screen();
// printc('h');
// printc('e');
// printc('l'); /* These work */
// printc('l');
// printc('o');
print("hello"); //this doesn't
return 1;
}
Output that it prints:
|a |
Thanks in advance!!
edit
New print function
void print(unsigned char *string) {
uint32 i = 0;
printc('|');
while (string[i] != '\0') {
printc('i'); //not printed
printc(string[i]);
i ;
}
printc('|');
}
still does not work
edit 2 updated the code as per @lundin's advice
int offset = 0;
void clear_screen() {
unsigned char * video = (unsigned char *)0xB8000;
for(int i = 0; i < 2000; i =2){
video[i] = ' ';
}
}
void printc(char c) {
unsigned char * video = (unsigned char *)0xB8000;
video[offset] = c;
video[offset 1] = 0x03;
offset = 2;
}
void print(const char *string) {
int i = 0;
printc('|');
while (string[i] != '\0') {
printc('i');
printc(string[i]);
i ;
}
printc('|');
}
int bootup(void)
{
clear_screen();
// printc('h');
// printc('e');
// printc('l');
// printc('l');
// printc('o');
print("hello");
return 1;
}
stack:
init_lm:
mov ax, 0x10
mov fs, ax ;other segments are ignored
mov gs, ax
mov rbp, 0x90000 ;set up stack
mov rsp, rbp
;Load kernel from disk
xor ebx, ebx ;upper 2 bytes above bh in ebx is for cylinder = 0x0
mov bl, 0x2 ;read from 2nd sectors
mov bh, 0x0 ;head
mov ch, 1 ;read 1 sector
mov rdi, KERNEL_ADDRESS
call ata_chs_read
jmp KERNEL_ADDRESS
jmp $
CodePudding user response:
Your program has undefined behavior since it contains multiple lines that aren't valid C. You will have gotten compiler messages about those lines.
unsigned char * video = 0xB8000;etc is not valid C, you need an explicit cast. "Pointer from integer/integer from pointer without a cast" issues- Similarly,
char * sus = '\0';is also not valid C. You are trying to assign a pointer to a single character, which doesn't make sense. String handling beginner FAQ here: Common string handling pitfalls in C programming. It also addresses memory allocation basics. sus[0] = 'a';etc here you have wildly undefined behavior sincesusisn't pointing at valid memory.- In case you are actually trying to access physical memory addresses, this isn't the correct way to do so. You need volatile qualified pointers. See How to access a hardware register from firmware? (In your case it probably isn't a register but everything from that link still applies - how to use hex constants etc.)
- EDIT:
void print(unsigned char *string)...string[i] = 'c';is also wrong. First of all you are passing achar*which is not necessarily compatible withunsigned char*. Then you shouldn't modify the passed string from inside a function calledprint, that doesn't make sense. This should have beenconst char* stringto prevent such bugs. As it stands you are passing a string literal to this function and then try to modify it - that is undefined behavior since string literals are read-only.
Assuming gcc or clang, if you wish to block the compiler from generating an executable out of invalid C code, check out What compiler options are recommended for beginners learning C? In your case you also likely need the -ffreestanding option mentioned there.
CodePudding user response:
char * sus = '\0';
Have not checked more... but this assigns a null pointer to sus, and most probably is not what you want to do.
