I’ve been following the tutorial at https://github.com/cfenollosa/os-tutorial to create a custom 32-bit os on x86_64 asm and c, and i got to the screen drivers part which is about writing to the vga buffer to display characters on the screen from inside the kernel.
I prefer c++ so im using it instead of c, but now im getting this issue where if i use a char pointer to store a string instead of a int pointer i can’t get to display anything.
This is my main function, where i initialize the pointer and populate it with characters from A to L, which works if i use a int pointer, but not with a char one.
char* ptr = (char*)0x11000FF; // int* ptr = (int*)0x11000FF works
for(int i = 0; i < size; i++){
for(int i = 0; i < size; i++){
<code>#define size 12
int main(){
char* ptr = (char*)0x11000FF; // int* ptr = (int*)0x11000FF works
for(int i = 0; i < size; i++){
ptr[i] = 'A'+i;
}
ptr[size+1] = '';
for(int i = 0; i < size; i++){
printChar(i,0,ptr[i]);
}
}
</code>
#define size 12
int main(){
char* ptr = (char*)0x11000FF; // int* ptr = (int*)0x11000FF works
for(int i = 0; i < size; i++){
ptr[i] = 'A'+i;
}
ptr[size+1] = '';
for(int i = 0; i < size; i++){
printChar(i,0,ptr[i]);
}
}
Here is my print function
<code>#define VIDEO_ADDRESS 0xB8000
#define WHITE_ON_BLACK 0x0F
void printChar(unsigned int x, unsigned int y, char c){
char* videoMem = (char*)VIDEO_ADDRESS;
unsigned int offset = ((y*MAX_COLS + x)*2)+1;
videoMem[offset+1] = WHITE_ON_BLACK;
<code>#define VIDEO_ADDRESS 0xB8000
#define MAX_ROWS 25
#define MAX_COLS 80
#define WHITE_ON_BLACK 0x0F
#include "screen.h"
void printChar(unsigned int x, unsigned int y, char c){
char* videoMem = (char*)VIDEO_ADDRESS;
unsigned int offset = ((y*MAX_COLS + x)*2)+1;
videoMem[offset] = c;
videoMem[offset+1] = WHITE_ON_BLACK;
}
</code>
#define VIDEO_ADDRESS 0xB8000
#define MAX_ROWS 25
#define MAX_COLS 80
#define WHITE_ON_BLACK 0x0F
#include "screen.h"
void printChar(unsigned int x, unsigned int y, char c){
char* videoMem = (char*)VIDEO_ADDRESS;
unsigned int offset = ((y*MAX_COLS + x)*2)+1;
videoMem[offset] = c;
videoMem[offset+1] = WHITE_ON_BLACK;
}
And here is my Makefile
BOOTLOADER_DIR=$(SOURCE_DIR)/bootloader
KERNEL_DIR=$(SOURCE_DIR)/kernel
SRCs := $(shell find $(SOURCE_DIR) -name '*.cpp') #List of all .cpp files
OBJS := $(patsubst $(SOURCE_DIR)/%.cpp,$(BUILD_DIR)/%.o,$(SRCs)) #List of all c++ object files
all: folder run clean #Build from zero and wipe
qemu-system-x86_64 -drive file=$(BUILD_DIR)/$<,format=raw,index=0,media=disk
os.iso: bootloader.bin kernel.bin #Concatenate bootloader and kernel into single file
cat $(BUILD_DIR)/bootloader.bin $(BUILD_DIR)/kernel.bin > $(BUILD_DIR)/$@
bootloader.bin: $(BOOTLOADER_DIR)/bootloader.asm #Compile bootloader
nasm $< -f bin -o $(BUILD_DIR)/$@
kernel.bin: entry.o $(OBJS) #Link all object files
x86_64-elf-ld -o $(BUILD_DIR)/$@ -Ttext 0x512 $(BUILD_DIR)/$< $(OBJS) --oformat binary
entry.o: $(KERNEL_DIR)/kernelentry.asm #Compile kernel entry point
nasm $< -f elf64 -o $(BUILD_DIR)/$@
$(BUILD_DIR)/%.o: $(SOURCE_DIR)/%.cpp #Generic for compiling .cpp files
g++ -c $< -o $@ -fpermissive
folder: #Create build folder
mkdir -p $(BUILD_DIR)/kernel/drivers
clean: #Wipe build folder
<code>SOURCE_DIR=source
BOOTLOADER_DIR=$(SOURCE_DIR)/bootloader
KERNEL_DIR=$(SOURCE_DIR)/kernel
BUILD_DIR=build
SRCs := $(shell find $(SOURCE_DIR) -name '*.cpp') #List of all .cpp files
OBJS := $(patsubst $(SOURCE_DIR)/%.cpp,$(BUILD_DIR)/%.o,$(SRCs)) #List of all c++ object files
all: folder run clean #Build from zero and wipe
run: os.iso #Start VM
qemu-system-x86_64 -drive file=$(BUILD_DIR)/$<,format=raw,index=0,media=disk
os.iso: bootloader.bin kernel.bin #Concatenate bootloader and kernel into single file
cat $(BUILD_DIR)/bootloader.bin $(BUILD_DIR)/kernel.bin > $(BUILD_DIR)/$@
bootloader.bin: $(BOOTLOADER_DIR)/bootloader.asm #Compile bootloader
nasm $< -f bin -o $(BUILD_DIR)/$@
kernel.bin: entry.o $(OBJS) #Link all object files
x86_64-elf-ld -o $(BUILD_DIR)/$@ -Ttext 0x512 $(BUILD_DIR)/$< $(OBJS) --oformat binary
entry.o: $(KERNEL_DIR)/kernelentry.asm #Compile kernel entry point
nasm $< -f elf64 -o $(BUILD_DIR)/$@
$(BUILD_DIR)/%.o: $(SOURCE_DIR)/%.cpp #Generic for compiling .cpp files
g++ -c $< -o $@ -fpermissive
folder: #Create build folder
mkdir -p $(BUILD_DIR)/kernel/drivers
clean: #Wipe build folder
rm -rf $(BUILD_DIR)/*
</code>
SOURCE_DIR=source
BOOTLOADER_DIR=$(SOURCE_DIR)/bootloader
KERNEL_DIR=$(SOURCE_DIR)/kernel
BUILD_DIR=build
SRCs := $(shell find $(SOURCE_DIR) -name '*.cpp') #List of all .cpp files
OBJS := $(patsubst $(SOURCE_DIR)/%.cpp,$(BUILD_DIR)/%.o,$(SRCs)) #List of all c++ object files
all: folder run clean #Build from zero and wipe
run: os.iso #Start VM
qemu-system-x86_64 -drive file=$(BUILD_DIR)/$<,format=raw,index=0,media=disk
os.iso: bootloader.bin kernel.bin #Concatenate bootloader and kernel into single file
cat $(BUILD_DIR)/bootloader.bin $(BUILD_DIR)/kernel.bin > $(BUILD_DIR)/$@
bootloader.bin: $(BOOTLOADER_DIR)/bootloader.asm #Compile bootloader
nasm $< -f bin -o $(BUILD_DIR)/$@
kernel.bin: entry.o $(OBJS) #Link all object files
x86_64-elf-ld -o $(BUILD_DIR)/$@ -Ttext 0x512 $(BUILD_DIR)/$< $(OBJS) --oformat binary
entry.o: $(KERNEL_DIR)/kernelentry.asm #Compile kernel entry point
nasm $< -f elf64 -o $(BUILD_DIR)/$@
$(BUILD_DIR)/%.o: $(SOURCE_DIR)/%.cpp #Generic for compiling .cpp files
g++ -c $< -o $@ -fpermissive
folder: #Create build folder
mkdir -p $(BUILD_DIR)/kernel/drivers
clean: #Wipe build folder
rm -rf $(BUILD_DIR)/*
I would expect for these two to do the same, since they are both being casted into a char when passed into the printChar function, and data size in memory shouldn’t matter since they are being passed into it by index.