c hello world works
This commit is contained in:
23
README.adoc
23
README.adoc
@@ -239,8 +239,6 @@ Source: link:bios_hello_world.S[]
|
|||||||
|
|
||||||
==== C hello world
|
==== C hello world
|
||||||
|
|
||||||
TODO get working.
|
|
||||||
|
|
||||||
Same output as <<bios-hello-world>>, but written in C:
|
Same output as <<bios-hello-world>>, but written in C:
|
||||||
|
|
||||||
....
|
....
|
||||||
@@ -250,7 +248,13 @@ cd c_hello_world
|
|||||||
|
|
||||||
Source: link:c_hello_world[]
|
Source: link:c_hello_world[]
|
||||||
|
|
||||||
Single stage, so still limited to 512 bytes of code + data!
|
But keep in mind the following limitations and difficulties:
|
||||||
|
|
||||||
|
* single stage, so still limited to 512 bytes of code + data!
|
||||||
|
* use use GCC's `-m` which does not produce "real" 16 bit code, but rather 32-bit code with `0x66` and `0x67` prefixes: https://wiki.osdev.org/X86-64_Instruction_Encoding#Legacy_Prefixes
|
||||||
|
* setting up the initial state and the linker script is much harder and error prone than with assembly
|
||||||
|
|
||||||
|
Therefore, for most applications, you will just want to use <<multiboot>> instead, which overcomes all of those problems.
|
||||||
|
|
||||||
To disassemble the generated C code, try:
|
To disassemble the generated C code, try:
|
||||||
|
|
||||||
@@ -258,11 +262,20 @@ To disassemble the generated C code, try:
|
|||||||
objdump -D -m i8086 main.elf
|
objdump -D -m i8086 main.elf
|
||||||
....
|
....
|
||||||
|
|
||||||
TODO: I see several `eax` references still, why?
|
but note that it still contains references to 32-bit references, e.g.:
|
||||||
|
|
||||||
|
....
|
||||||
|
00007c17 <main>:
|
||||||
|
7c17: 66 55 push %ebp
|
||||||
|
7c19: 66 89 e5 mov %esp,%ebp
|
||||||
|
7c1c: 66 83 ec 10 sub $0x10,%esp
|
||||||
|
....
|
||||||
|
|
||||||
|
This is because those instructions are modified by the prefix `0x66`, which makes them behave like 32-bit.
|
||||||
|
|
||||||
=== No linker script
|
=== No linker script
|
||||||
|
|
||||||
Print `hello world` without using an explitic linker script:
|
Print `hello world` without using an explicit linker script:
|
||||||
|
|
||||||
....
|
....
|
||||||
make -C no-linker-script run
|
make -C no-linker-script run
|
||||||
|
|||||||
2
c_hello_world/clean
Executable file
2
c_hello_world/clean
Executable file
@@ -0,0 +1,2 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
rm -f *.o *.elf *.img
|
||||||
@@ -2,5 +2,12 @@
|
|||||||
.text
|
.text
|
||||||
.global mystart
|
.global mystart
|
||||||
mystart:
|
mystart:
|
||||||
mov $__stack_top, %sp
|
ljmp $0, $.setcs
|
||||||
|
.setcs:
|
||||||
|
xor %ax, %ax
|
||||||
|
mov %ax, %ds
|
||||||
|
mov %ax, %es
|
||||||
|
mov %ax, %ss
|
||||||
|
mov $__stack_top, %esp
|
||||||
|
cld
|
||||||
call main
|
call main
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ SECTIONS
|
|||||||
*(.data)
|
*(.data)
|
||||||
*(.rodata)
|
*(.rodata)
|
||||||
__bss_start = .;
|
__bss_start = .;
|
||||||
|
/* COMMON vs BSS: https://stackoverflow.com/questions/16835716/bss-vs-common-what-goes-where */
|
||||||
*(.bss)
|
*(.bss)
|
||||||
|
*(COMMON)
|
||||||
__bss_end = .;
|
__bss_end = .;
|
||||||
}
|
}
|
||||||
/* https://stackoverflow.com/questions/53584666/why-does-gnu-ld-include-a-section-that-does-not-appear-in-the-linker-script */
|
/* https://stackoverflow.com/questions/53584666/why-does-gnu-ld-include-a-section-that-does-not-appear-in-the-linker-script */
|
||||||
|
|||||||
@@ -1,18 +1,11 @@
|
|||||||
void main(void) {
|
void main(void) {
|
||||||
int i;
|
int i;
|
||||||
char s[] = "hello world";
|
char s[] = {'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd'};
|
||||||
/* Add a bunch of debug prints to see if the control loop is correct. It is. */
|
|
||||||
__asm__ ("mov $0x0E40, %ax; int $0x10");
|
|
||||||
for (i = 0; i < sizeof(s); ++i) {
|
for (i = 0; i < sizeof(s); ++i) {
|
||||||
__asm__ ("mov $0x0E41, %ax; int $0x10");
|
|
||||||
__asm__ (
|
__asm__ (
|
||||||
"mov %0, %%ax; int $0x10"
|
"int $0x10" : : "a" ((0x0e << 8) | s[i])
|
||||||
:
|
|
||||||
: "m" (s[i])
|
|
||||||
: "%ax"
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
__asm__ ("mov $0x0E40, %ax; int $0x10");
|
|
||||||
while (1) {
|
while (1) {
|
||||||
__asm__ ("hlt");
|
__asm__ ("hlt");
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -eux
|
set -eux
|
||||||
as -ggdb3 --32 -o entry.o entry.S
|
as -ggdb3 --32 -o entry.o entry.S
|
||||||
gcc -c -ggdb3 -m16 -nostartfiles -nostdlib -o main.o -std=c99 main.c
|
gcc -c -ggdb3 -m16 -ffreestanding -fno-PIE -nostartfiles -nostdlib -o main.o -std=c99 main.c
|
||||||
ld -m elf_i386 -o main.elf -T linker.ld entry.o main.o
|
ld -m elf_i386 -o main.elf -T linker.ld entry.o main.o
|
||||||
objcopy -O binary main.elf main.img
|
objcopy -O binary main.elf main.img
|
||||||
qemu-system-x86_64 -drive file=main.img,format=raw
|
qemu-system-x86_64 -drive file=main.img,format=raw
|
||||||
|
|||||||
Reference in New Issue
Block a user