TCC: Difference between revisions

[unchecked revision][unchecked revision]
Content deleted Content added
m Removed 64 byte header info and added -static flag to kernel compilation command to remove that header
m Bot: Replace deprecated source tag with syntaxhighlight
 
(6 intermediate revisions by 6 users not shown)
Line 9:
16/64-bit support, instructions up to MMX are supported.
 
Note: The Windows version of TCC doesn't producesproduce ELF executables, but only object files. You
need to recompile TCC without PE support, if you want to use this tutorial on Windows. You can
skip this step if you aren't using Windows.
 
==Building TCC with ELF support==
===Windows===
1. Download [http://download.savannah.gnu.org/releases/tinycc/tcc-0.9.26.tar.bz2 TCC sources] and [http://download.savannah.gnu.org/releases/tinycc/tcc-0.9.26-win32-bin.zip 32-bit TCC] and (if you have a 64-bit OS) [http://download.savannah.gnu.org/releases/tinycc/tcc-0.9.26-win64-bin.zip 64-bit TCC].
 
Line 22 ⟶ 23:
4. Open Notepad or another text editor, and enter this:
 
<sourcesyntaxhighlight lang="winbatch">
@echo off
 
Line 95 ⟶ 96:
 
:finished
</syntaxhighlight>
</source>
 
5. Save to tcc-0.9.26 with any name you want, but the extension MUST be .bat. If you use notepad, you will have to change the type from "Text Documents" to "All Files".
Line 101 ⟶ 102:
6. Run the script, make sure everything compiled correctly (note that there may be warnings about assignments from incompatible pointer types and bound checking not supporting malloc in a certain environment, but these are okay), and inside win32-elf you should have a working ELF compiler. You should also have win32 and win64 for 32-bit and 64-bit PE compilers, and a 64-bit ELF compiler in win64-elf. Note: The 64-bit compilers won't be compiled on a non-64 bit OS.
If there are errors compiling TCC, just change the "@echo off" to "@echo on" and run the script again to see where things went wrong.
 
===Linux===
Your distribution may already provide a package for tcc. If not, download the sources from https://download.savannah.gnu.org/releases/tinycc/ and go on from there. You know how to build a program from scratch, right?
 
==A small kernel example==
Line 107 ⟶ 111:
 
===start32.asm===
<sourcesyntaxhighlight lang="asm">
; Tutorial: A small kernel with Fasm & TCC
; By Tommy.
Line 145 ⟶ 149:
jmp @b
 
</syntaxhighlight>
</source>
 
===kernel.c===
<sourcesyntaxhighlight lang="c">
/* Tutorial: A small kernel with Fasm & TCC
* By Tommy.
Line 171 ⟶ 175:
}
 
</syntaxhighlight>
</source>
 
==Compiling and linking==
Assemble start32.asm with:
<sourcesyntaxhighlight lang="bash">
fasm start32.asm
</syntaxhighlight>
</source>
 
Compile kernel.c with:
<sourcesyntaxhighlight lang="bash">
tcc -c kernel.c
</syntaxhighlight>
</source>
 
Then link the whole thing with:
<sourcesyntaxhighlight lang="bash">
tcc -nostdlib -Wl,-Ttext,0x100000 start32.o kernel.o -o kernel-i386.elf
</syntaxhighlight>
</source>
 
If you would prefer it in binary form, for example, if you're using your own bootloader that doesn't support ELF, link it with this:
<sourcesyntaxhighlight lang="bash">
tcc -nostdlib -Wl,-Ttext,0x100000 -Wl,--oformat,binary -static start32.o kernel.o -o kernel-i386.bin
</syntaxhighlight>
</source>
 
That's all!
Line 198 ⟶ 202:
==Inline Assembly==
TCC supports inline GAS syntax assembly like GCC:
<sourcesyntaxhighlight lang="c">
__asm__ __volatile__("hlt");
</syntaxhighlight>
</source>
You can use this to your benefit for many things, such as debugging in Bochs:
<sourcesyntaxhighlight lang="c">
#define breakpoint() __asm__ __volatile__("xchg %bx, %bx");
 
Line 212 ⟶ 216:
}
}
</syntaxhighlight>
</source>
Then adding this to your bochsrc.bxrc file in a text editor:
<sourcesyntaxhighlight lang="text">
port_e9_hack: enabled=1
magic_break: enabled=1
</syntaxhighlight>
</source>
And from boch's install location, executing bochsdbg.exe instead of bochs.exe.
 
Line 224 ⟶ 228:
So if you use structs to store your GDT entries or GDTR, beware, you will encounter issues loading your GDT if you don't specify the packing of structures correctly.
When creating structures, use something like this:
<sourcesyntaxhighlight lang="c">
// We use the attribute 'packed' to tell TCC not to change any of the alignment in the structure.
struct some_struct {
Line 232 ⟶ 236:
// This last attribute can be kept, it won't interfere with the compilation or output, so it may be
// useful to retain compatilbity with GCC, as long as the above attributes don't interfere with GCC.
</syntaxhighlight>
</source>
Instead of this:
<sourcesyntaxhighlight lang="c">
// We use the attribute 'packed' to tell GCC not to change any of the alignment in the structure.
struct some_struct {
Line 240 ⟶ 244:
unsigned char b;
} __attribute__((packed));
</syntaxhighlight>
</source>
 
 
==Inline Function Warning==
TCC doesn't support function inlining, because the 'inline' keyword is ignored, so if a function needs to be inlined, you must use defines instead.
 
==stdint.h==
TCC doesn't include stdint.h, but all typedefs required are provided in stddef.h.
To use stdint.h place the following code in your kernels include path as stdint.h. This will make your code compatible with both gcc and tcc.
<syntaxhighlight lang="c">
/* stdint.h */
 
#ifdef __TINYC__
/* tcc */
#include <stddef.h>
#else
/* assume gcc */
#include_next <stdint.h>
#endif
</syntaxhighlight>
 
[[Category:C]]
[[Category:Compilers]]