问题
I'm following this tutorial to make a simple bare bones 32-bit operating system. I have gotten as far as section 4 where i'm writing to the frame buffer. Basically i'm attempting to create my own println function. Here is the code for my function:
/** fb_write_cell:
* Writes a character with the given foreground and background to position i
* in the framebuffer.
*
* @param i The location in the framebuffer
* @param c The character
* @param fg The foreground color
* @param bg The background color
*/
static void fb_write_cell(unsigned int i, char c, unsigned char fg, unsigned bg) {
fb[i] = c;
fb[i + 1] = ((fg & 0x0F) << 4) | (bg & 0x0F);
}
/** fb_print:
* Print a string of text to the framebuffer
* @param *buf The character array to print
*/
int fb_print(char *str, unsigned int length) {
unsigned int i = 0, x = 0;
// print the message to the framebuffer
for(; i < (2 * length); i+=2) {
fb_write_cell(i, str[x], FB_BLACK, FB_GREEN);
x++;
}
return 0;
}
/** fb_println:
* Print a string of text to the framebuffer and move to the next line
* @param *buf The character array to print
*/
int fb_println(char *str, unsigned int length) {
fb_print(str, length);
return 0;
}
I call it like this:
char array[] = "Hello world!";
fb_println(array, sizeof(array));
However if I make the array longer than 61 characters I stop getting any output to the screen. In fact any code after the array creation doesn't get executed. I'm thinking that maybe it has something to do with limited RAM in my bare system (maybe only 64 bytes?) but I'm not sure.
My multiboot header and startup code in loader.s
that calls my C entry point main
is:
global loader ; the entry symbol for ELF
MAGIC_NUMBER equ 0x1BADB002 ; define the magic number constant
FLAGS equ 0x0 ; multiboot flags
CHECKSUM equ -MAGIC_NUMBER ; calculate the checksum
; (magic number + checksum + flags should equal 0)
KERNEL_STACK_SIZE equ 4096 ; size of stack in bytes
extern sum_of_three ; the function is defined elsewhere
extern main
section .text: ; start of the text (code) section
align 4 ; the code must be 4 byte aligned
dd MAGIC_NUMBER ; write the magic number to the machine code,
dd FLAGS ; the flags,
dd CHECKSUM ; and the checksum
section .bss:
align 4 ; align at 4 bytes
kernel_stack: ; label points to beginning of memory
resb KERNEL_STACK_SIZE ; reserve stack for the kernel
loader: ; the loader label (defined as entry point in linker script)
mov eax, 0xCAFEBABE ; place the number 0xCAFEBABE in the register eax
mov esp, kernel_stack + KERNEL_STACK_SIZE ; point esp to the start of the
; stack (end of memory area)
;Example of how to call a function and send args
;push dword 3 ; arg3
;push dword 2 ; arg2
;push dword 1 ; arg1
;call sum_of_three ; call the function, the result will be in EAX
.loop:
call main
jmp .loop ; loop forever
My linker script link.ld
is:
ENTRY(loader) /* the name of the entry label */
SECTIONS {
. = 0x00100000; /* the code should be loaded at 1 MB */
.text ALIGN (0x1000) : /* align at 4 KB */
{
*(.text) /* all text sections from all files */
}
.rodata ALIGN (0x1000) : /* align at 4 KB */
{
*(.rodata*) /* all read-only data sections from all files */
}
.data ALIGN (0x1000) : /* align at 4 KB */
{
*(.data) /* all data sections from all files */
}
.bss ALIGN (0x1000) : /* align at 4 KB */
{
*(COMMON) /* all COMMON sections from all files */
*(.bss) /* all bss sections from all files */
}
}
My whole source code can be found here.
回答1:
The issues here are not related to your C code but problems in your file loader.s
. You have problems with the section names having a colon on the end that becomes part of the section name, and you haven't put the code in the executable .text
section.
These lines have extra colons on the section names:
section .text: ; start of the text (code) section
section .bss:
They should be:
section .text ; start of the text (code) section
section .bss
These extra colons cause things to be placed in unexpected way and could be influenced by the amount of data in a particular section (like strings in your C code). This likely caused your kernel.elf
to not always appear as a Multiboot compatible bootloader.
As well code needs to be placed in the .text
section. You placed your stack and the code after it in the .bss
section which is incorrect. To fix this place a section directive above the start of your code like this:
section .text
loader: ; the loader label (defined as entry point in linker script)
You also put your kernel in an infinite loop:
.loop:
call main
jmp .loop ; loop forever
You probably meant to put an infinite loop after your kernel is complete:
call main
.loop:
jmp .loop ; loop forever
Error in LittleOS Book Tutorial
I noticed that this seems to be a mistake on the part of the author of the tutorial you are using in the section Compiling the Operating System as the mistake appears in this code:
section .text: ; start of the text (code) section align 4 ; the code must be 4 byte aligned
Someone may wish to raise this issue with the author.
来源:https://stackoverflow.com/questions/46759903/why-cant-i-make-a-char-array-longer-than-61-characters-in-c