<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh-Hans-CN">
	<id>http://wiki.foofun.cn//index.php?action=history&amp;feed=atom&amp;title=TCC</id>
	<title>TCC - 版本历史</title>
	<link rel="self" type="application/atom+xml" href="http://wiki.foofun.cn//index.php?action=history&amp;feed=atom&amp;title=TCC"/>
	<link rel="alternate" type="text/html" href="http://wiki.foofun.cn//index.php?title=TCC&amp;action=history"/>
	<updated>2026-04-04T03:30:17Z</updated>
	<subtitle>本wiki上该页面的版本历史</subtitle>
	<generator>MediaWiki 1.37.1</generator>
	<entry>
		<id>http://wiki.foofun.cn//index.php?title=TCC&amp;diff=1094&amp;oldid=prev</id>
		<title>Zhang3：创建页面，内容为“{{In Progress}}  本文描述了如何使用FASM和Tiny C Compiler（又名TCC）制作一个示例ELF内核。 也可以使用NASM(Bare_Bones_With_NASM)。 TCC是一个小型且快速的C编译器，它产生x86，x86_64或ARM代码，并生成PE或ELF可执行文件。  TCC正朝着完全符合ISOC99的方向发展，并且可以像FASM一样自我编译。（译者注：自我编译，指用自身的源代码和编译器可以编译出一…”</title>
		<link rel="alternate" type="text/html" href="http://wiki.foofun.cn//index.php?title=TCC&amp;diff=1094&amp;oldid=prev"/>
		<updated>2022-03-31T08:01:03Z</updated>

		<summary type="html">&lt;p&gt;创建页面，内容为“{{In Progress}}  本文描述了如何使用&lt;a href=&quot;/index.php?title=FASM&quot; title=&quot;FASM&quot;&gt;FASM&lt;/a&gt;和&lt;a href=&quot;/index.php?title=TCC&quot; title=&quot;TCC&quot;&gt;Tiny C Compiler&lt;/a&gt;（又名TCC）制作一个示例ELF内核。 也可以使用&lt;a href=&quot;/index.php?title=NASM&quot; title=&quot;NASM&quot;&gt;NASM&lt;/a&gt;(&lt;a href=&quot;/index.php?title=Bare_Bones_With_NASM&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new&quot; title=&quot;Bare Bones With NASM（页面不存在）&quot;&gt;Bare_Bones_With_NASM&lt;/a&gt;)。 TCC是一个小型且快速的C编译器，它产生x86，x86_64或ARM代码，并生成PE或ELF可执行文件。  TCC正朝着完全符合ISOC99的方向发展，并且可以像FASM一样自我编译。（译者注：自我编译，指用自身的源代码和编译器可以编译出一…”&lt;/p&gt;
&lt;p&gt;&lt;b&gt;新页面&lt;/b&gt;&lt;/p&gt;&lt;div&gt;{{In Progress}}&lt;br /&gt;
&lt;br /&gt;
本文描述了如何使用[[FASM]]和[[TCC|Tiny C Compiler]]（又名TCC）制作一个示例ELF内核。&lt;br /&gt;
也可以使用[[NASM]]([[Bare_Bones_With_NASM]])。&lt;br /&gt;
TCC是一个小型且快速的C编译器，它产生x86，x86_64或ARM代码，并生成PE或ELF可执行文件。 &lt;br /&gt;
TCC正朝着完全符合ISOC99的方向发展，并且可以像FASM一样自我编译。（译者注：自我编译，指用自身的源代码和编译器可以编译出一个新的编译器）&lt;br /&gt;
&lt;br /&gt;
TCC还包括一个链接器和一个汇编器(仅x86)。 但是此汇编器是有限的: 不支持16/64位，支持到MMX的指令。&lt;br /&gt;
&lt;br /&gt;
注： Windows版本的TCC不生成ELF可执行文件，而只生成目标文件。 如果要在Windows上使用本教程，则需要在没有PE支持的情况下重新编译TCC。 如果不使用Windows，可以跳过此步骤。&lt;br /&gt;
&lt;br /&gt;
==构建TCC带ELF支持==&lt;br /&gt;
===Windows===&lt;br /&gt;
1. 下载 [http://download.savannah.gnu.org/releases/tinycc/tcc-0.9.26.tar.bz2 TCC源代码]和[http://download.savannah.gnu.org/releases/tinycc/tcc-0.9.26-win32-bin.zip 32位TCC]和(如果你有64位操作系统) [http://download.savannah.gnu.org/releases/tinycc/tcc-0.9.26-win64-bin.zip 64位TCC]。&lt;br /&gt;
&lt;br /&gt;
2. 解压源代码文件夹tcc-0.9.26。&lt;br /&gt;
&lt;br /&gt;
3. 将32位TCC文件保存到TCC-0.9.26所在位置的名为“Win32”的文件夹中。 如果你有64位操作系统，请创建一个win64文件夹，并将64位文件保存到同一位置的名为 “win64” 的文件夹中。&lt;br /&gt;
&lt;br /&gt;
4. 打开记事本或其他文本编辑器，然后输入以下内容：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;winbatch&amp;quot;&amp;gt;&lt;br /&gt;
@echo off&lt;br /&gt;
&lt;br /&gt;
set \p VERSION = &amp;lt; .VERSION&lt;br /&gt;
echo &amp;gt; config.h #define TCC_VERSION &amp;quot;%VERSION%&amp;quot;&lt;br /&gt;
&lt;br /&gt;
set targetP=I386&lt;br /&gt;
set B=32&lt;br /&gt;
goto begin&lt;br /&gt;
&lt;br /&gt;
:x86_64&lt;br /&gt;
set targetP=X86_64&lt;br /&gt;
set B=64&lt;br /&gt;
goto begin&lt;br /&gt;
&lt;br /&gt;
:begin&lt;br /&gt;
set targetF=PE&lt;br /&gt;
set CC=..\win%B%\tcc.exe -O0 -s -fno-strict-aliasing&lt;br /&gt;
set P=%B%&lt;br /&gt;
&lt;br /&gt;
:start&lt;br /&gt;
if %targetF%==ELF set P=%B%-elf&lt;br /&gt;
set target=-DTCC_TARGET_%targetF% -DTCC_TARGET_%targetP%&lt;br /&gt;
&lt;br /&gt;
:tools&lt;br /&gt;
%CC% %target% win%P%\tools\tiny_impdef.c -o win%P%\tiny_impdef.exe&lt;br /&gt;
%CC% %target% win%P%\tools\tiny_libmaker.c -o win%P%\tiny_libmaker.exe&lt;br /&gt;
&lt;br /&gt;
:libtcc&lt;br /&gt;
if not exist win%P%\libtcc\nul mkdir win%P%\libtcc&lt;br /&gt;
copy libtcc.h win%P%\libtcc\libtcc.h&lt;br /&gt;
%CC% %target% -shared -DLIBTCC_AS_DLL -DONE_SOURCE libtcc.c -o win%P%\libtcc.dll&lt;br /&gt;
win%P%\tiny_impdef win%P%\libtcc.dll -o win%P%\libtcc\libtcc.def&lt;br /&gt;
&lt;br /&gt;
:tcc&lt;br /&gt;
%CC% %target% tcc.c -o win%P%\tcc.exe -ltcc -Lwin%P%\libtcc&lt;br /&gt;
&lt;br /&gt;
:copy_std_includes&lt;br /&gt;
copy include\*.h win%P%\include&lt;br /&gt;
&lt;br /&gt;
:libtcc1.a&lt;br /&gt;
win%B%\tcc %target% -c lib\libtcc1.c -o win%P%\libtcc1.o&lt;br /&gt;
win%B%\tcc %target% -c win%P%\lib\crt1.c -o win%P%\crt1.o&lt;br /&gt;
win%B%\tcc %target% -c win%P%\lib\wincrt1.c -o win%P%\wincrt1.o&lt;br /&gt;
win%B%\tcc %target% -c win%P%\lib\dllcrt1.c -o win%P%\dllcrt1.o&lt;br /&gt;
win%B%\tcc %target% -c win%P%\lib\dllmain.c -o win%P%\dllmain.o&lt;br /&gt;
win%B%\tcc %target% -c win%P%\lib\chkstk.S -o win%P%\chkstk.o&lt;br /&gt;
goto lib%B%&lt;br /&gt;
&lt;br /&gt;
:lib32&lt;br /&gt;
win%B%\tcc %target% -c lib\alloca86.S -o win%P%\alloca86.o&lt;br /&gt;
win%B%\tcc %target% -c lib\alloca86-bt.S -o win%P%\alloca86-bt.o&lt;br /&gt;
win%B%\tcc %target% -c lib\bcheck.c -o win%P%\bcheck.o&lt;br /&gt;
win%P%\tiny_libmaker win%P%\lib\libtcc1.a win%P%\libtcc1.o win%P%\alloca86.o win%P%\alloca86-bt.o win%P%\crt1.o win%P%\wincrt1.o win%P%\dllcrt1.o win%P%\dllmain.o win%P%\chkstk.o win%P%\bcheck.o&lt;br /&gt;
@goto the_end&lt;br /&gt;
&lt;br /&gt;
:lib64&lt;br /&gt;
win%P%\tcc %target% -c lib\alloca86_64.S -o win%P%\alloca86_64.o&lt;br /&gt;
win%P%\tiny_libmaker win%P%\lib\libtcc1.a win%P%\libtcc1.o win%P%\alloca86_64.o win%P%\crt1.o win%P%\wincrt1.o win%P%\dllcrt1.o win%P%\dllmain.o win%P%\chkstk.o&lt;br /&gt;
&lt;br /&gt;
:the_end&lt;br /&gt;
del win%P%\*.o&lt;br /&gt;
&lt;br /&gt;
@if %targetF%==PE (&lt;br /&gt;
	@set targetF=ELF&lt;br /&gt;
	@goto start&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
@if %B%==64 goto finished&amp;amp;amp;#10;@if _%PROCESSOR_ARCHITEW6432%_==_AMD64_ goto x86_64&lt;br /&gt;
@if _%PROCESSOR_ARCHITECTURE%_==_AMD64_ goto x86_64&lt;br /&gt;
&lt;br /&gt;
:finished&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5. 使用你想要的名称保存到TCC-0.9.26，但扩展名必须是.bat。 如果使用记事本，则必须将保存对话框的类型从 “文本文档” 更改为 “所有文件”。&lt;br /&gt;
&lt;br /&gt;
6. 运行脚本，确保所有内容都正确编译（请注意，可能会有来自不兼容指针类型和绑定检查的分配的警告，在特定环境中不支持malloc，但这些都可以接受），并且在win32-elf中，你应该有一个工作的elf编译器。 你还应该拥有用于32位和64位PE编译器的Win32和Win64，以及Win64-ELF中的64位ELF编译器。 注意: 64位编译器不会在非64位操作系统上编译。&lt;br /&gt;
如果编译TCC时出现错误，只需将“@echo off”更改为“@echo on”，然后再次运行脚本，看看哪里出了问题。&lt;br /&gt;
&lt;br /&gt;
===Linux===&lt;br /&gt;
你的发行版可能已经提供了TCC的包。 如果没有，请从https://download.savannah.gnu.org/releases/tinycc/下载源代码，然后从那里继续。 你知道如何从头开始构建程序，对吗？&lt;br /&gt;
&lt;br /&gt;
==一个小内核示例==&lt;br /&gt;
&lt;br /&gt;
这个小例子以ELF格式构建了一个小内核，可以通过Grub引导。&lt;br /&gt;
&lt;br /&gt;
===start32.asm===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;asm&amp;quot;&amp;gt;&lt;br /&gt;
;  Tutorial: A small kernel with Fasm &amp;amp; TCC&lt;br /&gt;
;  By Tommy.&lt;br /&gt;
 &lt;br /&gt;
        format elf&lt;br /&gt;
        use32&lt;br /&gt;
&lt;br /&gt;
;&lt;br /&gt;
; Equates&lt;br /&gt;
;&lt;br /&gt;
MULTIBOOT_PAGE_ALIGN	    equ (1 shl 0)&lt;br /&gt;
MULTIBOOT_MEMORY_INFO	    equ (1 shl 1)&lt;br /&gt;
MULTIBOOT_AOUT_KLUDGE	    equ (1 shl 16)&lt;br /&gt;
MULTIBOOT_HEADER_MAGIC	    equ 0x1BADB002&lt;br /&gt;
MULTIBOOT_HEADER_FLAGS	    equ MULTIBOOT_PAGE_ALIGN or MULTIBOOT_MEMORY_INFO&lt;br /&gt;
MULTIBOOT_CHECKSUM          equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)&lt;br /&gt;
&lt;br /&gt;
        section '.text' executable&lt;br /&gt;
;&lt;br /&gt;
; Multiboot header&lt;br /&gt;
;&lt;br /&gt;
dd MULTIBOOT_HEADER_MAGIC&lt;br /&gt;
dd MULTIBOOT_HEADER_FLAGS&lt;br /&gt;
dd MULTIBOOT_CHECKSUM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&lt;br /&gt;
; Kernel entry point.&lt;br /&gt;
;&lt;br /&gt;
        public  _start&lt;br /&gt;
        extrn   kmain&lt;br /&gt;
_start:&lt;br /&gt;
        ; Call the main kernel function.&lt;br /&gt;
        call    kmain&lt;br /&gt;
 &lt;br /&gt;
@@:&lt;br /&gt;
        jmp     @b&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===kernel.c===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/*  Tutorial: A small kernel with Fasm &amp;amp; TCC&lt;br /&gt;
 *  By Tommy.&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Main kernel function.&lt;br /&gt;
 */&lt;br /&gt;
void&lt;br /&gt;
kmain (void)&lt;br /&gt;
{&lt;br /&gt;
    *((unsigned char *) 0xB8000) = 'H';&lt;br /&gt;
    *((unsigned char *) 0xB8001) = 0x1F;&lt;br /&gt;
    *((unsigned char *) 0xB8002) = 'E';&lt;br /&gt;
    *((unsigned char *) 0xB8003) = 0x1F;&lt;br /&gt;
    *((unsigned char *) 0xB8004) = 'L';&lt;br /&gt;
    *((unsigned char *) 0xB8005) = 0x1F;&lt;br /&gt;
    *((unsigned char *) 0xB8006) = 'L';&lt;br /&gt;
    *((unsigned char *) 0xB8007) = 0x1F;&lt;br /&gt;
    *((unsigned char *) 0xB8008) = 'O';&lt;br /&gt;
    *((unsigned char *) 0xB8009) = 0x1F;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==编译和链接==&lt;br /&gt;
使用以下选项汇编start32.asm：&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
fasm start32.asm&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
编译kernel.c用:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
tcc -c kernel.c&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
然后将整件东西链接起来：&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
tcc -nostdlib -Wl,-Ttext,0x100000 start32.o kernel.o -o kernel-i386.elf&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
如果你更喜欢二进制形式，例如，如果你正在使用自己的不支持ELF的引导加载程序，请使用以下链接方式：&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
tcc -nostdlib -Wl,-Ttext,0x100000 -Wl,--oformat,binary -static start32.o kernel.o -o kernel-i386.bin&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
就这样!&lt;br /&gt;
&lt;br /&gt;
==内联汇编==&lt;br /&gt;
TCC支持内联GAS语法汇编，如GCC：&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
__asm__ __volatile__(&amp;quot;hlt&amp;quot;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
你可以用这个特性为你处理好很多事情，比如在Bochs调试:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define breakpoint() __asm__ __volatile__(&amp;quot;xchg %bx, %bx&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
void bochs_print (char *string) {&lt;br /&gt;
	char *c = string;&lt;br /&gt;
	while (*c != '\0') {&lt;br /&gt;
		outb(0xE9, *c); // may be outportb&lt;br /&gt;
		c++;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
然后将其添加到你的bochsrc中。文本编辑器中的bxrc文件：&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
port_e9_hack: enabled=1&lt;br /&gt;
magic_break: enabled=1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
并从Boch的安装位置执行bochsdbg.exe，而不是bochs.exe。&lt;br /&gt;
&lt;br /&gt;
== 关于GDT和结构体的警告 ==&lt;br /&gt;
根据TCC的创始人法布里斯·贝拉德（Fabrice Bellard）的说法，并且被（痛苦地）证明是正确的： &amp;quot;在TCC中，只有结构字段或变量声明支持‘packed’属性，整个结构体不支持。 因此，你的解决方案是将其添加到打包结构体的每个字段中。&amp;quot;&lt;br /&gt;
因此，如果使用结构体存储GDT条目或GDTR，请注意，如果没有正确指定结构的打包，那么在加载GDT时会遇到问题。&lt;br /&gt;
在创建结构体时，请使用类似以下内容：&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// 我们使用属性 'packed' 告诉TCC不要更改结构中的任何对齐方式。&lt;br /&gt;
struct some_struct {&lt;br /&gt;
   unsigned char a __attribute__((packed));&lt;br /&gt;
   unsigned char b __attribute__((packed));&lt;br /&gt;
} __attribute__((packed));&lt;br /&gt;
// 最后一个属性可以保留，它不会干扰编译或输出，它可能对&lt;br /&gt;
// 保持与GCC的兼容性有用，只要上述属性不干扰GCC即可。&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
而不是这样:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
//我们使用属性“packed”告诉GCC不要更改结构中的任何对齐方式。&lt;br /&gt;
struct some_struct {&lt;br /&gt;
   unsigned char a;&lt;br /&gt;
   unsigned char b;&lt;br /&gt;
} __attribute__((packed));&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==内联函数警告==&lt;br /&gt;
TCC不支持函数内联，因为 'inline' 关键字会被忽略，所以如果一个函数需要内联，你必须使用defins预定义代替。&lt;br /&gt;
&lt;br /&gt;
==stdint.h==&lt;br /&gt;
TCC不包括stdint.h、 但stddef.h中提供了所需的所有typedefs类型定义&lt;br /&gt;
要使用stdint.h，将以下代码作为stdint.h放入你的内核包含路径中。 这将使你的代码与gcc和tcc兼容。&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/* stdint.h */&lt;br /&gt;
&lt;br /&gt;
#ifdef __TINYC__&lt;br /&gt;
/* tcc */&lt;br /&gt;
#include &amp;lt;stddef.h&amp;gt;&lt;br /&gt;
#else&lt;br /&gt;
/* assume gcc */&lt;br /&gt;
#include_next &amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Zhang3</name></author>
	</entry>
</feed>