怎么将C语言代码转换成nasm的16位汇编语言?

如题,TC2.0的过不了nasm编译
关注者
6
被浏览
3,744

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");