/* GenPC Elite Macro Assembler, just a TASM killer and the real tool for crazy coders. (C)oderight -JEDI- from SECTOR -ONE- 1994/95 Last revision in date : 12/28/95 To be compiled with GCC, BORLAND or WATCOM C++ */ #define REGTO 1 #define VERSION "2.6" #define MONTH "Feb" #define YEAR "96" #define BETA_TEST #if (REGTO == 1) /* Jedi/Sector One */ #define REGISTERED "enO rotceS/ideJ" #elif (REGTO == 2) /* Michel Furic */ #define REGISTERED "ciruF lehciM" #elif (REGTO == 3) /* Quicky */ #define REGISTERED "ykciuQ" #elif (REGTO == 4) /* Deneb */ #define REGISTERED "beneD" #elif (REGTO == 5) /* Florent Chichery */ #define REGISTERED "yrehcihC tnerolF" #elif (REGTO == 6) /* Mon ami bresilien */ #define REGISTERED "neiliserb ima noM" #elif (REGTO == 7) /* Keops/Equinox */ #define REGISTERED "xoniuqE/spoeK" #endif #include #if defined (unix) || defined (__unix__) #include #endif #include #include #include #ifndef EXIT_SUCCESS #define EXIT_SUCCESS 0 #endif #ifndef EXIT_FAILURE #define EXIT_FAILURE 1 #endif #if defined (_POSIX_SOURCE) || defined (__STRICT_ANSI__) && !defined (_BSD_SOURCE) && !defined (__USE_BSD) && !defined (NEED_STRCASE) && !defined (strcasecmp) && !defined (strncasecmp) || !defined (__GNUC__) || !defined (unix) || !defined (__unix__) #define NEED_STRCASECMP #define NEED_UNLINK_PROTOTYPE #endif #ifdef NEED_UNLINK_PROTOTYPE #ifndef unlink int unlink(const char *_path); #endif #endif #ifdef REGISTERED #define MAX_LABEL 32760 #define IOBUFFER 16380 #define MAX_RELOC 32760 #else #define MAX_LABEL 16380 #define IOBUFFER 32760 #define MAX_RELOC 16380 #endif struct lotus { char etat; long offset; char reg1; char reg2; char factor; char r; } pry1, pry2, pry3; void eop(void), checkquiet(void); void soundgarden(void), label(void), bwl(void), fsh(void); int checkduplicatelabel(void); char *skipspace(register char *), *nextarg(register char *), *nextcoma(register char *); void take2(void), put(int), wri(void *, size_t); void nop(void), end(void), dcb(void), dcw(void), dcl(void), dsb(void), dsw(void), dsl(void); void trap(void), rts(void), rtsf(void), iret(void), iretd(void), lea(void); void lock(void), repne(void), repe(void), stop(void), cmc(void), clc(void), stc(void), cld(void), std(void), cli(void), sti(void); void aaa(void), aad(void), aam(void), aas(void), adc(void), org(void), assume(void), segment(void), even(void), page(void), dpage(void); void add(void), and(void), arpl(void), bound(void), bsf(void), bsr(void), swap(void); void bt(void), btc(void), btr(void), bts(void), align(void), alignq(void); void call(void), callz(void), callf(void), callzf(void), xor(void); void cbw(void), cwd(void), cdq(void), cwde(void), clts(void), cmp(void), cmps(void), test(void); void daa(void), das(void), dec(void), div_(void), enter(void), wait_(void), idiv(void); void imul(void), in(void), inc(void), incbin(void); void cs(void), ds(void), es(void), fs(void), gs(void), ss(void); void rept(void), endr(void), set(void), ins(void), into(void), invd(void), wbinvd(void); void ja(void), jae(void), jb(void), jbe(void), jcxz(void), jecxz(void), je(void); void jg(void), jge(void), jl(void), jle(void), jno(void), jnp(void), jns(void); void jne(void), jo(void), jp(void), js(void), jmp(void), jmpf(void), jmpz(void), jmpzf(void); void seta(void), setae(void), setb(void), setbe(void), sete(void); void setg(void), setge(void), setl(void), setle(void), setno(void), setnp(void), setns(void); void setne(void), seto(void), setp(void), sets(void); void lahf(void), lar(void), lds(void), les(void), lfs(void), lgs(void), lss(void); void lods(void), leave(void), loop(void), loope(void), loopne(void); void lgdt(void), lidt(void), lldt(void), lmsw(void), lsl(void), ltr(void), str(void), verr(void); void sgdt(void), sidt(void), sldt(void), smsw(void), verw(void); void movs(void), outs(void), mov(void), movsx(void), movzx(void); void mul(void), neg(void), not(void), or(void), out(void); void pop(void), popa(void), popf(void), push(void), pusha(void), pushf(void); void rcl(void), rcr(void), rol(void), ror(void), sahf(void), shl(void), shr(void), sar(void); void shld(void), shrd(void), xchg(void), xlat(void); void sub(void), sbb(void), scas(void), stos(void), limite(void), mini(void), overlay(void); void stack(void), header(void), include(void), macro(void), endm(void), once(void); void perform(unsigned char, int, char, char, char, unsigned char), limit(void); void real(void), unreal(void), segsize(void); void salc(void), icebp(void), umov(void), loadall(void), cmov(void), rdpmc(void), ud(void), ud2(void); void title(void), bss(void), text(void), use32(void), use16(void), opt(void); void heading(void), ohnomoreshits(void), int03(void); long val(char *); struct lotus getadrs(register char *); int findreg(char *); void column(void); static const struct {const char *nom; void (*col)(void);} neak[] = { {"nop", nop}, {"leave", leave}, {"unlink", leave}, {"dc.b", dcb}, {"dc.w",dcw}, {"dc.l",dcl}, {"dc", dcw}, {"ds.b", dsb}, {"ds.w",dsw} ,{"ds.l",dsl}, {"move", mov}, {"mov", mov}, {"movs", movs}, {"moves", movs}, {"outs", outs}, {"movsx", movsx}, {"movesx", movsx}, {"movzx", movzx}, {"movezx", movzx}, {"out", out}, {"pop", pop}, {"scas", scas}, {"stos", stos}, {"lgdt", lgdt}, {"lidt", lidt}, {"lldt", lldt}, {"lmsw", lmsw}, {"trapv", into}, {"into", into}, {"wbinvd", wbinvd}, {"flush", wbinvd}, {"invd", invd}, {"trap", trap}, {"int", trap}, {"rted", iretd}, {"rtid", iretd}, {"iretd", iretd}, {"rte", iret}, {"rti", iret}, {"iret", iret}, {"lea", lea}, {"braf", jmpzf}, {"jmpf", jmpf}, {"bra", jmpz}, {"jmp", jmp}, {"rtsf", rtsf}, {"retf", rtsf}, {"rts", rts}, {"ret", rts}, {"lock", lock}, {"rep", repe}, {"repne", repne}, {"repnz", repne}, {"repeq", repe}, {"repz", repe}, {"repe", repe}, {"hlt", stop}, {"stop", stop}, {"xor", xor}, {"eor", xor}, {"cmc", cmc}, {"ngc", cmc}, {"clc", clc}, {"stc", stc}, {"cld", cld}, {"d+", cld}, {"std", std}, {"d-", std}, {"cli", cli}, {"intoff", cli}, {"sti", sti}, {"inton", sti}, {"aaa", aaa}, {"aad", aad}, {"aam", aam}, {"aas", aas}, {"addx", adc}, {"adc", adc}, {"org", org}, {"assume", assume}, {"segment", segment}, {"para", segment}, {"page", page}, {"dpage", dpage}, {"even", even}, {"align.q", alignq}, {"align", align}, {"add", add}, {"and", and}, {"arpl", arpl}, {"bound", bound}, {"bs+", bsf}, {"bsf", bsf}, {"bs-", bsr}, {"swap", swap}, {"bswap", swap}, {"btstc", btc}, {"btstn", btc}, {"btc", btc}, {"btstr", btr}, {"btr", btr}, {"tas", bts}, {"btsts", bts}, {"btst", bt}, {"bts", bts}, {"bt", bt}, {"jsrf", callzf}, {"callf", callf}, {"jsr", callz}, {"call", call}, {"bsrf", callzf}, {"bsr", callz}, {"mulu", mul}, {"mul", mul}, {"verr", verr}, {"verw", verw}, {"exta.q", cdq}, {"ext.q", cdq}, {"cdq", cdq}, {"exta", cbw}, {"ext", cbw}, {"cbw", cbw}, {"cwde", cwde}, {"cwd", cwd}, {"clts", clts}, {"cmps", cmps}, {"cmp", cmp}, {"daa", daa}, {"das", das}, {"dec", dec}, {"test", test}, {"lahf", lahf}, {"lar", lar}, {"lsl", lsl}, {"ltr", ltr}, {"str", str}, {"lds", lds}, {"les", les}, {"lfs", lfs}, {"lgs", lgs}, {"lss", lss}, {"divs", idiv}, {"idiv", idiv}, {"divu", div_}, {"div", div_}, {"link", enter}, {"enter", enter}, {"wait", wait_}, {"fwait", wait_}, {"muls", imul}, {"imul", imul}, {"incbin", incbin}, {"inc", inc}, {"ins", ins}, {"cs", cs}, {"ds", ds}, {"es", es}, {"fs", fs}, {"gs", gs}, {"ss", ss}, {"rept", rept}, {"endr", endr}, {"set", set}, {"in", in}, {"jnbe", ja}, {"bhi", ja}, {"jae", jae}, {"jnb", jae}, {"bcc", jae}, {"jnae", jb}, {"bcs", jb}, {"jbe", jbe}, {"jna", jbe}, {"bls", jbe}, {"jge", jge}, {"jnl", jge}, {"bge", jge}, {"jnc", jae}, {"jno", jno}, {"bvc", jno}, {"jnge", jl}, {"blt", jl}, {"jle", jle}, {"jng", jle}, {"ble", jle}, {"jcxz", jcxz}, {"bcxz", jcxz}, {"beq", je}, {"jnle", jg}, {"bgt", jg}, {"jecxz", jecxz}, {"becxz", jecxz}, {"jcez", jecxz}, {"bcez", jecxz}, {"jns", jns}, {"bpl", jns}, {"jne", jne}, {"jnz", jne}, {"bne", jne}, {"jnp", jnp}, {"jpo", jnp}, {"bpo", jnp}, {"bvs", jo}, {"jpe", jp}, {"bpe", jp}, {"bmi", js}, {"ja", ja}, {"jb", jb}, {"jc", jb}, {"je", je}, {"jz", je}, {"jg", jg}, {"jl", jl}, {"jo", jo}, {"jp", jp}, {"js", js}, {"setbe", seta}, {"shi", seta}, {"setae", setae}, {"setnb", setae}, {"scc", setae}, {"setae", setb}, {"scs", setb}, {"setbe", setbe}, {"setna", setbe}, {"sls", setbe}, {"setge", setge}, {"setnl", setge}, {"sge", setge}, {"setnc", setae}, {"setno", setno}, {"svc", setno}, {"setnge", setl}, {"slt", setl}, {"setle", setle}, {"setng", setle}, {"sle", setle}, {"seq", sete}, {"setnle", setg}, {"sgt", setg}, {"setns", setns}, {"spl", setns}, {"setne", setne}, {"setnz", setne}, {"sne", setne}, {"setnp", setnp}, {"setpo", setnp}, {"spo", setnp}, {"svs", seto}, {"setpe", setp}, {"setpe", setp}, {"smi", sets}, {"seta", seta}, {"setb", setb}, {"setc", setb}, {"sete", sete}, {"setz", sete}, {"setg", setg}, {"setl", setl}, {"seto", seto}, {"setp", setp}, {"sets", sets}, {"loope", loope}, {"loopz", loope}, {"dbeq", loope}, {"loopne", loopne}, {"loopnz", loopne}, {"dbne", loopne}, {"lods", lods}, {"loop", loop}, {"dbf", loop}, {"dbra", loop}, {"neg", neg}, {"not", not}, {"or", or}, {"popa", popa}, {"popf", popf}, {"push", push}, {"pusha", pusha}, {"pushf", pushf}, {"roxl", rcl}, {"rcl", rcl}, {"roxr", rcr}, {"rcr", rcr}, {"rol", rol}, {"ror", ror}, {"sahf", sahf}, {"saf", sahf}, {"asl", shl}, {"sal", shl}, {"asr", sar}, {"sar", sar}, {"shl", shl}, {"shr", shr}, {"sub", sub}, {"subx", sbb}, {"sbb", sbb}, {"shld", shld}, {"shrd", shrd}, {"sgdt", sgdt}, {"sidt", sidt}, {"sldt", sldt}, {"smsw", smsw}, {"exg", xchg}, {"xchg", xchg}, {"xlat", xlat}, {"xlatb", xlat}, {"salc", salc}, {"icebp", icebp}, {"int01", icebp}, {"trap01", icebp}, {"int03", int03}, {"trap03", int03}, {"umov", umov}, {"umove", umov}, {"loadall", loadall}, {"cmov", cmov}, {"cmove", cmov}, {"rdpmc", rdpmc}, {"ud", ud}, {"ud2", ud2}, {"stack", stack}, {"header", heading}, {"exe", heading}, {"max", limite}, {"limit", limite}, {"min", mini}, {"mini", mini}, {"overlay", overlay}, {"include", include}, {"macro", macro}, {"once", once}, {"real", real}, {"realmode", real}, {"flat", unreal}, {"unreal", unreal}, {"unlimit", unreal}, {"segsize", segsize}, {"endm", endm}, {"bss", bss}, {"section bss", bss}, {"text", text}, {"section text", text}, {"data", text}, {"section data", text}, {"title", title}, {"use32", use32}, {"use16", use16}, {"opt", opt}, {NULL, end} }; static const char *registres[] = { "a", "c", "d", "b", "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh", "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", "ae", "ce", "de", "be", "spe", "bpe", "sie", "die", "es", "cs", "ss", "ds", "fs", "gs", "cr0", "cr2", "cr3", "dr0", "dr1", "dr2", "dr3", "dr6", "dr7", "tr3", "tr4", "tr5", "tr6", "tr7", NULL }; struct stackent { struct stackent *link; char *file; long pl; long pos; }; struct stackent *upstack = NULL; #ifdef REGISTERED struct stackent *uponce = NULL; struct macroent { struct macroent *link; char *file; char *macro; long pl; long pos; }; struct macroent *upmacro = NULL; #endif int pass_brief = 2; int pass_correct = 1; #define PASS_BRIEF pass_brief #define PASS_CORRECT pass_correct #define PASS_LAST 1 #define PASS_FIRST PASS_BRIEF #define PASS_MAX 3 char *line, *prout, **name, sizer, *pnt, forward = 0; char *buffer, *bufpnt, *bufend, *accordeon; FILE *joe, *popol; int lastlabel = 1, passe, tpasse = 1; long pl = 0, tpl = 0, rpc = 0, pc = 0, reupeuteumeu = -1, *where, assumer = 0; long maxsegsize = -1, maxsegcounter = -1; long orgvalue = 0; long retimes, repl; long stk = 0, taille; long battletech = 0; long *reloc; int relocpnt = 0; char exe = 0, clara = 0; unsigned short lim = 0xffff, lowlim = 0, ovrlay = 0; char *sourcefile; char preprocess = 0, isverbose = 0, isquiet = 0, optimize = 0, nowarning = 0; char unresolvedlabel = 0, autoalign = 0, isobject = 0, peephole = 0; long pcwoalign = 0, lastpcwoalign = 0; int extra_passe = 0, bssflag = 0; int seg32 = 0; long polter1, polter2; enum cputype { CALL, C186, C286, C386, C486, C586, C686, CBEST } cpu = CBEST; static char *cpunames[] = { "8086 or 8088", "80186", "80286", "80386", "80486", "Pentium", "P6", "maximum" }; #define CPUCHECK(NEEDED) if (cpu < NEEDED) cpusucks(NEEDED) #ifdef NEED_STRCASECMP int strcasecmp(const char *s1, const char *s2) { register const unsigned char *p1 = (const unsigned char *) s1; register const unsigned char *p2 = (const unsigned char *) s2; unsigned char c1, c2; if (p1 == p2) return 0; do { c1 = tolower(*p1++); c2 = tolower(*p2++); if (c1 == '\0') break; } while (c1 == c2); return c1 - c2; } int strncasecmp(const char *s1, const char *s2, size_t n) { register const unsigned char *p1 = (const unsigned char *) s1; register const unsigned char *p2 = (const unsigned char *) s2; unsigned char c1, c2; if (p1 == p2 || n == 0) return 0; do { c1 = tolower(*p1++); c2 = tolower(*p2++); if (c1 == '\0' || c1 != c2) return c1 - c2; } while (--n > 0); return c1 - c2; } #endif int strtokcasecmp(const char *s, const char *token) { register const unsigned char *p1 = (const unsigned char *) s; register const unsigned char *p2 = (const unsigned char *) token; unsigned char c1, c2; if (p1 == p2) return 0; for (;;) { if ((c2 = *p2) == 0) return 0; p2++; if ((c1 = tolower(*p1)) == 0 || c1 != c2) return -1; p1++; } } int strfastcasecmp(const char *s1, const char *s2) { register const unsigned char *p1 = (const unsigned char *) s1; register const unsigned char *p2 = (const unsigned char *) s2; unsigned char c1, c2; if (p1 == p2) return 0; do { c1 = tolower(*p1++); c2 = *p2++; if (c1 == '\0') break; } while (c1 == c2); return c1 - c2; } void warning(const char *shakeyourbody) { if (nowarning == 0) { checkquiet(); fprintf(stderr, "WARNING : %s at line %ld\n", shakeyourbody, pl); } } void error(const char *shakeyourbody) { fprintf(stderr, "ERROR : %s at line %ld\n", shakeyourbody, pl); exit(EXIT_FAILURE); } void checkquiet(void) { static char fanou[13] = ""; if (strncmp(fanou, sourcefile, 12)) { fprintf(stderr, "\n*** In file [%s] : ***\n", sourcefile); strncpy(fanou, sourcefile, 12); } } void cpusucks(enum cputype required) { fprintf(stderr, "ERROR : You wanted a %s compatibility, but at line %ld, you\n\tused a feature that needs at least a %s processor.\n", cpunames[cpu], pl, cpunames[required]); exit(EXIT_FAILURE); } void optinfo(void) { if (isverbose && tpasse != 2) { if (lastpcwoalign > pcwoalign) { printf("%ld bytes saved compared to the previous pass.\n", lastpcwoalign - pcwoalign); } else if (lastpcwoalign < pcwoalign) { printf("%ld extra bytes were added to the previous pass due to cross-references.\n", pcwoalign - lastpcwoalign); } } } void eop(void) { if (joe != NULL) fclose(joe); if (popol != NULL) { fclose(popol); } if (sourcefile != NULL) { fprintf(stderr, "\n( Last processed file was : [%s] )\n", sourcefile); } } void decrypt(char *encrypted) { char *zarawhite; int daphnee = strlen(encrypted); zarawhite = encrypted + daphnee; do { putchar(*--zarawhite); daphnee--; } while (daphnee != 0); } int main(int argc, char **argv) { char *targetname, *popy; #ifdef REGISTERED printf("\n-*-*=)> GenPC v" VERSION "r Elite Assembler by -JEDI- From -SECTOR ONE- " MONTH " " YEAR " <(=*-*-\n\n"); #else printf("\n-*-*=)> GenPC v" VERSION " Elite Assembler by -JEDI- From -SECTOR ONE- " MONTH " '" YEAR " <(=*-*-\n\n"); #endif passe = PASS_FIRST; atexit(eop); if (argc < 2) goto man; do { popy = argv[1]; if (!strcasecmp(popy, "-e") || !strcasecmp(popy, "--preprocess")) { preprocess = 1; argv++; argc--; } else if (!strcasecmp(popy, "-nw") || !strcasecmp(popy, "--nowarning")) { nowarning = 1; argv++; argc--; } else if (!strcasecmp(popy, "-v") || !strcasecmp(popy, "--verbose")) { isverbose = 1; argv++; argc--; } else if (!strcasecmp(popy, "-q") || !strcasecmp(popy, "--quiet")) { isquiet = 1; argv++; argc--; } else if (!strcasecmp(popy, "-p") || !strcasecmp(popy, "--peepholes")) { peephole = 1; argv++; argc--; } else if (!strcasecmp(popy, "-o") || !strcasecmp(popy, "--optimize")) { optimize = 1; pass_brief = 3; pass_correct = 2; argv++; argc--; } else if (!strcasecmp(popy, "-a") || !strcasecmp(popy, "--autoalign")) { autoalign = 1; argv++; argc--; } else if (!strcasecmp(popy, "-c") || !strcasecmp(popy, "--object")) { isobject = 1; argv++; argc--; } else if (!strcasecmp(popy, "-86") || !strcasecmp(popy, "-88") || !strcasecmp(popy, "--cpu=88") || !strcasecmp(popy, "--cpu=86")) { cpu = CALL; argv++; argc--; } else if (!strcasecmp(popy, "-186") || !strcasecmp(popy, "--cpu=186")) { cpu = C186; argv++; argc--; } else if (!strcasecmp(popy, "-286") || !strcasecmp(popy, "--cpu=286")) { cpu = C286; argv++; argc--; } else if (!strcasecmp(popy, "-386") || !strcasecmp(popy, "--cpu=386")) { cpu = C386; argv++; argc--; } else if (!strcasecmp(popy, "-486") || !strcasecmp(popy, "--cpu=486")) { cpu = C486; argv++; argc--; } else if (!strcasecmp(popy, "-586") || !strcasecmp(popy, "--cpu=586") || !strcasecmp(popy, "-pentium") || !strcasecmp(popy, "--cpu=pentium")) { cpu = C586; argv++; argc--; } else if (!strcasecmp(popy, "-686") || !strcasecmp(popy, "--cpu=686") || !strcasecmp(popy, "-p6") || !strcasecmp(popy, "--cpu=P6")) { cpu = C686; argv++; argc--; } else { break; } } while (argc > 1); if (argc == 3) targetname = argv[2]; else if (argc != 2) { man: printf("Usage : GEMA [options] [target.obj|target.com|target.exe]\n"); printf("Options :\n"); printf("-E, --preprocess : display preprocessed sources\n"); printf("-v, --verbose : verbose output\n"); printf("-q, --quiet : reduced output\n"); printf("-o, --optimize : automatic level 2 optimizations\n"); printf("-p, --peepholes : automatic peepholes optimizations\n"); printf("-nw, --nowarning : disable all warnings\n"); printf("-a, --autoalign : enable automatic alignment for each label\n"); printf("-c, --object : produce a .OBJ linkable file\n"); printf("-86, -88, --cpu=86, --cpu=88 : assemble only 8086 opcodes\n"); printf("-186, --cpu=186 : assemble only 80186 opcodes\n"); printf("-286, --cpu=286 : assemble only 80286 opcodes\n"); printf("-386, --cpu=386 : assemble only 80386 opcodes\n"); printf("-486, --cpu=486 : assemble only 80486 opcodes\n"); printf("-586, -pentium, --cpu=586, --cpu=pentium : 80586 opcodes\n"); printf("-686, -p6, --cpu=686, --cpu=p6 : 80686 opcodes\n"); #ifdef REGISTERED printf("\nRegistered to : "); decrypt(REGISTERED); #else printf("\nShareware release, please register !"); #endif #if defined(__DATE__) && defined(__TIME__) printf("\nLast revision in date : " __DATE__ ", " __TIME__ "\n"); #endif exit(EXIT_SUCCESS); } else { if ((targetname = (char *) malloc(strlen(argv[1]) + 5)) == NULL) { fprintf(stderr, "ERROR : No memory enough for filenames\n"); exit(EXIT_FAILURE); } strcpy(targetname, argv[1]); if ((popy = strrchr(targetname, '.')) == NULL) { if (isobject == 0) { strcat(targetname, ".exe"); } else { strcpy(targetname, ".obj"); } } else { if (isobject == 0) { strcpy(++popy, "exe"); } else { strcpy(++popy, "obj"); } } } if ((name = (char **) malloc(MAX_LABEL)) == NULL) { fprintf(stderr, "ERROR : No memory enough for label names\n"); exit(EXIT_FAILURE); } if ((where = (long *) malloc(MAX_LABEL * sizeof(long))) == NULL) { fprintf(stderr, "ERROR : No memory enough for label references\n"); exit(EXIT_FAILURE); } if ((reloc = (long *) malloc(MAX_RELOC * sizeof(long))) == NULL) { fprintf(stderr, "ERROR : No memory enough for relocation table\n"); exit(EXIT_FAILURE); } if ((line = (char *) malloc(256)) == NULL) { fprintf(stderr, "ERROR : No memory enough for inline analyze\n"); exit(EXIT_FAILURE); } if ((prout = (char *) malloc(256)) == NULL) { fprintf(stderr, "ERROR : No memory enough for inline buffering\n"); exit(EXIT_FAILURE); } if ((bufpnt = buffer = (char *) malloc(IOBUFFER)) == NULL) { fprintf(stderr, "ERROR : No memory enough for I/O buffering\n"); exit(EXIT_FAILURE); } bufend = buffer + IOBUFFER; passe = PASS_FIRST; sgeg: sourcefile = argv[1]; if ((joe = fopen(sourcefile, "rt")) == NULL) { if (*sourcefile == '-') { printf("Unrecognized option [%s], assembly aborted.\n", sourcefile); } else { printf("Sorry, but I can't locate that file\n"); } exit(EXIT_FAILURE); } if (passe == PASS_LAST) { if ((popol = fopen(targetname, "wb")) == NULL) { printf("Sorry, but I can't create the target file\n"); fclose(joe); joe = NULL; exit(EXIT_FAILURE); } } *name = "START"; *where = 0; if (passe == PASS_BRIEF) printf("-> Assembling : [%s] to [%s]...\n", argv[1], targetname); legal: while (fgets(line, 255, joe) != NULL) { pnt = line; if (preprocess) { printf("%s", line); } /* else if (isverbose) { printf("%ld/%ld \r", tpl, pl); } */ pl++; tpl++; rpc = pc; if (*pnt == '\n' || *pnt == '/' || *pnt == '*' || *pnt == '%' || *pnt == ';') continue; if (*pnt == ' ' || *pnt == '\t') { enjoy: soundgarden(); continue; } label(); goto enjoy; } if (upstack != NULL) { struct stackent *savent = upstack; fclose(joe); if (upstack->link != NULL) free(sourcefile); sourcefile = upstack->file; if ((joe = fopen(sourcefile, "rt")) == NULL) { fprintf(stderr, "ERROR : Can't reopen [%s] at line %ld\n", sourcefile, pl); exit(EXIT_FAILURE); } fseek(joe, upstack->pos, SEEK_SET); pl = upstack->pl; upstack = upstack->link; free(savent); /* if (!isquiet && isverbose != 0) { printf("\tBack to file [%s]\n", sourcefile); } */ goto legal; } if (isobject != 0 && exe != 0) { ohnomoreshits(); } fsh(); if (popol != NULL) { fclose(popol); } if (joe != NULL) { fclose(joe); } popol = joe = NULL; if (reupeuteumeu >= 0) { fprintf(stderr, "ERROR : No ENDR follows the last REPT\n"); exit(EXIT_FAILURE); } if (--passe) { newturn: tpasse++; optinfo(); lastpcwoalign = pcwoalign; taille = pc; if (passe != PASS_LAST) { relocpnt = 0; } rpc = pc = tpl = pl = pcwoalign = 0; bssflag = 0; assumer = 0; seg32 = 0; if (!isquiet || isverbose != 0) { if (forward) printf("-> Second pass for forward references...\n"); else { if (extra_passe) { printf("-> Extra pass for crossed peepholes...\n"); extra_passe++; } else { printf("-> New pass for extended warnings and optimizations...\n"); extra_passe = 1; } } } forward = 0; goto sgeg; } else if (lastpcwoalign != pcwoalign) { if (extra_passe < PASS_MAX) { pass_brief = 3; pass_correct = 2; passe = PASS_LAST; goto newturn; } printf("-> Optimization impossible due to crossed relative lengths - Retrying...\n"); pass_brief = 3; pass_correct = 2; passe = PASS_CORRECT; optimize = 0; goto newturn; } else if (forward) { fprintf(stderr, "\nERROR : Crossed references\n"); exit(EXIT_FAILURE); } if (!exe && isobject == 0) { if ((popy = strstr(targetname, ".exe")) != NULL) { char *ren; if ((ren = (char *) malloc(strlen(targetname) + 1)) == NULL) { fprintf(stderr, "ERROR : No memory enough for renaming [.exe] to [.com]\n"); exit(EXIT_FAILURE); } strcpy(ren, targetname); strcpy(popy, ".com"); unlink(targetname); if (rename(ren, targetname) != 0) { fprintf(stderr, "ERROR : Can't rename [%s] to [%s]\n", ren, targetname); exit(EXIT_FAILURE); } printf("Moving [%s] to [%s]...\n", ren, targetname); } } else if (!stk && nowarning == 0) { fprintf(stderr, "WARNING : No stack\n"); } optinfo(); if (exe != 0 && relocpnt == 0) { printf("\n%ld lines assembled in %ld bytes of PC-relative code.\n", tpl, pc); } else if (exe) { printf("\n%ld lines assembled in %ld bytes of relocatable code.\n", tpl, pc); } else { printf("\n%ld lines assembled in %ld bytes of tiny model code.\n", tpl, ((pc - 0x100) > 0) ? pc - 0x100 : pc); } if (isverbose) { printf("The main file [%s] was %ld lines long.\n", sourcefile, pl); printf("%d symbols were defined and %ld bytes were used for alignment.\n", lastlabel, pc - pcwoalign); printf("There are %d entries in the relocation table.\n", relocpnt); printf("%d passes ( %d extra ) were necessary to produce ", tpasse, extra_passe); if (optimize) { printf("automatically optimized"); } else { printf("raw"); } printf(" code.\n"); } printf("\n-<(* Thank You For Having Done The Right Choice...Keep on Coding or Die ! *)>-\n"); sourcefile = NULL; exit(EXIT_SUCCESS); return 0; } void ware(void) { if (sizer && passe == PASS_BRIEF) { warning("Size has no effect"); } } void put(int c) { if (passe == PASS_LAST && !bssflag) { if (bufpnt == bufend) { fwrite(buffer, IOBUFFER, 1, popol); bufpnt = buffer; } *bufpnt++ = c; } pc++; pcwoalign++; if (maxsegsize < 0) { return; } maxsegcounter--; if (maxsegcounter == 0) { fprintf(stderr, "ERROR : Too many data in segment (max size was %ld bytes) at line %ld\n", maxsegsize, pl); exit(EXIT_FAILURE); } } void wri(void *c, size_t lune) { if (passe == PASS_LAST && !bssflag) { if (bufpnt + lune >= bufend) { fwrite(buffer, bufpnt - buffer, 1, popol); bufpnt = buffer; } memcpy(bufpnt, c, lune); bufpnt += lune; } pc += lune; pcwoalign += lune; if (maxsegsize < 0) { return; } maxsegcounter -= lune; if (maxsegcounter == 0) { fprintf(stderr, "ERROR : Too many data in segment (max size was %ld bytes) at line %ld\n", maxsegsize, pl); exit(EXIT_FAILURE); } } void fsh(void) { if (passe == PASS_LAST) { if (bufpnt != buffer) { fwrite(buffer, bufpnt - buffer, 1, popol); bufpnt = buffer; } } } void hey(struct lotus fleur) { if (seg32 == 0) { if (sizer == 'L') { put(0x66); } if ((fleur.reg1 >= 20 && fleur.etat > 8) || fleur.etat == 8) { put(0x67); } } else { if (sizer != 'L') { put(0x66); } if (!((fleur.reg1 >= 20 && fleur.etat > 8) || fleur.etat == 8)) { put(0x67); } } } #ifdef REGISTERED int checkmacro(char *zepnt) { register struct macroent *pntmac = upmacro; while (pntmac != NULL) { if (!strtokcasecmp(zepnt, pntmac->macro)) { return 0; } pntmac = pntmac->link; } return -1; } #endif void soundgarden(void) { int t = 0; char *pnt2; const char *tekno; pnt = skipspace(pnt); if (*pnt == '\n' || *pnt == '\r' || *pnt == 0) return; for(;;) { if ((tekno = neak[t].nom) == NULL) { #ifdef REGISTERED if (checkmacro(pnt) != 0) { #endif fprintf(stderr, "ERROR : Unknown instruction at line %ld :\n\t%s", pl, pnt); exit(EXIT_FAILURE); #ifdef REGISTERED } break; #endif } else if (!strtokcasecmp(pnt, tekno)) { pnt2 = pnt; pnt += strlen(tekno); if (isalnum(*pnt)) { pnt = pnt2; t++; continue; } if (*pnt == '.') { if ((sizer = toupper(*(++pnt))) == 'L') { CPUCHECK(C286); } } else { sizer = 0; } (*neak[t].col)(); break; } t++; } } void label(void) { char *proutos, zok; unsigned int size = 0; int thinkabout; proutos = prout; for (;;) { zok = *pnt++; if (zok == '\n' || zok == ':' || zok == '\t' || zok == ' ') break; if (isalnum(zok) || zok == '_' || zok == '.' || zok == '!') { *proutos++ = zok; size++; } else { error("Invalid label name"); } } if (!size) { error("Label declaration error"); } prout[size] = 0; if (autoalign != 0) { while (pc & 1) { put(0x90); pcwoalign--; rpc++; } } if ((thinkabout = checkduplicatelabel()) == -1) { if ((name[lastlabel] = (char *) malloc(size + 1)) == NULL) { fprintf(stderr, "ERROR : Oh no ! More memory for labels !\n"); exit(EXIT_FAILURE); } where[lastlabel] = rpc; strcpy(name[lastlabel++], prout); if (lastlabel == MAX_LABEL) { fprintf(stderr, "ERROR : Too many labels !\n"); exit(EXIT_FAILURE); } } else if (*prout != '!') { where[thinkabout] = rpc; } } int checkduplicatelabel() { int t, u = -1; for (t = 0; t < lastlabel; t++) { if (!strcmp(prout, name[t])) break; } if (t < lastlabel) { if (passe == PASS_BRIEF && *prout != '.' && *prout != '!') { fprintf(stderr, "ERROR : Duplicate label/constant variable [%s] at line %ld\n", prout, pl); exit(EXIT_FAILURE); } u = t; } return u; } char *skipspace(register char *remember) { while(*remember == ' ' || *remember == '\t' || *remember == 13) remember++; return remember; } long eval(register char *num) { register char comedie; char *sondage, *anum, *onum; long total; int t, idea = 0; anum = num; pouf: total = 0; onum = num; comedie = *num++; if (comedie == ';') { error("Expression awaited before the comment"); } else if (isdigit(comedie)) { total = (comedie - '0'); for(;;) { comedie = *num++; if (isdigit(comedie)) { total *= 10; total += (comedie - '0'); } else break; } } else if (comedie == '\0' || comedie == 13 || comedie == '\n') { error("Incomplete subexpression"); } else if (comedie == '$') { for(;;) { comedie = *num++; if (comedie >= 'A' && comedie <= 'F') { total <<= 4; total |= (comedie - 'A' + 10); } else if (comedie >= 'a' && comedie <= 'f') { total <<= 4; total |= (comedie - 'a' + 10); } else if (isdigit(comedie)) { total <<= 4; total |= (comedie - '0'); } else break; } } else if (comedie == '%') { for(;;) { comedie = *num++; if (comedie == '0' || comedie == '1') { total <<= 1; total |= (comedie - '0'); } else break; } } else if (comedie == '') { for(;;) { comedie = *num++; if (comedie >= '0' && comedie <='7') { total <<= 3; total |= (comedie - '0'); } else break; } } else if (comedie == '*') { total = rpc; num++; } else if (comedie == '-') { total = -val(num); num = accordeon; } else if (comedie == ':') { if (maxsegsize > 0) { total = val(num) % maxsegsize; } else { total = val(num); } num = accordeon; } else if (comedie == '@') { total = val(num); if ((total & 15) && passe == PASS_LAST && !idea && nowarning == 0) { checkquiet(); fprintf(stderr, "WARNING : @ not applied to a segment address at line %ld\n\t..@%s", pl, num); } num = accordeon; total >>= 4; } else if (comedie == '\'') { total = (unsigned char) *num++; while (*num != '\'' && *num != '\t' && *num != '\n' && *num != 13) { total <<= 8; total += (unsigned char) *num++; } if (*num != '\'') { error("Missing quote"); } num += 2; } else if (comedie == '~') { total = ~val(num); num = accordeon; } else if (isalpha(comedie) || comedie == '_' || comedie == '.' || comedie == '!') { sondage = prout; *sondage++ = comedie; for(;;) { comedie = *num++; if (!isalnum(comedie) && comedie != '_' && comedie != '.') break; *sondage++ = comedie; } *sondage = 0; for (t = 0; t < lastlabel; t++) { if (!strcmp(prout,name[t])) { total = where[t] - assumer; unresolvedlabel = 0; break; } } if (t == lastlabel) { if (passe == PASS_BRIEF) { forward = 1; /* switch (sizer) { case 'B' : case 'S' : total = 0x10; break; case 'W' : total = 0x1000; break; case 'L' : total = 0x1000000; break; default : */ total = (pc + 0xf) & ~0xf; /* do { total++; } while (total & 0xf); */ /* } */ unresolvedlabel = 1; } else { fprintf(stderr, "ERROR : Undefined label [%s] at line %ld\n", prout, pl); exit(EXIT_FAILURE); } } } else if (comedie == '[') { if ((onum = strchr(num, ']')) == NULL) { error("Final \']\' awaited in expression"); } total = val(num); num = skipspace(++onum); onum = num; } else { error("Undefined expression"); } accordeon = num; if (num != onum) num--; num = skipspace(num); comedie = *num; if (strchr("=%+-*/|&^<>", comedie) != NULL) { onum = num; *(onum) = '\n'; num = skipspace(++num); switch (idea) { case 0 : if (comedie == '=') { total = val(anum) == val(num); *onum = comedie; return total; } break; case 1 : if (comedie == '%') { total = val(anum) % val(num); *onum = comedie; return total; } break; case 2 : if (comedie == '+') { total = val(anum) + val(num); *onum = comedie; return total; } break; case 3 : if (comedie == '-') { total = val(anum) - val(num); *onum = comedie; return total; } break; case 4 : if (comedie == '*') { total = val(anum) * val(num); *onum = comedie; return total; } break; case 5 : if (comedie == '/') { total = val(anum) / val(num); *onum = comedie; return total; } break; case 6 : if (comedie == '|') { total = val(anum) | val(num); *onum = comedie; return total; } break; case 7 : if (comedie == '&') { total = val(anum) & val(num); *onum = comedie; return total; } break; case 8 : if (comedie == '^') { total = val(anum) ^ val(num); *onum = comedie; return total; } break; case 9 : if (comedie == '<') { total = val(anum) << val(num); *onum = comedie; return total; } break; case 10 : if (comedie == '>') { total = val(anum) >> val(num); *onum = comedie; return total; } } *onum = comedie; } else { if (idea != 10) { idea++; num = anum; } else return total; } goto pouf; } long val(char *num) { long fire; long oldassumer = assumer; if (*num == '\\') { assumer = 0; fire = eval(skipspace(++num)); fire >>= 4; clara = 1; assumer = oldassumer; return fire; } clara = 0; return eval(num); } char *nextarg(register char *doudou) { while (*doudou != ' ' && *doudou != '\t' && *doudou != '\n' && *doudou != 13) doudou++; if (*doudou == '\n' || *doudou == '\r') return NULL; while (*doudou == '\t' || *doudou == ' ') doudou++; if (*doudou == '\n' || *doudou == '\r') return NULL; if (*doudou == ';') { do { pnt++; } while (*pnt != '\n' && *pnt != '\r' && *pnt != 0); return NULL; } return doudou; } char *nextcoma(register char *doudou) { while (*doudou != ',' && *doudou != '\n' && *doudou != 13) doudou++; if (*doudou == '\n' || *doudou == 13) return NULL; doudou = skipspace(++doudou); if (*doudou == '\n' || *doudou == 13) return NULL; return doudou; } struct lotus getadrs(register char *df) { struct lotus back; int t = 0; char *df2; if (*df == '#') { df=skipspace(++df); back.offset = val(df); back.r = clara; for(;;) { if (*df == '\n' || *df == 13 || *df == ',') break; if (*df++ == '.') { switch (*df) { case 'B' : case 'b' : case 'S' : case 's' : back.etat = (clara)? 2 : 1; return back; case 'W' : case 'w' : back.etat = 2; return back; case 'L' : case 'l' : if (clara) { error("Can't relocate a long value"); } back.etat = 3; return back; } } } if (back.offset >= -128 && back.offset <= 255) back.etat = (clara)? 2 : 1; else if (back.offset >= -32768 && back.offset <= 65535) back.etat = 2; else { back.etat = 3; if (clara) { error("Can't relocate a long value"); } } return back; } if ((t = findreg(df)) != -1) { back.reg1 = t; back.etat = 4; return back; } back.etat = 5; if (*df == '(') { dust: df2 = df; df = skipspace(++df); if ((t = findreg(df)) != -1) { back.reg1 = t; back.etat += 4; while (*df != ',' && *df != ')' && *df != '\n' && *df != 13) { if (!isalnum(*df)) { error("Unknown addressing mode"); } df++; } if (*df == ')') return back; else if (*df++ != ',') { error("Missing ')'"); } df = skipspace(df); if ((t = findreg(df)) == -1) { error("Index register missing"); } back.reg2 = t; back.etat += 8; while (*df != '*' && *df != ')' && *df != '\n' && *df !=13) { if (!isalnum(*df)) { error("Suspicious garbage with index register"); } df++; } if (*df == ')') return back; else if (*df++ != '*') { error("Missing ')'"); } back.etat += 16; switch (val(df = skipspace(df))) { case 1 : back.factor = 0; break; case 2 : back.factor = 1; break; case 4 : back.factor = 2; break; case 8 : back.factor = 3; break; default : error("Suspicious factor"); } return back; } df = df2; } back.offset = val(df); if (optimize != 0 && back.offset == 0 && unresolvedlabel == 0) { df = skipspace(++df); for (;;) { if (*df == '\n' || *df == '\r' || *df == 0) break; if (*df == '(') { if (isverbose != 0 && passe == PASS_LAST) { warning("Superflous offset removed"); } back.etat = 5; goto dust; } df++; } } back.r = clara; back.etat = 5; for(;;) { if (*df == '\n' || *df == '\r' || *df == '(' || *df == 0) break; if (*df++ == '.') { if (*df == 'L' || *df == 'l') { if (clara) { error("Can't relocate a long offset"); } back.etat = 8; df = skipspace(++df); break; } if (*df == 'W' || *df == 'w') { back.etat = 7; df = skipspace(++df); break; } if (*df == 'B' || *df == 'b' || *df == 'S' || *df =='s') { back.etat = (clara)? 7 : 6; df = skipspace(++df); break; } } } if (back.etat == 5) { if (back.offset >= -128 && back.offset <= 127) back.etat = 6; else if (back.offset >= -32768 && back.offset <= 32767) back.etat = 7; else back.etat = 8; } if (*df == '(') goto dust; return back; } void nop(void) { ware(); put(0x90); } int findreg(char *tralala) { int t = 0; char dynamic; char *hoke; register const char **regptr = registres; hoke = prout; for(;;) { dynamic = *tralala++; if (dynamic == '.' || dynamic == '_') return -1; else if (isalnum(dynamic)) *hoke++ = dynamic; else break; } if (hoke == prout) return -1; *hoke = 0; for (;;) { if (*regptr == NULL) { return -1; } if (!strfastcasecmp(prout, *regptr)) { return t; } regptr++; t++; } } void take2(void) { if ((pnt = nextarg(pnt)) == NULL) { error("Two arguments are missing"); } pry1 = getadrs(pnt); if (!pry1.etat) { error("Invalid adressing mode"); } while(*pnt != ',' && *pnt != '\n' && *pnt != 13) pnt++; if (*pnt++ != ',') { error("Second argument is missing"); } pnt = skipspace(pnt); if (pry1.etat >= 13) { while(*pnt != ',' && *pnt != '\n' && *pnt != 13) pnt++; if (*pnt++ != ',') { error("Second argument is missing"); } pnt = skipspace(pnt); } pry2 = getadrs(pnt); if (!pry2.etat) { error("Invalid adressing mode"); } } void end(void) { printf("GenPC was forced to stop processing\n"); exit(EXIT_SUCCESS); } void dcb(void) { char ginette; if ((pnt = nextarg(pnt)) == NULL) return; do { if (*pnt == '\"') { for(;;) { ginette = *(++pnt); if (ginette == '\"' || ginette == 13 || ginette == '\n') break; put(ginette); } } else put((unsigned char) val(pnt)); if (clara) { error("Can't relocate a single byte"); } } while ((pnt = nextcoma(pnt)) != NULL); } void relocate(void) { /* if (passe != PASS_CORRECT) { return; } */ if (relocpnt == MAX_RELOC) { fprintf(stderr, "ERROR : Too many entries in relocation table\n"); exit(EXIT_FAILURE); } else { reloc[relocpnt++] = pc; } } void ccheck(void) { if (clara) { error("Impossible relocation"); } } void orage(void) { if (clara) relocate(); } void tempete(struct lotus cherie) { if (cherie.r) relocate(); } void dcw(void) { char ginette; unsigned int love; if ((pnt = nextarg(pnt)) == NULL) return; do { if (*pnt == '\"') { for(;;) { ginette = *(++pnt); if (ginette == '\"' || ginette == 13 || ginette == '\n') break; put(ginette); } } else { love = val(pnt); orage(); wri(&love, 2); } } while ((pnt = nextcoma(pnt)) != NULL); } void dcl(void) { char ginette; unsigned long love; if ((pnt = nextarg(pnt)) == NULL) return; do { if (*pnt == '\"') { for(;;) { ginette = *(++pnt); if (ginette == '\"' || ginette == 13 || ginette == '\n') break; put(ginette); } } else { love = val(pnt); wri(&love, 4); } if (clara) { error("Can't relocate a long constant"); } } while ((pnt = nextcoma(pnt)) != NULL); } void dsb(void) { char ginette; long t, tm; if ((pnt = nextarg(pnt)) == NULL) return; do { if (*pnt == '\"') { for(;;) { ginette = *(++pnt); if (ginette == '\"' || ginette == 13 || ginette == '\n') break; put(0); } } else { tm = val(pnt); for (t = 0; t < tm; t++) put(0); } } while ((pnt = nextcoma(pnt)) != NULL); } void dsw(void) { char ginette; long t, tm; static char tmp[] = { 0, 0 }; if ((pnt = nextarg(pnt)) == NULL) return; do { if (*pnt == '\"') { for(;;) { ginette = *(++pnt); if (ginette == '\"' || ginette == 13 || ginette == '\n') break; put(0); } } else { tm = val(pnt); for (t = 0; t < tm; t++) wri(tmp, 2); } } while ((pnt = nextcoma(pnt)) != NULL); } void dsl(void) { char ginette; long t, tm; static char tmp[] = { 0, 0, 0, 0 }; if ((pnt = nextarg(pnt)) == NULL) return; do { if (*pnt == '\"') { for(;;) { ginette = *(++pnt); if (ginette == '\"' || ginette == 13 || ginette == '\n') break; put(0); } } else { tm = val(pnt); for (t = 0; t < tm; t++) wri(tmp, 4); } } while ((pnt = nextcoma(pnt)) != NULL); } void trap(void) { ware(); if ((pnt = nextarg(pnt)) == NULL) { error("incomplete TRAP #"); } if (*pnt == '#') { pnt++; pnt = skipspace(pnt); } put(0xcd); put(val(pnt)); ccheck(); } void rts(void) { unsigned int oupla; if (sizer == 'L' && seg32 == 0) { put(0x66); } if ((pnt = nextarg(pnt)) == NULL) { put(0xc3); return; } if ((oupla = val(pnt)) != 0) { put(0xc2); orage(); wri(&oupla, 2); } } void rtsf(void) { unsigned int oupla; ware(); if ((pnt = nextarg(pnt)) == NULL) { put(0xcb); return; } if ((oupla = val(pnt)) != 0) { put(0xca); orage(); wri(&oupla, 2); } } void stop(void) { ware(); put(0xf4); } void cmc(void) { ware(); put(0xf5); } void clc(void) { ware(); put(0xf8); } void stc(void) { ware(); put(0xf9); } void cld(void) { ware(); put(0xfc); } void std(void) { ware(); put(0xfd); } void cli(void) { ware(); put(0xfa); } void sti(void) { ware(); put(0xfb); } void aaa(void) { ware(); put(0x37); } void undoc(void) { if (isverbose != 0 && passe == PASS_BRIEF) { warning("Undocumented opcode"); } } void aaundoc(char op) { long im; ware(); put(op); if ((pnt = nextarg(pnt)) == NULL) { im = 0x0a; } else { if (*pnt == ';') { im = 0x0a; goto talali; } else if (*pnt == '#') { pnt = skipspace(++pnt); if (*pnt == '\n' || *pnt == '\r' || *pnt == 0 || *pnt == ';') { error("Some undocumented thing is missing after the # symbol"); } } im = val(pnt); if (im < 0 || im > 255) { undoc(); if (passe == PASS_LAST) { warning("ASCII base operand reduced to a byte"); } im &= 0xff; } } talali: put(im); } void aad(void) { aaundoc(0xd5); } void aam(void) { aaundoc(0xd4); } void aas(void) { ware(); undoc(); put(0x3f); } void salc(void) { ware(); undoc(); put(0xd6); } void icebp(void) { CPUCHECK(C386); ware(); undoc(); put(0xf1); } void int03(void) { CPUCHECK(C386); ware(); undoc(); put(0xf3); } void umov(void) { CPUCHECK(C386); undoc(); put(0x0f); perform(0x10, 0x10, 0, 0, 0x80, 0); } void loadall(void) { CPUCHECK(C386); ware(); undoc(); put(0x0f); put(0x07); } void cmov(void) { CPUCHECK(C686); undoc(); put(0x0f); perform(0x40, 0x40, 0, 0, 0x80, 0); } void rdpmc(void) { CPUCHECK(C686); ware(); undoc(); put(0x0f); put(0x33); } void ud(void) { ware(); undoc(); put(0x0f); put(0x0b); } void ud2(void) { ware(); undoc(); put(0x0f); put(0xb9); } void bwl(void) { if (!sizer) sizer = 'W'; else if (sizer == 'S') sizer = 'B'; else if (sizer != 'B' && sizer != 'W' && sizer != 'L') { error("Invalid size"); } } void lea(void) { take2(); if (sizer == 'B' || sizer == 'S' || pry2.etat != 4) { error("LEA deals only with word and long registers"); } if (pry1.etat < 4) { error("Can't load effective address of an immediate value"); } else if (pry1.etat == 4) { error("Use MOVE"); } perform(0x8a, 0x8a, 0, 1, 0x80, 0); } void adc(void) { perform(0x10, 0x10, 0, 0, 0x80, 0); } void add(void) { perform(0x00, 0x00, 0, 0, 0x80, 0); } void sub(void) { perform(0x28, 0x28, 0, 0, 0x80, 0); } void sbb(void) { perform(0x18, 0x18, 0, 0, 0x80, 0); } void perform(unsigned char fuckepita, int trynow, char runaway, char away2, char horizon, unsigned char tryit) { unsigned char head, head2 = 0, moving = 0, onup = 0; int hole, away = 0; if (!away2) take2(); bwl(); if (pry1.etat == 4) /* Op1 = Registre */ { if (pry2.etat == 4) /* Op2 = Registre */ { switch (sizer) { case 'B' : if (seg32 != 0 && !runaway) { put(0x66); } put(fuckepita + 2); if (pry1.reg1 >= 12 || pry2.reg1 >= 12) { fanfare: error("Instruction and operands sizes don't fit"); } if (pry1.reg1 >= 4) pry1.reg1 -= 4; if (pry2.reg1 >= 4) pry2.reg1 -= 4; head = 0xc0 + (pry2.reg1 << 3) + pry1.reg1 + tryit; put(head); break; case 'W' : if (seg32 != 0 && !runaway) { put(0x66); } put(fuckepita + 3); if ((pry1.reg1 >= 4 && pry1.reg1 <12) || pry1.reg1 >= 20) goto fanfare; if ((pry2.reg1 >= 4 && pry2.reg1 <12) || pry2.reg1 >= 20) goto fanfare; if (pry1.reg1 >= 12) pry1.reg1 -= 12; if (pry2.reg1 >= 12) pry2.reg1 -= 12; head = 0xc0 + (pry2.reg1 << 3) + pry1.reg1 + tryit; put(head); break; default : if (seg32 == 0 && !runaway) { put(0x66); } put(fuckepita + 3); if ((pry1.reg1 >= 4 && pry1.reg1 <16) || pry1.reg1 >= 28) goto fanfare; if ((pry2.reg1 >= 4 && pry2.reg1 <16) || pry2.reg1 >= 28) goto fanfare; if (pry1.reg1 >= 20) pry1.reg1 -= 20; else if (pry1.reg1 >= 16) pry1.reg1 -= 12; if (pry2.reg1 >= 20) pry2.reg1 -= 20; else if (pry2.reg1 >= 16) pry2.reg1 -= 12; head = 0xc0 + (pry2.reg1 << 3) + pry1.reg1 + tryit; put(head); } return; } else if (pry2.etat > 5) /* Op1 = Registre, Op2 = Mem */ { degoute: switch (sizer) { case 'L' : if ((pry1.reg1 >= 4 && pry1.reg1 < 20) || pry1.reg1 >=28) goto fanfare; if (pry1.reg1 >= 20) pry1.reg1 -= 20; away = 1; if (seg32 == 0 && !onup && !runaway) { put(0x66); } goto tocard; case 'W' : if ((pry1.reg1 >= 4 && pry1.reg1 < 12) || pry1.reg1 >=20) goto fanfare; if (pry1.reg1 >= 12) pry1.reg1 -= 12; away = 1; if (seg32 != 0 && !onup && !runaway) { put(0x66); } goto tocard; case 'B' : away = 0; if (seg32 != 0 && !onup && !runaway) { put(0x66); } if (pry1.reg1 >= 12) goto fanfare; if (pry1.reg1 >= 4) pry1.reg1 -= 4; tocard: head = (pry1.reg1 << 3) + tryit; if (pry2.etat < 8) /* Op2 = Absolu.w */ { if (!onup) { if (seg32 != 0 && !runaway) { put(0x67); } put(fuckepita + away); } put(head + 6); hole = pry2.offset; tempete(pry2); wri(&hole, 2); break; } if (pry2.etat == 8) /* Op2 = Absolu.l */ { CPUCHECK(C286); if (!onup) { if (seg32 == 0 && !runaway) { put(0x67); } put(fuckepita + away); } put(head + 5); wri(&pry2.offset, 4); break; } lackers: if (pry2.etat == 9) /* (Reg) */ { if (pry2.reg1 < 4) pry2.reg1 += 12; if (pry2.reg1 == 18 || pry2.reg1 == 19 || pry2.reg1 == 15) { if (!onup) { if (seg32 != 0 && !runaway) { put(0x67); } put(fuckepita + away); } switch (pry2.reg1) { case 18 : head += 4; break; case 19 : head += 5; break; case 15 : head += 7; break; } put(head); break; } if (pry2.reg1 == 17) { if (!onup) { if (seg32 != 0 && !runaway) { put(0x67); } put(fuckepita + away); } if (head < 0x40) { put(0x40 + head + 6); put(0x00); } else { head += 6; put(head); } break; } if (pry2.reg1 >= 20 && pry2.reg1 <= 27) { if (!onup) { if (seg32 == 0 && !runaway) { put(0x67); } put(fuckepita + away); } if (pry2.reg1 == 24) { /* if (head < 0x40) { */ put(head + 4); put(0x24); /* } else { head += 4; put(head); } */ break; } else if (pry2.reg1 == 25) { if (head < 0x40) { put(0x40 + head + 5); put(0x00); } else { head += 5; put(head); } break; } head += (pry2.reg1 - 20); put(head); break; } else culture: error("Unknown adressing mode"); } else if (pry2.etat == 17) /* (Reg,Reg) */ { bouillon: /* if (pry2.reg1 == 16 || pry2.reg1 == 17 || pry2.reg1 == 24 || pry2.reg1 == 25) { char saveit = pry2.reg1; pry2.reg1 = pry2.reg2; pry2.reg2 = saveit; } */ if (pry2.reg1 == 17 || pry2.reg1 == 25) { if (moving == 0) { moving = 1; pry2.offset = 0; if (hole == 1) head += 0x40; else head += 0x80; } } if (pry2.reg1 < 4) pry2.reg1 += 12; if (pry2.reg2 < 4) pry2.reg2 += 12; if ((pry2.reg1 == 15 && pry2.reg2 == 18) || (pry2.reg1 == 18 && pry2.reg2 == 15)) { if (!onup) { if (seg32 != 0 && !runaway) { put(0x67); } put(fuckepita + away); } put(head); break; } else if ((pry2.reg1 == 15 && pry2.reg2 == 19) || (pry2.reg1 == 19 && pry2.reg2 == 15)) { if (!onup) { if (seg32 != 0 && !runaway) { put(0x67); } put(fuckepita + away); } head++; put(head); break; } else if ((pry2.reg1 == 17 && pry2.reg2 == 18) || (pry2.reg1 == 18 || pry2.reg2 == 17)) { if (!onup) { if (seg32 != 0 && !runaway) { put(0x67); } put(fuckepita + away); } head += 2; put(head); break; } else if ((pry2.reg1 == 17 && pry2.reg2 == 19) || (pry2.reg1 == 19 || pry2.reg2 == 17)) { if (!onup) { if (seg32 != 0 && !runaway) { put(0x67); } put(fuckepita + away); } head += 3; put(head); break; } else if (pry2.reg1 >= 20 && pry2.reg1 < 28 && pry2.reg2 >= 20 && pry2.reg2 < 28) { if (!onup) { if (seg32 == 0 && !runaway) { put(0x67); } put(fuckepita + away); } head += 4; put(head); head2 += ((pry2.reg2 - 20) << 3) + pry2.reg1 - 20; put(head2); break; } else goto culture; } else if (pry2.etat == 33) /* (Reg,Reg*Coef) */ { head2 = pry2.factor << 6; goto bouillon; } else if ((hole = ((pry2.etat - 5) & 3)) != 0) /* Offset */ { if (hole == 2) hole++; else if (passe == PASS_LAST && pry2.reg1 < 20 && hole == 3) { error("Offset out of range"); } if (hole == 1) head += 0x40; else head += 0x80; moving = 1; pry2.etat = ((pry2.etat - 5) & ~3) + 5; goto lackers; } else { goto culture; } } if (moving) { if (hole == 1) { put(pry2.offset); } else if (pry2.reg1 >=20 && pry2.reg1 < 28) { wri(&pry2.offset, 4); } else { wri(&pry2.offset, 2); } } if (onup) { if (onup == 1) put(pry1.offset); else if (onup == 2) { hole = pry1.offset; tempete(pry1); wri(&hole, 2); } else { wri(&pry1.offset, 4); } } return; } else { error("Can't assign immediate values"); } } else if (pry1.etat < 4 && pry2.etat == 4) /* #,Reg */ { switch (sizer) { case 'L' : if ((pry2.reg1 >= 4 && pry2.reg1 < 20) || pry2.reg1 >=28) goto fanfare; if (pry2.reg1 >= 20) pry2.reg1 -= 20; away = 3; if (seg32 == 0 && !runaway) { put(0x66); } goto petard; case 'W' : if ((pry2.reg1 >= 4 && pry2.reg1 < 12) || pry2.reg1 >=20 || pry1.etat == 3) goto fanfare; if (pry2.reg1 >= 12) pry2.reg1 -= 12; away = 3; if (seg32 != 0 && !runaway) { put(0x66); } goto petard; case 'B' : away = 0; if (seg32 != 0 && !runaway) { put(0x66); } if (pry2.reg1 >= 12 || pry1.etat != 1) goto fanfare; if (pry2.reg1 >= 4) pry2.reg1 -= 4; } petard: head = pry2.reg1; if (pry1.etat == 1 && pry1.offset >= -128 && pry1.offset <= 127) { if (pry2.reg1 || sizer == 'L') { put(horizon + away); head += 0xc0 + fuckepita; put(head); } else goto unreality; put(pry1.offset); } else { if (pry2.reg1) { put(horizon + away - 2); head += 0xc0 + fuckepita; put(head); } else { unreality: if (away == 3) away =1; put(fuckepita + 4 + away); } if (pry1.etat == 3 || sizer == 'L') wri(&pry1.offset, 4); else if (pry1.etat == 2 || sizer == 'W') { hole = pry1.offset; tempete(pry1); wri(&hole, 2); } else put(pry1.offset); } } else if (pry1.etat > 5 && pry2.etat == 4) /* Mem,Reg */ { struct lotus donald; donald = pry1; pry1 = pry2; pry2 = donald; fuckepita += 2; goto degoute; } else if (pry1.etat < 4 && pry2.etat > 5) /* #,Mem */ { tryit = trynow; if (pry2.etat < 8) pry2.reg1 = 0; else if (pry2.etat == 8) pry2.reg1 = 21; if (sizer == 'B' && pry1.etat == 1) { if (seg32 != 0 && !runaway) { put(0x66); } if (seg32 == 0 && pry2.reg1 > 20 && !runaway) { put(0x67); } else if (seg32 != 0 && pry2.reg1 <= 20 && !runaway) { put(0x67); } pry1.etat = 4; pry1.reg1 = 0; onup = 1; put(horizon); goto degoute; } else if (sizer == 'W' && pry1.etat == 2) { if (seg32 != 0 && !runaway) { put(0x66); } if (seg32 == 0 && pry2.reg1 > 20 && !runaway) { put(0x67); } else if (seg32 != 0 && pry2.reg1 <=20 && !runaway) { put(0x67); } pry1.etat = 4; pry1.reg1 = 0; onup = 2; put(horizon + 1); goto degoute; } else if (sizer == 'W' && pry1.etat == 1) { if (seg32 != 0 && !runaway) { put(0x66); } if (seg32 == 0 && pry2.reg1 > 20 && !runaway) { put(0x67); } else if (seg32 != 0 && pry2.reg1 <= 20 && !runaway) { put(0x67); } pry1.etat = 4; pry1.reg1 = 0; onup = 1; put(horizon + 3); goto degoute; } else if (sizer == 'L' && pry1.etat == 1) { if (seg32 == 0 && !runaway) { put(0x66); } if (seg32 == 0 && pry2.reg1 > 20 && !runaway) { put(0x67); } else if (seg32 != 0 && pry2.reg1 <=20 && !runaway) { put(0x67); } pry1.etat = 4; pry1.reg1 = 0; onup = 1; put(horizon + 3); goto degoute; } else if (sizer == 'L') { if (seg32 == 0 && !runaway) { put(0x66); } if (seg32 == 0 && pry2.reg1 > 20 && !runaway) { put(0x67); } else if (seg32 != 0 && pry2.reg1 <= 20 && !runaway) { put(0x67); } pry1.etat = 4; pry1.reg1 = 0; onup = 4; put(horizon + 1); goto degoute; } else { error("Size mismatch with constant"); } } else { error("Unknown assignement"); } } void org(void) { ware(); if ((pnt = nextarg(pnt)) == NULL) { error("ORG needs one argument"); } orgvalue = pcwoalign = pc = val(pnt); ccheck(); } void opt(void) { char zekar, newcar; ware(); if ((pnt = nextarg(pnt)) == NULL) { error("OPT needs one argument"); } zekar = tolower(*pnt++); newcar = *pnt; if (newcar != '+' && newcar != '-') { error("'+' or '-' awaited to enable/disable an option"); } switch(zekar) { case 'v' : isverbose = (newcar == '+') ? 1 : 0; break; case 'o' : optimize = (newcar == '+') ? 1 : 0; break; case 'q' : isquiet = (newcar == '+') ? 1 : 0; break; case 'w' : nowarning = (newcar == '-') ? 1 : 0; break; case 'a' : autoalign = (newcar == '+') ? 1 : 0; break; default : warning("Unrecognized option"); } } void title(void) { } void assume(void) { ware(); if ((pnt = nextarg(pnt)) == NULL) { error("ASSUME needs one argument"); } assumer = 0; assumer = val(pnt); ccheck(); if ((assumer & 15) != 0 && passe == PASS_LAST) { warning("Assuming a non segment-aligned value"); } } void segment(void) { ware(); maxsegcounter = maxsegsize; while (pc & 15) { put(0x90); pcwoalign--; } column(); } void page(void) { ware(); maxsegcounter = maxsegsize; while(pc & 0xff) { put(0x90); pcwoalign--; } column(); } void dpage(void) { ware(); maxsegcounter = maxsegsize; while(pc & 0x1ff) { put(0x90); pcwoalign--; } column(); } void even(void) { ware(); if (pc & 1) { put(0x90); pcwoalign--; } } void align(void) { if (sizer == 'B' || sizer == 'S') { warning("Directive has no effect"); } else { bwl(); if (sizer == 'W') { if (pc & 1) { put(0x90); pcwoalign--; } } else { while(pc & 3) { put(0x90); pcwoalign--; } } } } void alignq(void) { if (sizer) { error("Ambigous directive"); } while(pc & 7) { put(0x90); pcwoalign--; } } void and(void) { perform(0x20, 0x20, 0, 0, 0x80, 0); } void xor(void) { perform(0x30, 0x30, 0, 0, 0x80, 0); } void arpl(void) { CPUCHECK(C286); limit(); perform(0x60, 0x60, 0, 0, 0x80, 0); } void limit(void) { char *toc; toc = pnt; take2(); bwl(); pnt = toc; if (pry2.etat != 4 || pry1.etat < 4 || sizer == 'B') { error("Impossible adressing mode"); } } void limit2(void) { char *toc; toc = pnt; take2(); bwl(); pnt = toc; if (pry2.etat != 4 || pry1.etat <= 4 || sizer == 'B') { error("Impossible adressing mode"); } } void bound(void) { CPUCHECK(C186); limit2(); perform(0x5F, 0x5F, 0, 0, 0x80, 0); } void bsf(void) { CPUCHECK(C386); limit(); if ((pry1.etat > 5 && (pry1.reg1 >= 4 && pry1.reg1 < 12)) || pry1.etat == 1) { snake: error("Incoherent sizes"); } if (sizer == 'W') { if (pry1.etat == 3 || (pry1.etat > 5 && pry1.reg1 >= 20)) goto snake; if (seg32 != 0) { put(0x66); put(0x67); } put(0x0f); perform(0xb9, 0xb9, 0, 0, 0x80, 0); } else { if (pry1.etat == 2 || (pry1.etat > 5 && pry1.reg1 < 20 && pry1.reg1 >= 4)) goto snake; if (seg32 == 0) { put(0x66); put(0x67); } put(0x0f); perform(0xb9, 0xb9, 1, 0, 0x80, 0); } } void bsr(void) { CPUCHECK(C386); limit(); if ((pry1.etat > 5 && (pry1.reg1 >= 4 && pry1.reg1 < 12)) || pry1.etat == 1) { snake: error("Incoherent sizes"); } if (sizer == 'W') { if (pry1.etat == 3 || (pry1.etat > 5 && pry1.reg1 >= 20)) goto snake; if (seg32 != 0) { put(0x66); put(0x67); } put(0x0f); perform(0xBA, 0xBA, 0, 0, 0x80, 0); } else { if (pry1.etat == 2 || (pry1.etat > 5 && pry1.reg1 < 20 && pry1.reg1 >= 4)) goto snake; if (seg32 == 0) { put(0x66); put(0x67); } put(0x0f); perform(0xBA, 0xBA, 1, 0, 0x80, 0); } } void take1(void) { if ((pnt = nextarg(pnt)) == NULL) { error("One argument is missing"); } pry1 = getadrs(pnt); } void swap(void) { CPUCHECK(C486); take1(); ware(); if (pry1.etat != 4) { error("Invalid adressing mode"); } if ((pry1.reg1 >= 4 && pry1.reg1 < 20) || (pry1.reg1 >= 28)) { error("SWAP can only work on 32 bits registers"); } if (pry1.reg1 >= 20) pry1.reg1 -= 20; if (seg32 == 0) { put(0x66); } put(0x0f); put(0xc8 + pry1.reg1); } void bits(unsigned char mediatic) { char *toc; CPUCHECK(C386); toc = pnt; take2(); pnt = toc; bwl(); if (pry1.etat == 1) { if (pry2.etat == 4) /* #b,reg.w */ { if (pry2.reg1 >= 12 && pry2.reg1 < 20) pry2.reg1 -= 12; else if (pry2.reg1 > 4) { error("Only a word register can be used"); } put(0x0f); put(0xba); put(0xe0 + pry2.reg1); put(pry1.offset); } else if (pry2.etat < 5) goto bang; else /* #b,mem */ { if (sizer == 'B') { error("Only .W and .L fit to <#b>,"); } hey(pry2); put(0x0f); perform(0x20 + mediatic, 0x20 + mediatic, 1, 1, 0xb7, 0); } } else if (pry1.etat == 4) { if (pry2.etat == 4) /* reg,reg */ { if (pry1.reg1 >= 12 && pry1.reg1 < 20) pry1.reg1 -= 12; else if (pry1.reg1 > 4) { thisismydream: error("Only a word register can be used"); } if (pry2.reg1 >= 12 && pry2.reg1 < 20) pry2.reg1 -= 12; else if (pry2.reg1 > 4) goto thisismydream; put(0x0f); put(0xa3); put(0xc0 + (pry1.reg1 << 3) + pry2.reg1); } else if (pry2.etat < 5) goto bang; else { if (sizer == 'B') { error("Only .W and .L fit to ,"); } hey(pry2); put(0x0f); perform(0xa2 + mediatic, 0xa2 + mediatic, 1, 0, 0x80, 0); } } else { bang: error("unknown adressing mode"); } } void bt(void) { bits(0); } void btc(void) { bits(0x18); } void btr(void) { bits(0x10); } void bts(void) { bits(0x8); } void colle(char uhu, char yo, char helicoptere) { long relative; signed short rel2; if (!helicoptere) { take1(); bwl(); } if (sizer == 'B' || sizer == 'S') { error("Byte jump is impossible"); } if (pry1.etat < 4 || (uhu && pry1.etat > 5 && pry1.etat < 9)) { relative = pry1.offset - rpc - 3; rel2 = (signed short) relative; if (sizer == 'L') { if (seg32 == 0) { put(0x67); } else { relative++; } put(0xe8); relative -= 3; wri(&relative, 4); } else if (rel2 != relative && passe == PASS_LAST) { error("Jump too far, use JSR.L/JSRF"); } else { if (seg32 != 0) { rel2--; put(0x67); } put(0xe8); wri(&rel2, 2); } } else if (pry1.etat == 4) { if (pry1.reg1 >= 20 && pry1.reg1 < 28) { sizer = 'L'; pry1.reg1 -= 20; } else if ((pry1.reg1 >= 4 && pry1.reg1 < 12) || pry1.reg1 >= 20) { error("Only word/long registers can fit with JSR/CALL"); } else if (pry1.reg1 >= 12) { if (sizer == 'W') pry1.reg1 -= 12; else { error("Incoherent instruction and register sizes"); } } if (sizer == 'L') { if (seg32 == 0) { put(0x66); } } else if (seg32 != 0) { put(0x66); } put(0xff); put((yo == 0xd0) ? 0xd0 + pry1.reg1 : 0xe0 + pry1.reg1); } else { pry2.etat = 4; if (sizer == 'L') pry2.reg1 = 23; else pry2.reg1 = 14; if (pry1.etat == 8 || (pry1.etat >= 9 && pry1.reg1 >= 20)) { if (seg32 == 0) { put(0x67); } } else if (seg32 != 0) { put(0x67); } perform(0xfc, 0xfc, 1, 1, 0x80, (yo == 0xd0) ? 0 : 0x10); } } void call(void) { colle(0, 0xd0, 0); } void callz(void) { colle(1, 0xd0, 0); } void collef(char uhu, char stylo) { unsigned short youpla; if (uhu) take1(); else take2(); bwl(); if (sizer == 'B') { error("Byte values can't fit to far jumps"); } if (uhu) { pry2.offset = pry1.offset & 0xf; pry1.offset >>= 4; if (sizer == 'L') { pry1.etat = 7; pry2.etat = 8; } else if (pry1.offset == (unsigned short) pry1.offset) { pry1.etat = pry2.etat = 7; pry1.r = 1; } else { error("Jump too far for a 16 bit segment"); } } if (pry1.etat == 6 || pry1.etat == 7) { if (sizer == 'L' && pry2.etat >= 6 && pry2.etat <= 8) { if (seg32 == 0) { put(0x66); } put(stylo); wri(&pry2.offset, 4); goto jerk; } else if (pry2.etat == 6 || pry2.etat == 7) { if (seg32 != 0) { put(0x66); } put(stylo); youpla = (unsigned short) pry2.offset; tempete(pry2); wri(&youpla, 2); jerk: youpla = (unsigned short) pry1.offset; tempete(pry1); wri(&youpla, 2); } else { error("Incorrect index to far jump"); } } else { error("Incorrect base to far jump"); } } void callf(void) { collef(0, 0x9a); } void callzf(void) { collef(1, 0x9a); } void cbw(void) { CPUCHECK(C386); bwl(); if (sizer == 'W') { if (seg32 != 0) { put(0x66); } put(0x98); } else if (sizer == 'L') { if (seg32 == 0) { put(0x66); } put(0x98); } else { error("Can't extend to a byte"); } } void cwd(void) { CPUCHECK(C386); ware(); put(0x99); } void cwde(void) { CPUCHECK(C386); ware(); if (seg32 == 0) { put(0x66); } put(0x98); } void cdq(void) { CPUCHECK(C386); if (sizer && passe == PASS_BRIEF) { warning("Conversion forced from LONG to QUAD"); } if (seg32 == 0) { put(0x66); } put(0x99); } void clts(void) { CPUCHECK(C286); ware(); put(0x0f); put(0x06); } void cmp(void) { perform(0x38, 0x38, 0, 0, 0x80, 0); } void test(void) { take2(); bwl(); if (pry1.etat < 4) { if (sizer == 'B') { if (pry1.etat != 1) { if (passe == PASS_LAST) { warning("Constant too large for a byte"); } pry1.offset &= 0xff; pry1.etat = 1; } } else if (sizer == 'W') { if (pry1.etat == 3) { if (passe == PASS_LAST) { warning("Constant too large for a word"); } pry1.offset &= 0xffff; } pry1.etat = 2; } else pry1.etat = 3; if (pry2.etat == 4 && (pry2.reg1 == 0 || pry2.reg1 == 4 || pry2.reg1 == 12 || pry2.reg1 == 20)) perform(0xa4, 0xa4, 0, 1, 0xf6, 0); else perform(0x00, 0x00, 0, 1, 0xf6, 0); } else perform(0x82, 0x82, 0, 1, 0x80, 0); } void macadam(char assez) { bwl(); if (seg32 == 0) { if (sizer == 'L') { CPUCHECK(C286); put(0x66); } } else { if (sizer != 'L') { put(0x66); } } put((sizer == 'B') ? assez : assez + 1); } void cmps(void) { macadam(0xa6); } void daa(void) { ware(); put(0x27); } void das(void) { ware(); put(0x2f); } void decom(unsigned char banjo) { take1(); bwl(); if (pry1.etat == 4) { if (sizer == 'B') { if (pry1.reg1 >= 4 && pry1.reg1 < 12) pry1.reg1 -= 4; else if (pry1.reg1 >= 4) { demakeup: error("Incoherent instruction and register"); } if (seg32 != 0) { put(0x66); } put(0xfe); put(0xc0 + banjo + pry1.reg1); } else if (sizer == 'W') { if (pry1.reg1 >= 12 && pry1.reg1 < 20) pry1.reg1 -= 12; else if (pry1.reg1 >= 4) goto demakeup; if (seg32 != 0) { put(0x66); } put(0x40 + banjo + pry1.reg1); } else { if (pry1.reg1 >= 20 && pry1.reg1 < 28) pry1.reg1 -= 20; else if (pry1.reg1 >= 4) goto demakeup; if (seg32 == 0) { put(0x66); } put(0x40 + banjo + pry1.reg1); } } else if (pry1.etat < 4) { error("Can't decrement an immediate value"); } else if (pry1.etat == 8) { error("Can't manage a 32-bits address"); } else { pry2.etat = 4; pry2.reg1 = 0; hey(pry1); perform(0xfc, 0xfc, 1, 1, 0x80, banjo); } } void dec(void) { decom(8); } void divide(signed char mobylette) { take1(); bwl(); if (pry1.etat == 4) { if (sizer == 'B') { if (pry1.reg1 >= 4 && pry1.reg1 < 12) pry1.reg1 -= 4; else if (pry1.reg1 >= 4) { demakeup: error("Incoherent instruction and register"); } if (seg32 != 0) { put(0x66); } put(0xf6); put(0xf0 + pry1.reg1 + mobylette); } else if (sizer == 'W') { if (pry1.reg1 >= 12 && pry1.reg1 < 20) pry1.reg1 -= 12; else if (pry1.reg1 >= 4) goto demakeup; if (seg32 != 0) { put(0x66); } put(0xf7); put(0xf0 + pry1.reg1 + mobylette); } else { if (pry1.reg1 >= 20 && pry1.reg1 < 28) pry1.reg1 -= 20; else if (pry1.reg1 >= 4) goto demakeup; if (seg32 == 0) { put(0x66); } put(0xf7); put(0xf0 + pry1.reg1 + mobylette); } } else if (pry1.etat < 4) { error("Can't modify an immediate value"); } else if (pry1.etat == 8) { error("Can't manage a 32-bits address"); } else { pry2.etat = 4; pry2.reg1 = 0; hey(pry1); perform(0xf4, 0xf4, 1, 1, 0x80, 0x30 + mobylette); } } void div_(void) { divide(0); } void enter(void) { unsigned short chatte; CPUCHECK(C186); take2(); ware(); if (pry1.etat == 1 || pry1.etat == 2 || pry1.etat == 6 || pry1.etat == 7) { if (pry2.etat == 1 || pry2.etat == 6) { put(0xc8); chatte = pry1.offset; tempete(pry1); wri(&chatte, 2); put(pry2.offset); } else { error("Immediate byte expected as second argument"); } } else { error("Immediate word expected as first argument"); } } void wait_(void) { ware(); put(0x9b); } void idiv(void) { divide(8); } void imul(void) { char *tuviens; signed short toudou; tuviens = pnt; if ((pnt = nextarg(pnt)) == NULL) { error("Missing arguments"); } pry1 = getadrs(pnt); bwl(); if (!pry1.etat) { error("Invalid adressing mode"); } while(*pnt != ',' && *pnt != '\n' && *pnt != 13) pnt++; if (*pnt++ != ',') { ami: pnt = tuviens; divide(-8); return; } pnt = skipspace(pnt); if (pry1.etat >= 13) { while(*pnt != ',' && *pnt != '\n' && *pnt != 13) pnt++; if (*pnt++ != ',') goto ami; pnt = skipspace(pnt); } pry2 = getadrs(pnt); if (!pry2.etat) { error("Invalid adressing mode"); } while(*pnt != ',' && *pnt != '\n' && *pnt != 13) pnt++; if (*pnt++ != ',') { delicate: if (pry2.etat != 4) { error("Register awaited as second argument"); } if (sizer == 'B') { error("Multiplication of byte registers not allowed"); } if (pry1.etat == 4) { if (sizer == 'W') { if (pry1.reg1 >= 12 && pry1.reg1 < 20) pry1.reg1 -= 12; else if (pry1.reg1 >= 4) { error("Word register awaited as first argument"); } if (pry2.reg1 >= 12 && pry2.reg1 < 20) pry2.reg1 -= 12; else if (pry2.reg1 >= 4) { error("Word register awaited as second argument"); } if (seg32 != 0) { put(0x66); } put(0x0f); put(0xaf); put(0xc0 + (pry2.reg1 << 3) + pry1.reg1); } else { if (pry1.reg1 >= 20 && pry1.reg1 < 28) pry1.reg1 -= 20; else if (pry1.reg1 >= 4) { error("Long register awaited as first argument"); } if (pry2.reg1 >= 20 && pry2.reg1 < 28) pry2.reg1 -= 20; else if (pry2.reg1 >= 4) { error("Long register awaited as second argument"); } if (seg32 == 0) { put(0x66); } put(0x0f); put(0xaf); put(0xc0 + (pry2.reg1 << 3) + pry1.reg1); } } else if (pry1.etat > 5) { if (pry1.etat == 8) { error("Direct 32-bits addresses can't be used"); } hey(pry1); put(0x0f); perform(0xac, 0xac, 1, 1, 0x80, 0); } else { pry3 = pry2; goto loulou; } return; } pnt = skipspace(pnt); if (pry1.etat >= 13) { while(*pnt != ',' && *pnt != '\n' && *pnt != 13) pnt++; if (*pnt++ != ',') goto delicate; pnt = skipspace(pnt); } pry3 = getadrs(pnt); loulou: if (pry1.etat == 1 || pry1.etat == 2 || (pry1.etat == 3 && sizer == 'L')) { if (pry3.etat != 4) { error("Register awaited as third argument"); } if (sizer == 'B') { error("Multiplication of byte registers not allowed"); } if (pry2.etat == 4) { if (sizer == 'L') { if (pry2.reg1 >= 20 && pry2.reg1 < 28) pry2.reg1 -= 20; else if (pry2.reg1 >= 4) { error("Long register awaited as second argument"); } if (pry3.reg1 >= 20 && pry3.reg1 < 28) pry3.reg1 -= 20; else if (pry3.reg1 >= 4) { error("Long register awaited as third argument"); } if (seg32 == 0) { put(0x66); } } else { if (pry2.reg1 >= 12 && pry2.reg1 < 20) pry2.reg1 -= 12; else if (pry2.reg1 >= 4) { error("Word register awaited as second argument"); } if (pry3.reg1 >= 12 && pry3.reg1 < 20) pry3.reg1 -= 12; else if (pry3.reg1 >= 4) { error("Word register awaited as third argument"); } if (seg32 != 0) { put(0x66); } } if (pry1.etat == 1) { put(0x6b); put(0xc0 + pry2.reg1 + (pry3.reg1 << 3)); put(pry1.offset); } else { if (sizer == 'L') { put(0x69); put(0xc0 + pry2.reg1 + (pry3.reg1 << 3)); wri(&pry1.offset, 4); } else { if (pry1.etat == 3 && passe == PASS_LAST) { error("Immediate too large"); } toudou = (signed short) pry1.offset; put(0x69); put(0xc0 + pry2.reg1 + (pry3.reg1 << 3)); tempete(pry2); wri(&toudou, 2); } } } else { error("MULS <#>,, not implemented yet"); } } else { error("Correct constant awaited as first argument"); } } void in(void) { bwl(); if ((pnt = nextarg(pnt)) == NULL) { error("One or two arguments are missing"); } pry1 = getadrs(pnt); if (pry1.etat == 7 && pry1.offset <= 255) pry1.etat = 6; if (pry1.etat != 6 && pry1.etat != 1 && !(pry1.etat == 4 && (pry1.reg1 == 2 || pry1.reg1 == 14))) { error("[First] parameter must be D or #"); } while(*pnt != ',' && *pnt != '\n' && *pnt != 13) pnt++; if (*pnt++ != ',') goto cjwilson; pnt = skipspace(pnt); if (pry1.etat >= 13) { while(*pnt != ',' && *pnt != '\n' && *pnt != 13) pnt++; if (*pnt++ != ',') goto cjwilson; pnt = skipspace(pnt); } pry2 = getadrs(pnt); if (!(pry2.etat == 4 && (pry2.reg1 == 0 || (pry2.reg1 == 4 && sizer == 'B') || (pry2.reg1 == 12 && sizer == 'W') || (pry2.reg1 == 20 && sizer == 'L')))) { error("Second parameter must be A or nothing"); } cjwilson: if (sizer == 'L') { if (seg32 == 0) { put(0x66); } } else if (seg32 != 0) { put(0x66); } if (pry1.etat == 4) put((sizer == 'B') ? 0xec : 0xed); else { put((sizer == 'B') ? 0xe4 : 0xe5); put(pry1.offset); } } void out(void) { bwl(); if ((pnt = nextarg(pnt)) == NULL) { error("One or two arguments are missing"); } pry1 = getadrs(pnt); if (pry1.etat == 7 && pry1.offset <= 255) pry1.etat = 6; if (pry1.etat != 6 && pry1.etat != 1 && !(pry1.etat == 4 && (pry1.reg1 == 2 || pry1.reg1 == 14))) { if (!(pry1.etat == 4 && (pry1.reg1 == 0 || (pry1.reg1 == 4 && sizer == 'B') || (pry1.reg1 == 12 && sizer == 'W') || (pry1.reg1 == 20 && sizer == 'L')))) { error("Source parameter must be A or nothing"); } while(*pnt != ',' && *pnt != '\n' && *pnt != 13) pnt++; if (*pnt++ != ',') goto cjwilson; pnt = skipspace(pnt); if (pry1.etat >= 13) { while(*pnt != ',' && *pnt != '\n' && *pnt != 13) pnt++; if (*pnt++ != ',') goto cjwilson; pnt = skipspace(pnt); } pry1 = getadrs(pnt); if (pry1.etat == 7 && pry1.offset <= 255) pry1.etat = 6; if (pry1.etat != 6 && pry1.etat != 1 && !(pry1.etat == 4 && (pry1.reg1 == 2 || pry1.reg1 == 14))) { cjwilson: error("Port number or D expected as target"); } } if (sizer == 'L') { if (seg32 == 0) { put(0x66); } } else if (seg32 != 0) { put(0x66); } if (pry1.etat == 4) put((sizer == 'B') ? 0xee : 0xef); else { put((sizer == 'B') ? 0xe6 : 0xe7); put(pry1.offset); } } void inc(void) { decom(0); } void incbin(void) { char *proutos; FILE *facteur; size_t crash; proutos = prout; if ((pnt = nextarg(pnt)) == NULL) { error("A file name is missing"); } if (*pnt == '\'' || *pnt == '\"') { pnt = skipspace(++pnt); if (*pnt == 13 || *pnt == '\n') { error("A file name is missing after the \""); } } while (*pnt != 13 && *pnt != '\n' && *pnt != '\t' && *pnt != '\'' && *pnt != '\"') *proutos++ = *pnt++; *proutos = 0; if ((facteur = fopen(prout, "rb")) == NULL) { fprintf(stderr, "ERROR : Can't open [%s] at line %ld\n", prout , pl); exit(EXIT_FAILURE); } fsh(); while ((crash = fread(buffer, 1, IOBUFFER, facteur)) != 0) { wri(buffer, crash); } fclose(facteur); } void yop(char youplaboum) { ware(); put(youplaboum); if (*(pnt = skipspace(pnt)) == ':') { rpc++; pnt++; soundgarden(); } } void lock(void) { yop(0xf0); } void repne(void) { yop(0xf2); } void repe(void) { yop(0xf3); } void cs(void) { yop(0x2e); } void ds(void) { yop(0x3e); } void es(void) { yop(0x26); } void fs(void) { yop(0x64); } void gs(void) { yop(0x65); } void ss(void) { yop(0x36); } void rept(void) { if (reupeuteumeu >= 0) { error("Can't imbricate REPT...ENDR structures"); } take1(); if (pry1.etat < 4 || pry1.etat == 6 || pry1.etat == 7 || pry1.etat == 8) { if ((retimes = pry1.offset) <= 0) { error("Can't repeat a negative (or 0) time"); } else if (retimes == 1 && passe == PASS_BRIEF) { warning("Superflous REPT...ENDR"); } reupeuteumeu = ftell(joe); repl = pl; } else { error("Constant expected with a REPT"); } } void endr(void) { if (--retimes) { fseek(joe, reupeuteumeu, SEEK_SET); pl = repl; } else reupeuteumeu = -1; } void include(void) { register char *proutos; char zok; register struct stackent *ent; if ((pnt = nextarg(pnt)) == NULL) { error("INCLUDE needs a file name"); } if (*pnt == '\"') { pnt++; if ((proutos = strchr(pnt, '\"')) == NULL) { error("Missing double quotes"); } *proutos = 0; } else if (*pnt == '\'') { pnt++; if ((proutos = strchr(pnt, '\'')) == NULL) { error("Missing closing quote"); } *proutos = 0; } proutos = pnt; do { zok = *proutos++; } while (zok != '\n' && zok != 0 && zok != 13 && zok != '\t'); *--proutos = 0; if (upstack != NULL) { ent = upstack; do { if (!strcasecmp(ent->file, pnt)) { error("Circular include references"); } } while ((ent = ent->link) != NULL); } if (!isquiet) { printf("\tIncluding nested file : [%s]\n", pnt); } if ((ent = (struct stackent *) malloc(sizeof(struct stackent))) == NULL) { fprintf(stderr, "ERROR : Oh no ! More memory for dynamic stack\n"); exit(EXIT_FAILURE); } ent->link = upstack; ent->file = sourcefile; ent->pl = pl; ent->pos = ftell(joe); upstack = ent; fclose(joe); joe = NULL; if ((sourcefile = (char *) malloc(strlen(pnt) + 1)) == NULL) { fprintf(stderr, "ERROR : Outta memory to stack file names\n"); exit(EXIT_FAILURE); } strcpy(sourcefile, pnt); if ((joe = fopen(sourcefile, "rt")) == NULL) { fprintf(stderr, "ERROR : Can't include [%s] at line %ld\n", sourcefile, pl); exit(EXIT_FAILURE); } pl = 0; } void macro(void) { #ifndef REGISTERED error("Macros are only available in the registered release"); #else register char *onemoretime = line; char c; register struct macroent *ent; char *damacro, *damacropnt; for (;;) { c = *onemoretime; if (c == '\t' || c == ' ' || c == ':') break; onemoretime++; } *onemoretime++ = 0; onemoretime = skipspace(onemoretime); if (strtokcasecmp(onemoretime, "macro")) { warning("Suspicious garbage before MACRO"); } for (;;) { if (*onemoretime == 0 || *onemoretime == '\n' || *onemoretime == '\r') { error("Parse error in macro standing"); } if (!strtokcasecmp(onemoretime, "macro")) break; onemoretime++; } if ((ent = (struct macroent *) malloc(sizeof(struct macroent))) == NULL) { warning("No more memory for macros"); return; } pnt = line; if ((damacro = (char *) malloc(strlen(pnt) + 1)) == NULL) { warning("Can't store macro name"); return; } damacropnt = damacro; do { *damacropnt++ = c = tolower(*pnt++); } while (c != 0); ent->link = upmacro; ent->file = sourcefile; ent->macro = damacro; ent->pl = pl + 1; ent->pos = ftell(joe); upmacro = ent; #endif } void endm(void) { #ifdef REGISTERED #endif } void once(void) { #ifndef REGISTERED warning("Register GEMA to enjoy the ONCE directive"); #else register struct stackent *scan = uponce; int found = 0; char *source2; while (scan != NULL) { if (!strcasecmp(scan->file, sourcefile)) { if (scan->pl == tpasse) { found = 1; break; } else { scan->pl = tpasse; } } scan = scan->link; } if (found) { fseek(joe, 0, SEEK_END); if (isverbose && passe == PASS_BRIEF) { printf("- Skipping [%s] due to an ONCE directive -\n", sourcefile); } return; } if (passe != PASS_BRIEF) { return; } if ((scan = (struct stackent *) malloc(sizeof *scan)) == NULL) { error("No more memory for ONCE pragma"); } if ((source2 = (char *) malloc(strlen(sourcefile) + 1)) == NULL) { error("Need more memory for ONCE pragma"); } strcpy(source2, sourcefile); scan->file = source2; scan->pl = tpasse; scan->link = uponce; uponce = scan; #endif } void set(void) { char *proutos, zok; unsigned int size = 0; int thinkabout; long matou; CPUCHECK(C386); if ((pnt = nextarg(pnt)) == NULL) { error("SET needs one argument"); } matou = val(pnt); ccheck(); pnt = line; proutos = prout; for (;;) { zok = *pnt++; if (zok == '\n' || zok == ':' || zok == '\t' || zok == ' ' || zok == 13) break; if (isalnum(zok) || zok == '_' || zok == '.' || zok == '!') { *proutos++ = zok; size++; } else { error("Invalid variable name"); } } if (!size) { error("Variable declaration error"); } prout[size] = 0; if ((thinkabout = checkduplicatelabel()) == -1) { error("SET error"); } else where[thinkabout] = matou; } void ins(void) { CPUCHECK(C186); macadam(0x6c); } void into(void) { ware(); put(0xce); } void invd(void) { CPUCHECK(C486); ware(); put(0x0f); put(0x08); } void iret(void) { if (sizer == 'L') { if (seg32 == 0) { put(0x66); } } else if (seg32 != 0) { put(0x66); } else if (sizer == 'B' || sizer == 'S') { error("Byte return is impossible"); } put(0xcf); } void iretd(void) { CPUCHECK(C386); ware(); if (seg32 == 0) { put(0x66); } put(0xcf); } void j(char rio) { long relative; short rel2; take1(); bwl(); if (pry1.etat != 1 && pry1.etat != 2 && pry1.etat != 3 && pry1.etat != 6 && pry1.etat != 7 && pry1.etat != 8) { error("Pointer expected"); } relative = pry1.offset - rpc; if (sizer == 'B') { hun: relative -= 2; if (relative > 127 || relative < -128) { if (passe == PASS_LAST) { error("Jump too far for a byte, try .W"); } else { relative = 0; } } if (seg32 != 0) { put(0x67); relative--; } put(rio); put(relative); } else if (sizer == 'W') { if (optimize != 0 && unresolvedlabel == 0) { if (relative <= 0x7a && relative >= -0x7a) { if (isverbose && passe == PASS_LAST) { warning("Conditional jump was made short"); } sizer = 'B'; goto hun; } } relative -= 4; rel2 = (signed short) relative; if (relative < -0x7ff0L || relative > 0x7ff0L) { if (passe == PASS_LAST) { error("Jump too far for a word, try .L"); } else { relative = 0; } } if (seg32 != 0) { put(0x67); rel2--; } put(0x0f); put(rio + 0x10); wri(&rel2, 2); } else { relative -= 4; if (seg32 == 0) { put(0x67); relative--; } put(0x0f); put(rio + 0x10); wri(&relative, 4); } } void ja(void) { j(0x77); } void jae(void) { j(0x73); } void jb(void) { j(0x72); } void jbe(void) { j(0x76); } void bizaroide(char trouakar) { long relative; take1(); if (pry1.etat != 1 && pry1.etat != 2 && pry1.etat != 3 && pry1.etat != 6 && pry1.etat != 7 && pry1.etat != 8) { error("8-bits pointer expected"); } if (sizer == 'W' || sizer == 'L') { error("BCXZ and BCEZ can only address a 8-bits offset"); } relative = pry1.offset - rpc - 2 - trouakar; if (passe == PASS_LAST && (relative > 127 || relative < -128)) { error("Jump out of byte range"); } if (trouakar) { if (seg32 == 0) { put(0x67); } } else if (seg32 != 0) { put(0x67); } put(0xe3); put(relative); } void jcxz(void) { bizaroide(0); } void jecxz(void) { bizaroide(1); } void je(void) { j(0x74); } void jg(void) { j(0x7f); } void jge(void) { j(0x7d); } void jl(void) { j(0x7c); } void jle(void) { j(0x7e); } void jno(void) { j(0x71); } void jnp(void) { j(0x7b); } void jns(void) { j(0x79); } void jne(void) { j(0x75); } void jo(void) { j(0x70); } void jp(void) { j(0x7a); } void js(void) { j(0x78); } void s(char rio) { take1(); if ((sizer == 'W' || sizer == 'L') && passe == PASS_BRIEF) { warning("Size forced to BYTE at line"); } sizer = 'B'; if (pry1.etat < 4) { error("Register or byte pointer expected"); } hey(pry1); pry2.etat = 4; pry2.reg1 = 0; put(0x0f); rio += 0x1e; perform(rio, rio, 1, 1, 0x80, 0); } void seta(void) { s(0x77); } void setae(void) { s(0x73); } void setb(void) { s(0x72); } void setbe(void) { s(0x76); } void sete(void) { s(0x74); } void setg(void) { s(0x7f); } void setge(void) { s(0x7d); } void setl(void) { s(0x7c); } void setle(void) { s(0x7e); } void setno(void) { s(0x71); } void setnp(void) { s(0x7b); } void setns(void) { s(0x79); } void setne(void) { s(0x75); } void seto(void) { s(0x70); } void setp(void) { s(0x7a); } void sets(void) { s(0x78); } void jump(char uhu) { long relative; signed short rel2; take1(); bwl(); if (pry1.etat < 4 || (uhu && pry1.etat > 5 && pry1.etat < 9)) { relative = pry1.offset - rpc; if (sizer == 'B') { nutsycat: relative -= 2; if (seg32 != 0) { relative--; } if (passe == PASS_LAST && (relative > 0x7a || relative < -0x7a)) { error("Byte jump out of range, try .W"); } if (relative == 0 && optimize != 0 && unresolvedlabel == 0) { if (isverbose && passe == PASS_LAST) { warning("Dummy jump replaced by nops"); } put(0x90); put(0x90); return; } if (seg32 != 0) { put(0x67); } put(0xeb); put(relative); } else if (sizer == 'W') { if (optimize != 0 && unresolvedlabel == 0) { if (relative <= 0x7a && relative >= -0x7a) /* $fd */ { if (isverbose && passe == PASS_LAST) { warning("Jump was made short"); } sizer = 'B'; goto nutsycat; } } relative -= 3; if (seg32 != 0) { relative--; } rel2 = (signed short) relative; if (passe == PASS_LAST && relative != rel2) { error("Word jump out of range, try .L"); } if (seg32 != 0) { put(0x67); } put(0xe9); wri(&rel2, 2); } else { relative -= 5; if (seg32 == 0) { put(0x67); relative--; } put(0xe9); wri(&relative, 4); } } else { colle(uhu, 0xc0, 1); } } void jmp(void) { jump(0); } void jmpz(void) { jump(1); } void jmpf(void) { collef(0, 0xea); } void jmpzf(void) { collef(1, 0xea); } void lahf(void) { put(0x9f); } void leave(void) { CPUCHECK(C186); put(0xc9); } void lods(void) { macadam(0xac); } void movs(void) { macadam(0xa4); } void scas(void) { macadam(0xae); } void outs(void) { CPUCHECK(C186); macadam(0x6e); } void stos(void) { macadam(0xaa); } void loupe(char pabo) { long relative; take1(); ware(); if (pry1.etat < 4 || pry1.etat == 6 || pry1.etat == 7 || pry1.etat == 8) { relative = pry1.offset - rpc - 2; if ((relative > 127 || relative < -128) && passe == PASS_LAST) { error("Loop too far"); } put(pabo); put(relative); } else { error("Short pointer expected"); } } void loop(void) { loupe(0xe2); } void loope(void) { loupe(0xe1); } void loopne(void) { loupe(0xe0); } void wbinvd(void) { CPUCHECK(C486); ware(); put(0x0f); put(0x09); } void gro(char sac) { char *vroum; CPUCHECK(C286); vroum = pnt; take2(); bwl(); if (sizer == 'B' || pry2.etat != 4) { error("Word or long register expected"); } if (pry1.etat < 4) { error("Can't load from a constant"); } pnt = vroum; hey(pry1); put(0x0f); perform(sac, sac, 1, 1, 0x80, 0); } void lar(void) { gro(-1); } void lsl(void) { gro(0); } void lds(void) { limit2(); perform(0xc2, 0xc2, 0, 0, 0x80, 0); } void les(void) { limit2(); perform(0xc1, 0xc1, 0, 0, 0x80, 0); } void lfs(void) { CPUCHECK(C386); limit2(); hey(pry1); put(0x0f); perform(0xb1, 0xb1, 1, 1, 0x80, 0); } void lgs(void) { CPUCHECK(C386); limit2(); hey(pry1); put(0x0f); perform(0xb2, 0xb2, 1, 1, 0x80, 0); } void lss(void) { CPUCHECK(C386); limit2(); hey(pry1); put(0x0f); perform(0xaf, 0xaf, 1, 1, 0x80, 0); } void lt(char c) { CPUCHECK(C286); take1(); ware(); sizer = 'W'; if (pry1.etat < 5) { error("64-bits pointer expected"); } hey(pry1); pry2.etat = 4; pry2.reg1 = 0; put(0x0f); perform(-2, -2, 1, 1, 0x80, c); } void lgdt(void) { lt(0x10); } void lidt(void) { lt(0x18); } void sgdt(void) { lt(0x00); } void sidt(void) { lt(0x08); } void ohoho(char tchac, char poum) { CPUCHECK(C286); take1(); ware(); sizer = 'W'; if (pry1.etat < 4) { error("16-bits pointer or register expected"); } hey(pry1); pry2.etat = 4; pry2.reg1 = 0; put(0x0f); perform(tchac, tchac, 1, 1, 0x80, poum); } void lldt(void) { ohoho(-3, 0x10); } void sldt(void) { ohoho(-3, 0x00); } void lmsw(void) { ohoho(-2, 0x30); } void smsw(void) { ohoho(-2, 0x20); } void ltr(void) { ohoho(-3, 0x18); } void verr(void) { ohoho(-3, 0x20); } void verw(void) { ohoho(-3, 0x28); } void str(void) { ohoho(-3, 0x08); } void mov(void) { signed short purelove; struct lotus coca; int lendemain; take2(); bwl(); if (pry1.etat < 4) { if (sizer == 'B') { if (pry1.etat != 1) { if (passe == PASS_LAST) { warning("Constant too large for a byte"); } pry1.etat = 1; pry1.offset &= 0xff; } } else if (sizer == 'W') { if (pry1.etat == 3) { if (passe == PASS_LAST) { warning("Constant too large for a word"); } pry1.offset &= 0xffff; } pry1.etat = 2; } else pry1.etat = 3; if (pry2.etat == 4) { switch (sizer) { case 'B' : if (pry2.reg1 >= 4 && pry2.reg1 < 12) pry2.reg1 -= 4; else if (pry2.reg1 >= 4) { error("Byte register expected"); } if (seg32 != 0) { put(0x66); } put(0xb0 + pry2.reg1); put(pry1.offset); break; case 'W' : if (pry2.reg1 >= 12 && pry2.reg1 < 20) pry2.reg1 -= 12; else if (pry2.reg1 >= 4) { error("Word register expected"); } if (seg32 != 0) { put(0x66); } put(0xb8 + pry2.reg1); purelove = (signed short) pry1.offset; tempete(pry1); wri(&purelove, 2); break; default : if (pry2.reg1 >= 20 && pry2.reg1 < 28) pry2.reg1 -= 20; else if (pry2.reg1 >= 4) { error("Long register expected"); } if (seg32 == 0) { put(0x66); } put(0xb8 + pry2.reg1); wri(&pry1.offset, 4); } } else perform(0x00, 0x00, 0, 1, 0xc6, 0); } else if (pry1.etat == 4 && (pry1.reg1 == 0 || pry1.reg1 == 4 || pry1.reg1 == 12 || pry1.reg1 == 20) && pry2.etat >= 6 && pry2.etat <= 8) /* a?,$xxx */ { switch (sizer) { case 'B' : if (seg32 != 0) { put(0x66); } if (pry2.etat == 8) { if (seg32 == 0) { put(0x67); } } else if (seg32 != 0) { put(0x67); } put(0xa2); if (pry2.etat == 8) { wri(&pry2.offset, 4); } else { wri(&pry2.offset, 2); } break; case 'W' : if (seg32 != 0) { put(0x66); } telephone: if (pry2.etat == 8) { if (seg32 == 0) { put(0x67); } } else if (seg32 != 0) { put(0x67); } put(0xa3); if (pry2.etat == 8) { wri(&pry2.offset, 4); } else { wri(&pry2.offset, 2); } break; default : if (seg32 == 0) { put(0x66); } goto telephone; } } else if (pry2.etat == 4 && (pry2.reg1 == 0 || pry2.reg1 == 4 || pry2.reg1 == 12 || pry2.reg1 == 20) && pry1.etat >= 6 && pry1.etat <= 8) /* $xxx,a? */ { switch (sizer) { case 'B' : if (seg32 != 0) { put(0x66); } if (pry1.etat == 8) { if (seg32 == 0) { put(0x67); } } else if (seg32 != 0) { put(0x67); } put(0xa0); if (pry1.etat == 8) { wri(&pry1.offset, 4); } else { wri(&pry1.offset, 2); } break; case 'W' : if (seg32 != 0) { put(0x66); } telephone2: if (pry1.etat == 8) { if (seg32 == 0) { put(0x67); } } else if (seg32 != 0) { put(0x67); } put(0xa1); if (pry1.etat == 8) { wri(&pry1.offset, 4); } else { wri(&pry1.offset, 2); } break; default : if (seg32 == 0) { put(0x66); } goto telephone2; } } else if (pry1.reg1 >=28 && pry1.reg1 < 34 && pry1.etat == 4) { if (sizer != 'W') { error("With a segment register, use MOV[E][.W]"); } pry1.reg1 -= 28; if (pry2.etat == 4) { if (pry2.reg1 >= 12 && pry2.reg1 < 20) pry2.reg1 -= 12; else if (pry2.reg1 >= 4) { error("Word register expected with a segment"); } if (seg32 != 0) { put(0x66); } put(0x8c); put(0xc0 + pry2.reg1 + (pry1.reg1 << 3)); } else { pry1.reg1 += 12; perform(0x8b, 0x8b, 0, 1, 0x80, 0); } } else if (pry2.reg1 >=28 && pry2.reg1 < 34 && pry2.etat == 4) { if (sizer != 'W') { error("With a segment register, use MOV[E][.W]"); } pry2.reg1 -= 28; if (pry1.etat == 4) { if (pry1.reg1 >= 12 && pry1.reg1 < 20) pry1.reg1 -= 12; else if (pry1.reg1 >= 4) { error("Word register expected with a segment"); } if (seg32 != 0) { put(0x66); } put(0x8e); put(0xc0 + pry1.reg1 + (pry2.reg1 << 3)); } else { pry2.reg1 += 12; perform(0x8b, 0x8b, 0, 1, 0x80, 0); } } else if (pry2.etat == 4 && pry2.reg1 >= 34) { coca = pry1; pry1 = pry2; pry2 = coca; lendemain = 2; goto toujours; } else if (pry1.etat == 4 && pry1.reg1 >= 34) { lendemain = 0; toujours: CPUCHECK(C286); if (sizer != 'L') { error("Use MOV[E].L with a control register"); } if (pry2.etat != 4) { error("Register expected"); } if (pry2.reg1 >= 20 && pry2.reg1 < 28) pry2.reg1 -= 20; else if (pry2.reg1 >= 4) { error("32-bits register expected"); } put(0x0f); if (pry1.reg1 < 37) { put(0x20 + lendemain); switch (pry1.reg1) { case 34 : put(0xc0 + pry2.reg1); break; case 35 : put(0xd0 + pry2.reg1); break; default : put(0xd8 + pry2.reg1); } } else if (pry1.reg1 < 43) { put(0x21 + lendemain); switch (pry1.reg1) { case 37 : case 38 : case 39 : case 40 : put(0xc0 + pry2.reg1 + ((pry1.reg1 - 37) << 3)); break; default : put(0xc0 + pry2.reg1 + ((pry1.reg1 - 35) << 3)); } } else { put(0x24 + lendemain); put(0xd8 + pry2.reg1 + ((pry1.reg1 - 43) << 3)); } } else { perform(0x88, 0x88, 0, 1, 0x80, 0); } } void movx(char tsoin) { CPUCHECK(C386); limit(); if (sizer == 'W') { if (pry1.etat == 4) { if (pry1.reg1 >= 4 && pry1.reg1 < 12) pry1.reg1 += 8; else if (pry1.reg1 >= 4) { error("First argument must be a byte register"); } } } else { if (pry1.etat == 4) { if (pry1.reg1 >= 4 && pry1.reg1 < 12) pry1.reg1 += 16; else if (pry1.reg1 >= 12 && pry1.reg1 < 20) { pry1.reg1 += 8; tsoin++; } else if (pry1.reg1 >= 4) { error("First argument must be a byte or word register"); } } } hey(pry1); put(0x0f); perform(tsoin, tsoin, 1, 1, 0x80, 0); } void movsx(void) { movx(0xbb); } void movzx(void) { movx(0xb3); } void mol(char iowa) { take1(); bwl(); if (pry1.etat < 4) { error("Can't deal with immediate values"); } pry2.etat = 4; pry2.reg1 = 0; perform(0xf4, 0xf4, 0, 1, 0x80, iowa); } void mul(void) { mol(0x20); } void neg(void) { mol(0x18); } void not(void) { mol(0x10); } void or(void) { perform(0x08, 0x08, 0, 0, 0x80, 0); } void pop(void) { take1(); bwl(); if (sizer == 'B') { error("Can't work on bytes"); } if (pry1.etat < 4) { error("Can't POP a constant"); } else if (pry1.etat == 4) { if (sizer == 'W') { if (pry1.reg1 >= 28 && pry1.reg1 < 34) { switch(pry1.reg1) { case 28 : put(0x07); break; case 29 : error("Can't POP CS"); case 30 : put(0x17); break; case 31 : put(0x1f); break; case 32 : put(0x0f); put(0xa1); break; default : put(0x0f); put(0xa9); } return; } if (pry1.reg1 >= 12 && pry1.reg1 < 20) pry1.reg1 -= 12; else if (pry1.reg1 >= 4) { wakeup: error("Incorrect register size"); } if (seg32 != 0) { put(0x66); } } else { if (pry1.reg1 >= 20 && pry1.reg1 < 28) pry1.reg1 -= 20; else if (pry1.reg1 >= 4) goto wakeup; if (seg32 == 0) { put(0x66); } } put(0x58 + pry1.reg1); } else { pry2.etat = 4; pry2.reg1 = 0; perform(0x8c, 0x8c, 0, 1, 0x80, 0); } } void popa(void) { if (sizer == 'B' || sizer == 'S') { error("Can't pop 8-bits parts"); } else if (sizer == 'L') { CPUCHECK(C386); if (seg32 == 0) { put(0x66); } } else { CPUCHECK(C386); } put(0x61); } void popf(void) { if (sizer == 'B' || sizer == 'S') { error("FLAG is a 16 or 32 bits register"); } else if (sizer == 'L') { CPUCHECK(C386); if (seg32 == 0) { put(0x66); } } put(0x9d); } void push(void) { take1(); bwl(); if (pry1.etat < 4) { if (sizer == 'B') { if (seg32 != 0) { put(0x66); } put(0x6a); if (pry1.offset > 255 && passe == PASS_LAST) { warning("Pushed immediate too large for a byte"); } put(pry1.offset); } else if (sizer == 'W') { if (seg32 != 0) { put(0x66); } put(0x68); if (pry1.offset > 65535 && passe == PASS_LAST) { warning("Pushed immediate too large for a word"); } wri(&pry1.offset, 2); } else if (passe == PASS_LAST) { if (seg32 == 0) { put(0x66); } put(0x68); wri(&pry1.offset, 4); } return; } if (sizer == 'B') { error("Can't work on bytes"); } else if (pry1.etat == 4) { if (sizer == 'W') { if (pry1.reg1 >= 28 && pry1.reg1 < 34) { switch(pry1.reg1) { case 28 : put(0x06); break; case 29 : put(0x0e); break; case 30 : put(0x16); break; case 31 : put(0x1e); break; case 32 : put(0x0f); put(0xa0); break; default : put(0x0f); put(0xa8); } return; } if (pry1.reg1 >= 12 && pry1.reg1 < 20) pry1.reg1 -= 12; else if (pry1.reg1 >= 4) { wakeup: error("Incorrect register size"); } if (seg32 != 0) { put(0x66); } } else { if (pry1.reg1 >= 20 && pry1.reg1 < 28) pry1.reg1 -= 20; else if (pry1.reg1 >= 4) goto wakeup; if (seg32 == 0) { put(0x66); } } put(0x50 + pry1.reg1); } else { pry2.etat = 4; pry2.reg1 = 0; perform(0xfc, 0xfc, 0, 1, 0x80, 0x30); } } void pusha(void) { if (sizer == 'B' || sizer == 'S') { error("Can't push 8-bits parts"); } else if (sizer == 'L') { CPUCHECK(C386); if (seg32 == 0) { put(0x66); } } else { CPUCHECK(C186); } put(0x60); } void pushf(void) { if (sizer == 'B' || sizer == 'S') { error("FLAG is a 16 or 32 bits register"); } else if (sizer == 'L') { CPUCHECK(C386); if (seg32 == 0) { put(0x66); } } put(0x9c); } void stayfresh(char kinky) { take2(); bwl(); if (pry2.etat == 4) { if (sizer == 'B') { if (pry2.reg1 >= 4 && pry2.reg1 < 12) pry2.reg1 -= 4; else if (pry2.reg1 >= 4) { error("Byte register expected"); } } else if (sizer == 'W') { if (pry2.reg1 >= 12 && pry2.reg1 < 20) pry2.reg1 -= 12; else if (pry2.reg1 >= 4) { error("Word register expected"); } } else { if (pry2.reg1 >=20 && pry2.reg1 < 28) pry2.reg1 -= 20; else if (pry2.reg1 >= 4) { error("Long register expected"); } } if (pry1.etat == 4) { if (pry1.reg1 == 1 || pry1.reg1 == 5) { macadam(0xd2); put(0xc0 + pry2.reg1 + kinky); } else { error("Only CL would work as counter"); } } else if (pry1.etat != 1) { error("Byte constant or C expected as count index"); } else if (pry1.offset == 1) { macadam(0xd0); put(0xc0 + pry2.reg1 + kinky); } else { macadam(0xc0); put(0xc0 + pry2.reg1 + kinky); put(pry1.offset); } } else if (pry2.etat < 4) { error("Can't modify a constant"); } else { if (pry1.etat == 4) { if (pry1.reg1 == 1 || pry1.reg1 == 5) { pry1.etat = 4; pry1.reg1 = 0; perform(0xd2, 0xd2, 0, 1, 0x80, kinky); } else { error("Only CL would work as counter"); } } else if (pry1.etat != 1) { error("Byte constant or C expected as count index"); } else if (pry1.offset == 1) { pry1.etat = 4; pry1.reg1 = 0; perform(0xd0, 0xd0, 0, 1, 0x80, kinky); } else perform(kinky, kinky, 0, 1, (sizer == 'B') ? 0xc0 : 0xbe, kinky); } } void rol(void) { stayfresh(0x00); } void ror(void) { stayfresh(0x08); } void rcl(void) { stayfresh(0x10); } void rcr(void) { stayfresh(0x18); } void shl(void) { stayfresh(0x20); } void shr(void) { stayfresh(0x28); } void sar(void) { stayfresh(0x38); } void sahf(void) { ware(); put(0x9e); } void shiftd(char addon) { struct lotus coca; char auphset = 0; CPUCHECK(C386); bwl(); if (sizer == 'B') { error("SHLD/SHRD can't deal with byte registers"); } if ((pnt = nextarg(pnt)) == NULL) { error("Syntax is SHLD/SHRD [CL|#] "); } coca = getadrs(pnt); if (coca.etat == 2 || coca.etat == 3) { warning("Constant converted to an unsigned 8-bit type"); auphset = (unsigned char) coca.offset; } else if (coca.etat == 1) { auphset = coca.offset; } else if (coca.etat == 4) { if (coca.reg1 == 5) { coca.reg1 = 1; } else if (coca.reg1 != 1) { error("Shift register must be CL"); } } else { error("Syntax is SHLD/SHRD [CL|#] "); } if ((pnt = nextcoma(pnt)) == NULL) { error("SHLD/SHRD need three arguments"); } pnt = skipspace(pnt); pry2 = getadrs(pnt); if (pry2.etat != 4) { error("Register awaited as source value"); } if (pry2.reg1 >= 12 && pry2.reg1 < 20) { if (sizer != 'W') { error("Incoherent instruction (L) and source (W) sizes"); } pry2.reg1 -= 12; } else if (pry2.reg1 >= 20 && pry2.reg1 < 28) { if (sizer != 'L') { error("Incoherent instruction (W) and source (L) sizes"); } pry2.reg1 -= 20; } else if (pry2.reg1 >= 4) { error("Second argument (source) must be a register"); } if ((pnt = nextcoma(pnt)) == NULL) { error("Third argument (target) awaited with SHLD/SHRD"); } pnt = skipspace(pnt); pry1 = getadrs(pnt); if (pry1.etat < 4) { error("Last argument is the target one, not an immediate"); } hey(pry1); put(0x0f); if (coca.etat == 4) { perform(addon + 1, addon + 1, 1, 1, 0x80, 0); } else { perform(addon, addon, 1, 1, 0x80, 0); put(auphset); } } void shld(void) { shiftd(0xa1); } void shrd(void) { shiftd(0xa9); } void xchg(void) { struct lotus vain; take2(); if (pry1.etat < 4) { error("Can't swap a constant"); } else if (pry1.etat == 4) { vain = pry1; pry1 = pry2; pry2 = vain; } perform(0x84, 0x84, 0, 1, 0x80, 0); } void xlat(void) { ware(); put(0xd7); } void stack(void) { if (stk && passe == PASS_BRIEF) { error("Redefinition of STACK"); } stk = rpc; } void header(void) { long savepcwoalign = pcwoalign; ware(); if (passe == PASS_LAST) { long kedal = 0, total; short kala; long th = 0; char *pub = " Assembled with GEMA "; /* 21+1 */ char *csa; int pouf; th = (relocpnt << 2) + 50; while(th & 0x0f) { th++; } put(0x4d); put(0x5a); total = taille + th; kala = total & 0x1ff; wri(&kala, 2); if (kala) { kala = (total >> 9) + 1; } else { kala = total >> 9; } wri(&kala, 2); wri(&relocpnt, 2); kala = th >> 4; wri(&kala, 2); wri(&lowlim, 2); wri(&lim, 2); kala = (stk & ~0xffff) >> 4; wri(&kala, 2); kala = stk & 0xffff; wri(&kala, 2); wri(&kedal, 2); kala = rpc & 0xffff; wri(&kala, 2); kala = (rpc & ~0xffff) >> 4; wri(&kala, 2); put(50); put(0); wri(&ovrlay, 2); for (csa = pub; csa < pub + 22; csa += 2) { wri(csa, 2); } for (pouf = 0; pouf < relocpnt; pouf++) { kala = reloc[pouf] & 0xffff; wri(&kala, 2); kala = (reloc[pouf] & ~0xffff) >> 4; wri(&kala, 2); } while(pc & 0x0f) { put(0); } pc = rpc; relocpnt = 0; } exe = 1; pcwoalign = savepcwoalign; } void limite(void) { ware(); if (lim != 0xffff && passe == PASS_BRIEF) { error("Max size redefinition"); } if ((pnt = nextarg(pnt)) == NULL) { error("LIMIT needs one argument"); } lim = val(pnt); ccheck(); } void mini(void) { ware(); if (lowlim && passe == PASS_BRIEF) { error("Min size redefinition"); } if ((pnt = nextarg(pnt)) == NULL) { error("MINI needs one argument"); } lowlim = val(pnt); ccheck(); } void overlay(void) { ware(); if (ovrlay && passe == PASS_BRIEF) { error("Redefinition of overlay ID"); } if ((pnt = nextarg(pnt)) == NULL) { error("OVERLAY needs one argument"); } ovrlay = val(pnt); ccheck(); } void column(void) { if (*(pnt = skipspace(pnt)) == ':') { pnt++; soundgarden(); } } void real(void) { ware(); maxsegsize = maxsegcounter = 65536; ccheck(); column(); } void unreal(void) { ware(); maxsegsize = maxsegcounter = -1; ccheck(); column(); } void segsize(void) { ware(); if ((pnt = nextarg(pnt)) == NULL) { error("SEGSIZE expects a segment size"); } maxsegsize = maxsegcounter = val(pnt); if (maxsegsize < 0 && nowarning == 0) { checkquiet(); fprintf(stderr, "WARNING : Negative segment size at line %ld - No more check for that segment\n", pl); maxsegsize = -1; } else if (maxsegsize == 0 && nowarning == 0) { checkquiet(); fprintf(stderr, "WARNING : Null segment size at line %ld - No more limit in that segment\n", pl); maxsegsize = -1; } else if (maxsegsize == 1 && nowarning == 0) { checkquiet(); fprintf(stderr, "WARNING : Declaring a single-byte segment at line %ld\n", pl); } ccheck(); column(); } void bss(void) { bssflag = 1; } void text(void) { bssflag = 0; } void use32(void) { CPUCHECK(C386); seg32 = 1; } void use16(void) { seg32 = 0; } void objheader(void) { long savepcwoalign = pcwoalign; size_t sfnl = strlen(sourcefile); long taillework = battletech + 4; long taillework2 = battletech; ware(); if (passe == PASS_LAST) { /* $80 - Title */ put(0x80); put(sfnl + 2); put(0); put(sfnl); wri(sourcefile, sfnl); put(0); /* $96 - LNames */ put(0x96); put(2); put(0); put(0); put(0); /* $88 - Comment */ put(0x88); put(3); put(0); put(0x40); put(0xa1); put(0); /* $96 - LNames */ put(0x96); put(12); put(0); put(5); put(0x5f); put(0x54); put(0x45); put(0x58); put(0x54); put(0x04); put(0x43); put(0x4f); put(0x44); put(0x45); put(0); /* $98 - Segment */ put(0x98); put(7); put(0); put(0xa9); /* Bizness' size */ fsh(); polter1 = ftell(popol); put(taillework2 & 0xff); put(taillework2 / 256); put(2); put(3); put(1); put(0); /* $96 - LNames */ put(0x96); put(12); put(0); put(5); put(0x5f); put(0x44); put(0x41); put(0x54); put(0x41); put(4); put(0x44); put(0x41); put(0x54); put(0x41); put(0); /* $98 - Segment */ put(0x98); put(7); put(0); put(0xa9); put(0); put(0); put(4); put(5); put(1); put(0); /* $96 - Putain encore un LNames de daube */ put(0x96); put(6); put(0); put(4); put(0x46); put(0x4c); put(0x41); put(0x54); put(0); /* $9a - ? */ put(0x9a); put(2); put(0); put(6); put(0); /* $96 - LNames */ put(0x96); put(8); put(0); put(6); put(0x44); put(0x47); put(0x52); put(0x4f); put(0x55); put(0x50); put(0); /* $9a - ? */ put(0x9a); put(4); put(0); put(7); put(0xff); put(2); put(0); /* $88 - ? */ put(0x88); put(4); put(0); put(0x40); put(0xa2); put(1); put(0); /* $a0 - Enfin le segment de code */ put(0xa0); /* Len! */ fsh(); polter2 = ftell(popol); put(taillework & 0xff); put(taillework / 256); put(1); put(orgvalue & 0xff); put(orgvalue / 256); } battletech = pc; pcwoalign = savepcwoalign; exe = 1; } void ohnomoreshits(void) { long pwmal; long taillework; long taillework2; long savepcwoalign = pcwoalign; /* printf("Real len = [%ld] Expected len = [%ld]\n", pc - battletech, taille); */ battletech = pc - battletech; taillework = battletech + 4; taillework2 = battletech; if (passe != PASS_LAST) { pcwoalign = savepcwoalign; return; } put(0); put(0x8a); put(2); put(0); put(0); put(0); fsh(); pwmal = ftell(popol); fseek(popol, polter1, SEEK_SET); fputc(taillework2 & 0xff, popol); fputc(taillework2 / 256, popol); fseek(popol, polter2, SEEK_SET); fputc(taillework & 0xff, popol); fputc(taillework / 256, popol); fseek(popol, pwmal, SEEK_SET); pcwoalign = savepcwoalign; } void heading(void) { if (isobject != 0) { objheader(); } else { header(); } }