📄 exe2bin.c
字号:
/*
* File: exe2bin.c
* Version: 3.14
* Last Updated: July 25, 2004
*
* Copyright (C) 2002, ChipLink Microsystem Labs. All Rights Reserved.
*
* Description: This file is a part of my Micro-Kernel RTOS (QNX like),
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char int8;
typedef short int16;
typedef long int32;
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned long uint32;
#pragma pack(push,1)
typedef struct
{
uint16 Signature; /* offset 00-01 */
uint16 ExtraBytes; /* offset 02-03 */
uint16 Pages; /* offset 04-05 */
uint16 RelocItems; /* offset 06-07 */
uint16 HeaderSize; /* offset 08-09 */
uint16 MinAlloc; /* offset 0A-0B */
uint16 MaxAlloc; /* offset 0C-0D */
uint16 InitSS; /* offset 0E-0F */
uint16 InitSP; /* offset 10-11 */
uint16 CheckSum; /* offset 12-13 */
uint16 InitIP; /* offset 14-15 */
uint16 InitCS; /* offset 16-17 */
uint16 RelocTable; /* offset 18-19 */
uint16 Overlay; /* offset 1A-1B */
/*
Hack here(July-24-2004):
以下两个字段 Borland 用来标志 Linker 的版本号
*/
uint16 Reserved1; /* offset 1C-1D */
uint8 Reserved2[2]; /* offset 1E-1F */
} exe_header;
#pragma pack(pop)
#define EXE_MAGIC1 0x5a4d /* "MZ" */
#define EXE_MAGIC2 0x4d5a /* "ZM" */
#define EXE_NE_MAGIC 0x454e /* "NE" --- Windows 3.x(win16) App */
#define EXE_LE_MAGIC 0x454c /* "LE" --- Windows 3.x(win16) VxD */
#define EXE_PE_MAGIC 0x4550 /* "PE" --- Windows NT(win32) App */
#define EXE_LX_MAGIC 0x584c /* "LX" --- OS/2 App */
#define GOT_EXENAME 0x01
#define GOT_BINNAME 0x02
#define GOT_SEGMENT 0x04
#define GOT_MASK (GOT_EXENAME | GOT_BINNAME | GOT_SEGMENT )
void copyright(void)
{
printf("EXE2BIN Version 3.14, Copyright (c) 1993-2004 ChipLink Microsystem Labs.\n\n\r");
}
void usage(void)
{
printf("Usage: \n");
printf(" EXE2BIN [/EXE=]exe_file[.exe] [[/BIN=]bin_file[.bin]] [/SEG=nnnn]\n");
printf("where:\n");
printf(" nnnn --- Segment in Hexadecimal system, default=0000H\n\n\r");
}
int main(int argc, char **argv)
{
exe_header hdr;
FILE * src, * dst;
uint32 flen, plen, addr;
uint8 * img = NULL;
uint16 i, opt, rseg, roff, * tab = NULL, segment=0x0000;
char ename[256]={0}, bname[256]={0}, tmp[256]={0}, * p;
copyright();
/* 命令行分析 */
for ( opt=0, --argc, ++argv; (argc > 0) && (opt!=GOT_MASK); --argc, ++argv )
{
/* 先判是否是 seg 参数 */
if( strnicmp( *argv, "/EXE", 4 )==0 )
{
strcpy( ename , (*argv)+5 );
opt |= GOT_EXENAME;
}
else if( strnicmp( *argv, "/BIN", 4 )==0 )
{
strcpy( bname , (*argv)+5 );
opt |= GOT_BINNAME;
}
else if( strnicmp( *argv, "/SEG", 4 )==0 )
{
segment = (uint16)strtoul( (*argv)+5, NULL, 16);
opt |= GOT_SEGMENT;
}
else {
if( (opt & GOT_EXENAME)==0 )
{
strcpy( ename , *argv );
opt |= GOT_EXENAME;
}
else if( (opt & GOT_BINNAME)==0 )
{
strcpy( bname , *argv );
opt |= GOT_BINNAME;
}
}
}
/* 用户在命令行中未给出 EXE 文件名 */
if( !(opt & GOT_EXENAME) )
{
usage();
return -1;
}
//首先确定 EXE 文件名中有无 '.' 分割符, 需要先找到最后一个 '\' 目录分隔符
p = strrchr( ename, '\\' );
if( !p )
{
p = strrchr( ename, '.' );
}
else {
p = strrchr( p, '.' );
}
if( !(opt & GOT_BINNAME) )
{
//EXE 文件名中有 '.' 分割符
if( p )
{
strncpy( bname, ename, p-ename );
}
else
{
//如果 EXE 文件名中未给出 '.' 分割符
strcpy( bname, ename );
}
strcat( bname, ".bin" );
}
if( !p )
{
strcpy( tmp, ename );
strcat( tmp, ".exe" );
printf(" EXE File: '%s' or '%s'(I Guess:-)\n", ename, tmp );
}
else
{
printf(" EXE File: '%s'\n", ename );
}
printf(" BIN File: '%s'\n", bname );
printf(" Segment: %04X (Hex)\n\n\r", segment );
src = fopen( ename, "rb");
if( !src )
{
//若打开失败,则在用户未给出 .EXE 扩展名的情况下尝试补齐扩展名再打开
if( !p )
{
src = fopen( tmp, "rb" );
}
//若补齐扩展名仍不能打开, 报错退出
if( !src )
{
printf("Cannot open file: neither %s or %s!\n", ename, tmp );
return -2;
}
}
fread( &hdr, 1, sizeof(hdr), src );
if( hdr.Signature != EXE_MAGIC1 && hdr.Signature != EXE_MAGIC2 )
{
printf("This is not a EXE file!\n");
fclose(src);
return -3;
}
/*
需再增加对 NE/LE/PE 格式的检查,确保只处理 DOS 的 Old EXE 格式
*/
if( hdr.RelocTable >= 0x40 )
{
fseek( src, 0x3cL, SEEK_SET );
fread( &roff, 1, sizeof(uint16), src );
fseek( src, (long)roff, SEEK_SET );
fread( &opt, 1, sizeof(uint16), src );
if( opt==EXE_NE_MAGIC || opt==EXE_LE_MAGIC || opt==EXE_PE_MAGIC || opt==EXE_LX_MAGIC )
{
printf("Windows NE/LE/PE or OS/2 LX format EXE file is not supported!\n");
fclose(src);
return -4;
}
}
dst = fopen( bname, "wb");
if( !dst )
{
printf("Cannot create file: %s!\n", bname );
fclose(src);
return -5;
}
flen = hdr.ExtraBytes?( (hdr.Pages-1) *512L + hdr.ExtraBytes): (hdr.Pages *512L);
plen = flen - (hdr.HeaderSize*16L);
printf("DOS File size: \t%Xh ( %u )\n", flen, flen );
printf("Load Image Size: \t%Xh ( %u )\n", plen, plen);
printf("Relocation Table entry count: \t%04Xh ( %5u )\n", hdr.RelocItems, hdr.RelocItems );
printf("Relocation Table address: \t%04Xh ( %5u )\n", hdr.RelocTable, hdr.RelocTable );
printf("Size of header record (in paragraphs): \t%04Xh ( %5u )\n", hdr.HeaderSize, hdr.HeaderSize );
printf("Minimum Memory Requirement (in paragraphs): \t%04Xh ( %5u )\n", hdr.MinAlloc, hdr.MinAlloc );
printf("Maximum Memory Requirement (in paragraphs): \t%04Xh ( %5u )\n", hdr.MaxAlloc, hdr.MaxAlloc );
printf("File load checksum: \t%04Xh ( %5u )\n", hdr.CheckSum, hdr.CheckSum );
printf("Overlay Number: \t%04Xh ( %5u )\n\n", hdr.Overlay, hdr.Overlay );
if( hdr.Reserved1==0x0001 && hdr.Reserved2[0]==0xFB )
{
printf("Linker: Borland TLINK Version %u.%02u\n\n", (hdr.Reserved2[1]>>4)&0x0f, hdr.Reserved2[1] & 0x0f );
}
printf("Initial Stack Segment (SS:SP): \t%04X:%04X\n", hdr.InitSS, hdr.InitSP );
printf("Program Entry Point (CS:IP): \t%04X:%04X\n\n\r", hdr.InitCS, hdr.InitIP );
if( hdr.RelocItems )
{
/* 重单位项 */
fseek( src, (long)hdr.RelocTable, SEEK_SET );
tab = (uint16 *)malloc( hdr.RelocItems * 4 );
#if 0
printf("malloc %d size for %d RelocateTable Items!\n",
hdr.RelocItems * 4, hdr.RelocItems );
#endif
if( !tab )
{
printf("Cannot allocate memory for Relocation Items!\n");
fclose(src);
fclose(dst);
return -6;
}
memset( tab, 0, hdr.RelocItems * 4 );
fread( tab, 1, hdr.RelocItems * 4, src );
printf("Relocation Locations (%u Entries)\n\n", hdr.RelocItems );
for( i=0; i<hdr.RelocItems; i++ )
{
roff = tab[ 2*i ];
rseg = tab[ 2*i+1 ];
printf(" %04X:%04X", rseg, roff );
if( i%5==4 ) printf("\n");
}
printf("\n\n\r");
}
/* Ok, Let's doing the real works */
fseek( src, (hdr.HeaderSize*16L), SEEK_SET );
img = (uint8 *)malloc( plen );
if( !img )
{
printf("Cannot allocate memory for image!\n");
if( tab ) free(tab);
fclose(src);
fclose(dst);
return -7;
}
memset( img, 0, plen );
fread( img, 1, plen, src );
for(i=0;i<hdr.RelocItems;i++)
{
roff = tab[ 2*i ];
rseg = tab[ 2*i+1 ];
addr = ( (uint32)(rseg << 4 ) + roff );
*((uint16 *)( (uint8 *)img + addr) ) += segment;
#if 0
printf("address( %08X = %04X:%04X ) = %04X(File offset: %lu )\n", addr, rseg, roff,
*((uint16 *)( img + addr)), addr + (hdr.HeaderSize*16L) );
#endif
}
fwrite( img, 1, plen, dst );
if( tab ) free(tab);
if( img ) free(img);
fclose(src);
fclose(dst);
printf("File was successfully converted!\n\r");
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -