Code:
#include <stdio.h>
#include <string.h>
#define CODE_SIZE 25
typedef struct {
unsigned short usMZ; // This is always = 'ZM'
unsigned short usLastPageSize; // Last page size in bytes
unsigned short usNumPages; // Number of 512 byte pages
unsigned short usNumRelocations; // ?
unsigned short usHeaderSize; // Size of header in paragraphs (16 bytes)
unsigned short usMinMemory; // Minimum memory in addition to code
unsigned short usMaxMemory; // Maximum memroy in addition to code
unsigned short usInitialStackSeg; // Initial stack segment
unsigned short usInitialStackOffset;// Initial stack offset
unsigned short usChecksum; // 0
unsigned long ulEntryPoint; // CS:IP
unsigned short usRelocTableOffset; // ?
unsigned short usOverlayNumber; // 0
} dosheader;
int main(void)
{
char szBuffer[BUFSIZ], *newline;
int i;
FILE *fp;
dosheader header;
printf("Enter text to be printed on execution: ");
fgets(szBuffer, BUFSIZ, stdin);
newline = szBuffer + strlen(szBuffer);
if (*newline == '\n')
*newline = 0;
header.usMZ = 'ZM';
header.usLastPageSize = CODE_SIZE + strlen(szBuffer) + 1;
header.usNumPages = 1;
header.usNumRelocations = 0;
header.usHeaderSize = 2;
header.usMinMemory = 0;
header.usMaxMemory = 0xFFFF;
header.usInitialStackSeg = 0;
header.usInitialStackOffset = 0;
header.usChecksum = 0;
header.ulEntryPoint = 0;
header.usRelocTableOffset = 0;
header.usOverlayNumber = 0;
fp = fopen("compiled.exe", "wb");
if (!fp)
return -1;
fwrite(&header.usMZ, 2, 1, fp);
fwrite(&header.usLastPageSize, 2, 1, fp);
fwrite(&header.usNumPages, 2, 1, fp);
fwrite(&header.usNumRelocations, 2, 1, fp);
fwrite(&header.usHeaderSize, 2, 1, fp);
fwrite(&header.usMinMemory, 2, 1, fp);
fwrite(&header.usMaxMemory, 2, 1, fp);
fwrite(&header.usInitialStackSeg, 2, 1, fp);
fwrite(&header.usInitialStackOffset, 2, 1, fp);
fwrite(&header.usChecksum, 2, 1, fp);
fwrite(&header.ulEntryPoint, 4, 1, fp);
fwrite(&header.usRelocTableOffset, 2, 1, fp);
fwrite(&header.usOverlayNumber, 2, 1, fp);
for (i=0;i<4;i++) // Pad out header
putc(0, fp);
// Right, there's no stack, so we're doing this the hard way...
putc(0x8C, fp); // mov ax, cs
putc(0xC8, fp);
putc(0x8E, fp); // mov ds, ax
putc(0xD8, fp);
putc(0xBE, fp); // mov si, offset message
putc(CODE_SIZE, fp);
putc(0, fp);
putc(0xB4, fp); // mov ah, 0Eh : Teletype
putc(0x0E, fp);
putc(0x33, fp); // xor bx, bx
putc(0xDB, fp);
putc(0xAC, fp); // lodsb
putc(0x3C, fp); // cmp al, 0
putc(0, fp);
putc(0x74, fp); // jz (pos + 4)
putc(4, fp);
putc(0xCD, fp); // int 10h (Video BIOS)
putc(0x10, fp);
putc(0xEB, fp); // jmp (pos - 9)
putc(0xF7, fp);
putc(0xB8, fp); // mov ax, 4C00h : Exit with error code 0
putc(0, fp);
putc(0x4C, fp);
putc(0xCD, fp); // int 21h (DOS)
putc(0x21, fp);
fwrite(szBuffer, strlen(szBuffer) + 1, 1, fp);
fclose(fp);
printf("Compilation successful.\n");
return 0;
}
There's nothing seriously wrong with it as such, except that if you type in a largeish message it'll bomb (Due to the number of pages in the program being fixed at 1). Could anyone suggest further improvements to this?