/* asmutil2.cpp , @CopyLeft by tsaiwn@csie.nctu.edu.tw * g++ -c asmutil2.cpp * utility routines to write out the object file records * 因為此程式使用 default parameter, 是 C++ 的功能, 可用 g++ 編譯 * 在 Turbo C++ 則把名稱取為 *.cpp 便會當作 C++ 看待(否則要用選項指定) * 如果堅持要當作純 C 程式, 則不能使用 default parameter 功能 * (就是要把參數中像 =0 這種式子去掉) * 當然, 如果 C++ 要與 C 混著用就要 extern "C" { ... } * 還有: 1. 這些 routines 並不是一定要這樣寫 2. 注意 wrec( ) 中的 nbyte 和 len 算法 (配合課本) 3. 各 functions 沒有check 是否有先叫用 wopen 打開 object file ? */ /* 若是堅持要純種 C, 則不要使用 default parameter 功能 */ /*** *** 注意 C++ 有 function name overloading *** ***/ /////////////////////////////////////////////////////////////// #include #include #include #include static FILE* fpObjFile=0; /* file pointer for Obj file */ static char fileNameObj[80]; static char defaultObjName[80] = "a-obj.text"; static char buf[99]; /* buffer to be written out to Object file */ static int nbyte = 0; /* 記住 buffer 中有幾個 bytes */ static long start0; /* 記住 H record 的程式起點 address */ static long pcNow = 0; /* 記住 Object file 目前 record 的開始 PC */ /*** *** 注意 C++ 有 function name overloading *** ***/ ///////////////////////////////////////////////////////// FILE* wopen(char* objFile) { fpObjFile = fopen(objFile, "wt"); /* 注意真的assembler是寫 binary Obj File*/ nbyte =0; strcpy((char*)fileNameObj, objFile); /* save the filename for obj file*/ return fpObjFile; } int wrecln(){ /* Write REC LiNe */ int nwritten = nbyte; /* 寫出幾個 byte */ if(fpObjFile==0) { fpObjFile=fopen(defaultObjName,"at"); /* append */ strcpy(fileNameObj, defaultObjName); } if(nbyte){ /* nbyte 不為 0, 須清掉 buffer */ buf[nbyte] = 0; /* ensure the string is NULL-terminated */ fprintf(fpObjFile, "%s", buf); nbyte = 0; } fprintf(fpObjFile, "\n"); /* 只有這裡會寫出 newLine */ return nwritten; /* Note here */ } int wrec(char*tmps, long pc) { /* 先用 sprintf()或用土方法把 tmps 準備好, 再叫用 wrec( ) */ int len, nwritten = 0; static long pcPrevious=0; char tmpxx[5]; if(nbyte > 60){ /* 一定是 T record :-) */ len = nbyte - 9; len /= 2; /* 每 2 個 nibble 是一個 byte */ /*接著要把此 T record 機器碼的長度(byte)數寫在 T 位址欄 之後面 */ sprintf(tmpxx, "%2.2X", len); /* 準備好 16 進位值 */ buf[7] = tmpxx[0]; buf[8] = tmpxx[1]; /* this T record length */ buf[nbyte] = 0; /* terminate string */ nwritten = nbyte; /* 先記住有幾個 byte 寫出去 */ wrecln(); /* flush out the buffer followed by a newLine */ /* prepare a new T record now */ nbyte = 9; pcPrevious = pcNow; pcNow += len; /* advance len location */ if(pc) pcNow = pc; /* 若 pc 不是 0 則用傳入的 pc 值 */ sprintf(buf, "T%6.6X00", pcNow); /* 準備好 T record 到 buf[] */ } while(*tmps){ buf[nbyte++] = *tmps; /* 逐 byte 塞入 buf[] 中 */ ++tmps; } return nwritten; /* how many bytes 實際有寫出去的 byte */ } int wtrec(char* tmps, long pc){ /* 呼叫 wrec 寫出 T record */ if(nbyte == 0) { /* 第一次 */ sprintf(buf, "T%6.6X00", pc); /* 準備好 T record */ pcNow = pc; nbyte = 9; } return wrec(tmps, pc); /* 不是第一次 */ } int whrec(char* name, long start, long length) { int nwritten; /* 寫出幾個 byte */ static char tmpbuf[80]; if(nbyte) wrecln(); /* flush out the buffer */ if(fpObjFile==0) { fpObjFile=fopen(defaultObjName,"at"); /* append */ strcpy(fileNameObj, defaultObjName); } start0 = start; sprintf(tmpbuf, "H%-6.6s%6.6X%6.6X", name, start, length); nwritten=strlen(tmpbuf); /* 19 */ wrec(tmpbuf, 0); wrecln(); /* flush out immediately */ /* H record 獨立, 所以寫出去 */ return nwritten; } int werec(long pc) { /* 寫出 E record, if pc == -1 means this E record has no address */ /* 如果還有未寫出的 T record 則須先寫出去 ! */ int nwritten = nbyte; if(pc == 0) pc = start0; /* default: the address in H record */ if(nbyte){ /* 清掉 buffer */ buf[nbyte] = 0; /* terminate string */ wrecln(); /* flush with a newLine */ } buf[0] = 'E'; if(pc == -1) { /* 只有 "E" 的 E record */ ++nwritten; nbyte = 1; }else{ pc = start0; /* default: the address in H record */ sprintf(buf, "E%6.6X", pc); nwritten += 7; nbyte = 7; } wrecln(); nbyte = 0; /* clear buffer */ return nwritten; /* bytes written this time */ } int wclose(){ long ans; if(nbyte) wrecln(); /* 清掉 buffer */ fseek(fpObjFile, 0L, SEEK_SET); /* 捲到 file 的最後 */ ans = ftell(fpObjFile); /* 取得此 file 的 size */ fclose(fpObjFile); fprintf(stderr, "Total %ld bytes written into %s\n", ans, fileNameObj); return ans; }