1 year ago
#71004
Charles Buchanan
Freestanding C: Why does this function fail to return data depending on the structure of the array?
I'm currently watching a Udemy tutorial on basic graphical OS development, which has just begun to explain how to render text in VBE graphical mode using bitmap fonts. The presenter creates a function (auto-generated by a python script) to return a given row of a given character by looking it up in a set of arrays.
The key point here is that the code uses a set of arrays of binary data, each containing the bitmaps of 13 characters, like so.
int getArialCharacter(int index, int y) {
unsigned int characters_arial_0[][150] = {
{ // List of 15 10-digit binary numbers, corresponding to rows of ASCII code 0 },
{ // List of 15 10-digit binary numbers, corresponding to rows of ASCII code 1 },
...
{ // List of 15 10-digit binary numbers, corresponding to rows of ASCII code 12 }
};
unsigned int characters_arial_1[][150] = { ... };
unsigned int characters_arial_2[][150] = { ... };
unsigned int characters_arial_3[][150] = { ... };
unsigned int characters_arial_4[][150] = { ... };
unsigned int characters_arial_5[][150] = { ... };
unsigned int characters_arial_6[][150] = { ... };
unsigned int characters_arial_7[][150] = { ... };
int start = (int)(' ');
if (index >= start && index < start + 13) {
return characters_arial_0[index - start][y];
}
else if (index >= start + 13 && index < start + 13 * 2) {
return characters_arial_1[index - (start + 13)][y];
}
...
else if (index >= start + 13 * 7 && index < start + 13 * 8) {
return characters_arial_7[index - (start + 13 * 7)][y];
}
}
I thought this seemed odd and unnecessary, so I tried refactoring it to use a single array (albeit with a different font), like so:
int font_func(int index, int y)
{
// I also tried uint8_t[128][64]
uint8_t chars[][64] = {
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // U+0000 (nul)
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // U+0001
...
};
return chars[index][y];
}
However, when I attempted to use this, no text printed to the screen at all. I can think of 3 explanations for this, but none fully satisfy me:
-
- Since our linker only links the text sections and does not link data sections (the link command is
ld -m elf_i386 -o boot/bin/kernel.img -Ttext 0x1000 boot/bin/kernel_entry.bin boot/bin/kernel.o
), the large array won't get linked. This explanation seems weak, since the individual, smaller arrays in the tutorial's version were linked fine.
- Since our linker only links the text sections and does not link data sections (the link command is
-
- Since memcpy hasn't been implemented, declaring large data structures with optimizations turned on results in a call to memcpy that doesn't go right. This explanation also seems weak, since I would expect a compiler warning.
-
- I made some error elsewhere in the implementation. It seems unlikely, since the only thing I changed was the function pointer which got passed to the printing function. (For the record, I've tried accounting for signed and unsigned chars. No luck.)
What does the locus of this issue seem to be? Thanks for the help.
The makefile for this project is shown below, if it helps:
all: bootloader
bootloader:
nasm boot/boot.asm -f bin -o boot/bin/boot.bin
nasm boot/kernel_entry.asm -f elf -o boot/bin/kernel_entry.bin
gcc -m32 -fno-lto -nostdlib -ffreestanding -nodefaultlibs -c boot/final.c -o boot/bin/kernel.o
ld -m elf_i386 -o boot/bin/kernel.img -Ttext 0x1000 boot/bin/kernel_entry.bin boot/bin/kernel.o
objcopy -O binary -j .text boot/bin/kernel.img boot/bin/kernel.bin
cat boot/bin/boot.bin boot/bin/kernel.bin > os.img
clear:
rm -f boot/boot.img
run:
qemu-system-x86_64 -vga virtio -drive format=raw,file=os.img
EDIT 2: Minimum reproducible example can be found here: https://drive.google.com/drive/folders/1Z5wlXrtRbXQ1wNhBU2_YsSMovaGe7DvB?usp=sharing
c
ld
vesa
freestanding
0 Answers
Your Answer