4 个回答
这是想写操作系统吧,吐槽一下,用TC2这个技术可是够老的。不过,你要是就想用TC,也不是不行。
你需要的是TASM这个东西,它里面带着TCC/TASM/TLINK工具能把C语言编译成汇编,还能把汇编和C生成的OBJ最后LINK起来。
NASM和TC是两个不同时代的产物,不太可能混合使用。
下面是我当年用TC写的FAT12的bootloader的编译脚本,其中MyEXE2BIN是自己用VC写的把EXE转BIN的工具。FAT12BS.ASM就是FAT12的引导扇区的开头。
编译脚本(bat)
set CCPATH=D:\TURBOC2\
set CC=%CCPATH%TCC.EXE
set ASM=%CCPATH%TASM.EXE
set LINK=%CCPATH%TLINK.EXE
set GETBIN=tool\MyEXE2BIN.exe
set INCLUDE=h
set BSHD=bootsec\FAT12BS.asm
set BSCODE=bootsec\FLOOPYBS.C
set OBJDIR=obj
%ASM% /ml %BSHD%,%OBJDIR%\bs1.obj
%CC% -S -mt -O -Z -I%INCLUDE% -E%ASM% -o%OBJDIR%\bs2.asm %BSCODE%
%CC% -c -mt -O -Z -I%INCLUDE% -E%ASM% -o%OBJDIR%\bs2.obj %BSCODE%
%LINK% %OBJDIR%\bs1.obj %OBJDIR%\bs2.obj, %OBJDIR%\bs.exe
%GETBIN% %OBJDIR%\bs.exe %OBJDIR%\bs.bin -b
FAT12BS.ASM的内容
assume cs:_TEXT, ds:_TEXT, ss:_TEXT
DGROUP group _TEXT
_TEXT segment
org 7c00h
start:
JMP Prepare
_BS_OEMName db 'XXXXX0.6'
_BS_BytesPerSec dw 200h
_BS_SecPerCls db 1
_BS_ReserveSec dw 0
_BS_FATCnt db 2
_BS_RootDir dw 0e0h
_BS_SecCnt16 dw 0b40h
_BS_MediaType db 0f0h
_BS_FATSize16 dw 9
_BS_SecPerTrack dw 12h
_BS_HeadCnt dw 2
_BS_HiddenSec dd 0
_BS_SecCnt32 dd 0
_BS_DrvNum db 0
_BS_Reserve1 db 0
_BS_BootFlag db 29h
_BS_VolumeID db 'XXXX'
_BS_VolumeLabel db 'XXXXX06BOOT'
_BS_FSType db 'FAT12 '
Prepare:
MOV AX,CS
MOV DS,AX
MOV SS,AX
MOV ES,AX
jmp _main
extrn _main:near
_TEXT ends
public _BS_OEMName
public _BS_BytesPerSec
public _BS_SecPerCls
public _BS_ReserveSec
public _BS_FATCnt
public _BS_RootDir
public _BS_SecCnt16
public _BS_MediaType
public _BS_FATSize16
public _BS_SecPerTrack
public _BS_HeadCnt
public _BS_HiddenSec
public _BS_SecCnt32
public _BS_DrvNum
public _BS_Reserve1
public _BS_BootFlag
public _BS_VolumeID
public _BS_VolumeLabel
public start
end start
FLOOPYBS.C
#include <CType.h>
extern int8_t BS_OEMName;
extern int16_t BS_BytesPerSec;
extern int8_t BS_SecPerCls;
extern int16_t BS_ReserveSec;
extern int8_t BS_FATCnt;
extern int16_t BS_RootDir;
extern int16_t BS_SecCnt16;
extern int8_t BS_MediaType;
extern int16_t BS_FATSize16;
extern int16_t BS_SecPerTrack;
extern int16_t BS_HeadCnt;
extern int32_t BS_HiddenSec;
extern int32_t BS_SecCnt32;
extern int8_t BS_DrvNum;
extern int8_t BS_Reserve1;
extern int8_t BS_BootFlag;
extern int8_t BS_VolumeID;
extern int8_t BS_FSType;
extern int8_t BS_VolumeLabel;
#define BS_RootDir 0xE0
#define BS_SectorSize 512
#define BS_RootDirSecCnt 14
#define BS_FatSecSize 9
#define BS_RootFatSecOffset 19
#define BS_SecInTrack 0x24
#define BS_SecInTrackInHd 0x12
#define BS_FileClsOffset 26
#define BS_StartIP 0x7C00
#if 0
#define BS_ITOA_DATA_OFFSET 0x400
#endif
#define BS_SWAP_DATA_OFFSET 0x0400
#define BS_FAT_DATA_OFFSET 0x1000
#define BS_LOADER_CS_OFFSET 0x1000
#define BS_LOADER_IP_OFFSET 0x0000
#define BS_FILENAME_LEN 11
#define BS_LOADERFILENAME "LDR BIN"
#if 0
int8_t * itoa(int16_t v);
void display(int8_t *s, int16_t len);
#endif
void loadFile(int16_t clsNum);
int16_t filenameCheck(int8_t * src, int8_t * dst);
uint16_t loadSec(int16_t addr, int16_t offset);
main()
int16_t i, j;
int16_t r, p;
p = BS_StartIP + BS_FAT_DATA_OFFSET;
for (i = 1;i <= BS_FatSecSize; i++, p += BS_SectorSize)
loadSec(p, i);
r = BS_RootFatSecOffset;
for (j = 0; j < BS_RootDirSecCnt; j++, r++)
p = BS_StartIP + BS_SWAP_DATA_OFFSET;
loadSec(p, r);
for (i = 0; i < 16; i++, p += 32)
if (filenameCheck(BS_LOADERFILENAME, p) == 0)
loadFile(*(int16_t *)(p + BS_FileClsOffset));
asm mov ax, BS_LOADER_CS_OFFSET;
asm push ax;
asm mov ax, BS_LOADER_IP_OFFSET;
asm push ax;
asm retf;
LblLoop:
asm jmp LblLoop;
void loadFile(int16_t clsNum)
int16_t t, s;
int16_t sec;
uint16_t addr = BS_LOADER_IP_OFFSET;
uint16_t es_r = BS_LOADER_CS_OFFSET;
asm mov es, es_r;
while(clsNum != 0xfff)
sec = clsNum - 2 + BS_RootDirSecCnt + BS_RootFatSecOffset;
loadSec(addr, sec);
addr += BS_SectorSize;
if (addr == 0)
es_r += 0x1000;
asm mov es, es_r;
t = (clsNum >> 1) * 3;
s = BS_StartIP + BS_FAT_DATA_OFFSET + t;
if (clsNum & 1)
clsNum = ((*(uint8_t *)(s + 1)) >> 4)
| ((*(uint8_t *)(s + 2)) << 4);
clsNum = (*(int16_t *)(s)) & 0xFFF;
return;
uint16_t loadSec(int16_t addr, int16_t offset)
uint8_t sec, hd, trk;
trk = offset / BS_SecInTrack;
sec = offset % BS_SecInTrack;
hd = sec / BS_SecInTrackInHd;
sec = (sec % BS_SecInTrackInHd) + 1;
asm mov ax, 0x0201;
asm mov bx, addr;
asm mov cl, sec;
asm mov ch, trk;
asm mov dh, hd;
asm mov dl, 0;
asm int 0x13;
asm cmp ah, 0;
asm jnz ldsFail;
return 0;
ldsFail:
return -1;
int16_t filenameCheck(int8_t * src, int8_t * dst)
int16_t i;
for (i = 0; i < BS_FILENAME_LEN; i++)
if (*src++ != *dst++)
return -1;
return 0;
#if 0
int8_t * itoa(int16_t v)
int8_t * buf;
int16_t f = 0;
int16_t i = 0;
buf = (int8_t *)BS_StartIP + BS_ITOA_DATA_OFFSET + 10;
if (v < 0)
f = 1, v = -v;
while(v > 0)
buf[i--] = v % 10 + '0';
v = v / 10;
if (f == 1)
buf[i--] = '-';
return &buf[i+1];
void display(int8_t *s, int16_t len)
int8_t c, *p = NULL;
if (len != 0) p = s + len;
while (((c = s[0]) != '\0') && p != s)
asm mov al, c;
asm mov ah, 0xE;
asm mov bl, 0x7;
asm int 0x10;
#endif
CType.h
#ifndef _CTYPE_H_
#define _CTYPE_H_
#define MAX_INT32 0x7FFFFFFF
#define MAX_UINT32 0xFFFFFFFF
#define MAX_INT16 0x7FFF
#define MAX_UINT16 0xFFFF
typedef unsigned char uint8_t;
typedef char int8_t;
typedef unsigned int uint16_t;
typedef int int16_t;
typedef unsigned long uint32_t;
typedef long int32_t;
typedef unsigned int size_t;
enum _Bool {
FALSE = 0,
TRUE = 1
#define NULL 0
#endif _CTYPE_H_ /* end of _CTYPE_H_ */
MyEXE2BIN.EXE的源码(用VC编译,生成可以执行文件然后作为工具链的一部分使用:
#include <stdio.h>
#include <string.h>
typedef int int32_t;
typedef short int int16_t;
typedef char int8_t;
typedef struct {
int16_t Signature;
int16_t ExtraBytes;
int16_t Pages;
int16_t RelocItems;
int16_t HeaderSize;
int16_t MinAlloc;
int16_t MaxAlloc;
int16_t InitSS;
int16_t InitSP;
int16_t CheckSum;
int16_t InitIP;
int16_t InitCS;
int16_t RelocTable;
int16_t Overlay;
} pe_header;
typedef struct {
int16_t offset;
int16_t segment;
} reloc_item;
int main(int argc, char * argv[])
FILE * fp, * fout;
pe_header phd;
int32_t pos;
int32_t len;
int32_t cnt;
int32_t i;
int16_t segOff = 0, addr;
size_t ret;
reloc_item item;
int8_t buf[512] = {0};
if (argc < 3)
printf("invalid parameter\n");
printf("usage: <exefilename> <binfilename> [flag]\n");
printf("flag: -pXXXX proceed with segment offset XXXX\n");
printf(" -b create bootsector\n");
return -1;
fp = fopen(argv[1], "rb");
if (fp == NULL)
printf("input file %s open failed\n", argv[1]);
return -2;
fread(&phd, 1, sizeof(pe_header), fp);
pos = phd.HeaderSize * 0x10;
if (argc == 4 && strcmp(argv[3], "-b") == 0)
printf("bootsector proccessing\n");
if (phd.InitCS != 0x0000 || phd.InitIP != 0x7C00)
printf("bad bootsector entry!\n");
return -9;
fout = fopen(argv[2], "wb");
if (fout == NULL)
printf("Output file %s open failed\n", argv[2]);
return -4;
fseek(fp, pos + phd.InitIP, SEEK_SET);
ret = fread(buf, 1, 512, fp);
if (ret > 510)
printf("Warning size is larger than 510 bytes\n");
buf[510] = '\x55';
buf[511] = '\xAA';
fwrite(buf, 1, 512, fout);
printf("write success!\n");
fclose(fout);
return 0;
if (phd.InitCS != 0 || phd.InitIP != 0)
printf("CS:IP = [%04X:%04X]\n", phd.InitCS, phd.InitIP);
printf("Not equal to 0000:0000, failed\n");
return -3;
if (argc == 4 && memcmp(argv[3], "-p", 2) != 0)
printf("unknown flag parameter %s\n", argv[3]);
return -5;
if (argc == 4)
sscanf(argv[3] + 2, "%x", &segOff);
fout = fopen(argv[2], "wb");
if (fout == NULL)
printf("Output file %s open failed\n", argv[2]);
return -4;
fseek(fp, pos, SEEK_SET);
len = phd.ExtraBytes + (phd.Pages - 1) * 0x200;
printf("First step copy data...\n");
while (pos < len)
ret = fread(buf, 1, 512, fp);
if (ret == 0)
break;
printf("+");
fwrite(buf, 1, ret, fout);
pos += ret;
printf("\n");
fclose(fout);
fout = fopen(argv[2], "rb+");
if (fout == NULL)
printf("Output file %s open failed\n", argv[2]);
return -4;
pos = phd.RelocTable;
cnt = phd.RelocItems;
fseek(fp, pos, SEEK_SET);
printf("Second step proceed reloc table...\n");
for (i = 0; i < cnt; i++)
fread(&item, 1, sizeof(item), fp);
pos = item.offset + item.segment * 0x10;
fseek(fout, pos, SEEK_SET);
fread(&addr, 1, 2, fout);
addr += segOff;
fseek(fout, pos, SEEK_SET);
fwrite(&addr, 1, 2, fout);
printf(".");
printf("\nSuccess\n");