disassem.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799
  1. /****************************************************************************
  2. * dcc project disassembler
  3. * (C) Cristina Cifuentes, Mike van Emmerik, Jeff Ledermann
  4. ****************************************************************************/
  5. #include <stdint.h>
  6. #include "dcc.h"
  7. #include "symtab.h"
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <malloc.h> /* For free() */
  11. #include <vector>
  12. #include <sstream>
  13. #include <iomanip>
  14. #ifdef _CONSOLE
  15. #include <windows.h> /* For console mode routines */
  16. #endif
  17. #include "disassem.h"
  18. // Note: for the time being, there is no interactive disassembler
  19. // for unix
  20. #ifndef __UNIX__
  21. #include <conio.h> // getch() etc
  22. #endif
  23. using namespace std;
  24. #define POS_LAB 15 /* Position of label */
  25. #define POS_OPC 20 /* Position of opcode */
  26. #define POS_OPR 25 /* Position of operand */
  27. #define WID_PTR 10 /* Width of the "xword ptr" lingo */
  28. #define POS_OPR2 POS_OPR+WID_PTR /* Position of operand after "xword ptr" */
  29. #define POS_CMT 54 /* Position of comment */
  30. #define DELTA_ICODE 16 /* Number of icodes to realloc by each time */
  31. static const char *szOps[] =
  32. {
  33. "CBW", "AAA", "AAD", "AAM", "AAS", "ADC", "ADD", "AND",
  34. "BOUND","CALL", "CALL", "CLC", "CLD", "CLI", "CMC", "CMP",
  35. "CMPS", "REPNE CMPS","REPE CMPS","DAA", "DAS", "DEC", "DIV", "ENTER",
  36. "ESC", "HLT", "IDIV", "IMUL", "IN", "INC", "INS", "REP INS",
  37. "INT", "IRET", "JB", "JBE", "JAE", "JA", "JE", "JNE",
  38. "JL", "JGE", "JLE", "JG", "JS", "JNS", "JO", "JNO",
  39. "JP", "JNP", "JCXZ", "JMP", "JMP", "LAHF", "LDS", "LEA",
  40. "LEAVE","LES", "LOCK", "LODS", "REP LODS", "LOOP", "LOOPE","LOOPNE",
  41. "MOV", "MOVS", "REP MOVS", "MUL", "NEG", "NOT", "OR", "OUT",
  42. "OUTS", "REP OUTS", "POP", "POPA", "POPF", "PUSH", "PUSHA","PUSHF",
  43. "RCL", "RCR", "ROL", "ROR", "RET", "RETF", "SAHF", "SAR",
  44. "SHL", "SHR", "SBB", "SCAS", "REPNE SCAS","REPE SCAS", "CWD", "STC",
  45. "STD", "STI", "STOS", "REP STOS", "SUB", "TEST", "WAIT", "XCHG",
  46. "XLAT", "XOR", "INTO", "NOP", "REPNE", "REPE", "MOD"
  47. };
  48. /* The following opcodes are for mod != 3 */
  49. static const char *szFlops1[] =
  50. {
  51. /* 0 1 2 3 4 5 6 7 */
  52. "FADD", "FMUL", "FCOM", "FCOMP", "FSUB", "FSUBR", "FDIV", "FDIVR", /* 00 */
  53. "FLD", "???", "FST", "???", "FLDENV","FLDCW", "FSTENV","FSTSW", /* 08 */
  54. "FIADD", "FIMUL", "FICOM","FICOMP","FISUB", "FISUBR","FIDIV", "FIDIVR", /* 10 */
  55. "FILD", "???", "FIST", "FISTP", "???", "???", "???", "FSTP", /* 18 */
  56. "FADD", "FMUL", "FCOM", "FCOMP", "FSUB", "FSUBR", "FDIV", "FDIVR", /* 20 */
  57. "FLD", "FLD", "FST", "FSTP", "FRESTOR","???", "FSAVE", "FSTSW", /* 28 */
  58. "FIADD", "FIMUL", "FICOM","FICOMP","FISUB", "FISUBR","FIDIV", "FIDIVR", /* 30 */
  59. "FILD", "???", "FIST", "FISTP", "FBLD", "???", "FBSTP", "FISTP" /* 38 */
  60. };
  61. /* The following opcodes are for mod == 3 */
  62. static const char *szFlops2[] =
  63. {
  64. /* 0 1 2 3 4 5 6 7 */
  65. "FADD", "FMUL", "FCOM", "FCOMP", "FSUB", "FSUBR", "FDIV", "FDIVR", /* 00 */
  66. "FLD", "FXCH", "FNOP", "???", "", "", "", "", /* 08 */
  67. "FIADD", "FIMUL", "FICOM","FICOMP","FISUB", "", "FIDIV", "FIDIVR", /* 10 */
  68. "FILD", "???", "FIST", "FISTP", "???", "???", "???", "FSTP", /* 18 */
  69. "FADD", "FMUL", "FCOM", "FCOMP", "FSUB", "FSUBR", "FDIV", "FDIVR", /* 20 */
  70. "FFREE", "FSTP", "FST", "???", "FUCOM", "FUCOMP","???", "???", /* 28 */
  71. "FADDP", "FMULP", "FICOM","", "FSUBRP","FISUBR","FDIVRP","FDIVP", /* 30 */
  72. "FILD", "???", "FIST", "FISTP", "", "???", "FBSTP", "FISTP" /* 38 */
  73. };
  74. static const char *szFlops0C[] =
  75. {
  76. "FCHS", "FABS", "???", "???", "FTST", "FXAM", "???", "???"
  77. };
  78. static const char *szFlops0D[] =
  79. {
  80. "FLD1", "FLDL2T","FLDL2E","FLDP1", "FLDLG2","FLDLN2","FLDZ", "???"
  81. };
  82. static const char *szFlops0E[] =
  83. {
  84. "F2XM1", "FYL2X", "FPTAN", "FPATAN","FXTRACT","FPREM1","FDECSTP","FINCSTP"
  85. };
  86. static const char *szFlops0F[] =
  87. {
  88. "FPREM", "FYLXP1","FSQRT", "FSINCOS","FRNDINT","FSCALE","FSIN","FCOS"
  89. };
  90. static const char *szFlops15[] =
  91. {
  92. "???", "FUCOMPP", "???", "???", "???", "???", "???", "???"
  93. };
  94. static const char *szFlops1C[] =
  95. {
  96. "???", "???", "FCLEX", "FINIT", "FTST", "FXAM", "???", "???"
  97. };
  98. static const char *szFlops33[] =
  99. {
  100. "???", "FCOMPP", "???", "???", "???", "???", "???", "???"
  101. };
  102. static const char *szFlops3C[] =
  103. {
  104. "FSTSWAX","???", "???", "???", "???", "???", "???", "???"
  105. };
  106. static const char *szIndex[8] = {"bx+si", "bx+di", "bp+si", "bp+di", "si", "di","bp","bx" };
  107. static const char *szBreg[8] = { "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh" };
  108. static const char *szWreg[12] = { "ax", "cx", "dx", "bx", "sp", "bp", "si", "di",
  109. "es", "cs", "ss", "ds" };
  110. static const char *szPtr[2] = { "word ptr ", "byte ptr " };
  111. static void dis1Line (Int i, Int pass);
  112. void dis1LineOp(Int i, boolT fWin, char attr, word *len, Function * pProc);
  113. static void formatRM(ostringstream &p, flags32 flg, LLOperand *pm);
  114. static ostringstream &strDst(ostringstream &os, flags32 flg, LLOperand *pm);
  115. static ostringstream &strSrc(ostringstream &os, ICODE *pc, bool skip_comma=false);
  116. static char *strHex(dword d);
  117. static Int checkScanned(dword pcCur);
  118. static void setProc(Function * proc);
  119. static void dispData(word dataSeg);
  120. void flops(ICODE *pIcode,std::ostringstream &out);
  121. boolT callArg(word off, char *temp); /* Check for procedure name */
  122. static FILE *fp;
  123. static CIcodeRec pc;
  124. static std::ostringstream buf;
  125. static Int cb, j, numIcode, allocIcode, eop;
  126. static vector<int> pl;
  127. static dword nextInst;
  128. static boolT fImpure;
  129. static Int lab, prevPass;
  130. static Function * pProc; /* Points to current proc struct */
  131. struct POSSTACK_ENTRY
  132. {
  133. Int ic; /* An icode offset */
  134. Function * pProc; /* A pointer to a PROCEDURE structure */
  135. } ;
  136. vector<POSSTACK_ENTRY> posStack; /* position stack */
  137. byte iPS; /* Index into the stack */
  138. //static char cbuf[256]; /* Has to be 256 for wgetstr() to work */
  139. // These are "curses equivalent" functions. (Used to use curses for all this,
  140. // but it was too much of a distribution hassle
  141. #define printfd(x) printf(x)
  142. #define dis_newline() printf("\n")
  143. #define dis_show() // Nothing to do unless using Curses
  144. /*****************************************************************************
  145. * disassem - Prints a disassembled listing of a procedure.
  146. * pass == 1 generates output on file .a1
  147. * pass == 2 generates output on file .a2
  148. * pass == 3 generates output on file .b
  149. ****************************************************************************/
  150. void disassem(Int pass, Function * ppProc)
  151. {
  152. Int i;
  153. pProc = ppProc; /* Save the passes pProc */
  154. if (pass != prevPass)
  155. {
  156. prevPass = pass;
  157. lab = 0; /* Restart label numbers */
  158. }
  159. createSymTables();
  160. allocIcode = numIcode = pProc->Icode.size();
  161. cb = allocIcode * sizeof(ICODE);
  162. if (numIcode == 0)
  163. {
  164. return; /* No Icode */
  165. }
  166. /* Open the output file (.a1 or .a2 only) */
  167. if (pass != 3)
  168. {
  169. auto p = (pass == 1)? asm1_name: asm2_name;
  170. fp = fopen(p, "a+");
  171. if (!fp)
  172. {
  173. fatalError(CANNOT_OPEN, p);
  174. }
  175. }
  176. pc=pProc->Icode;
  177. /* Create temporary code array */
  178. // Mike: needs objectising!
  179. //pc = (ICODE *)memcpy(allocMem(cb), pProc->Icode.GetFirstIcode(), (size_t)cb);
  180. if (pass == 1)
  181. {
  182. /* Bind jump offsets to labels */
  183. for (i = 0; i < numIcode; i++)
  184. {
  185. if ((pc[i].ic.ll.flg & I) && !(pc[i].ic.ll.flg & JMP_ICODE) &&
  186. JmpInst(pc[i].ic.ll.opcode))
  187. {
  188. /* Replace the immediate operand with an icode index */
  189. dword labTgt;
  190. if (pc.labelSrch(pc[i].ic.ll.src.op(),labTgt))
  191. {
  192. pc[i].ic.ll.src.SetImmediateOp(labTgt);
  193. /* This icode is the target of a jump */
  194. pc[labTgt].ic.ll.flg |= TARGET;
  195. pc[i].ic.ll.flg |= JMP_ICODE; /* So its not done twice */
  196. }
  197. else
  198. {
  199. /* This jump cannot be linked to a label */
  200. pc[i].ic.ll.flg |= NO_LABEL;
  201. }
  202. }
  203. }
  204. }
  205. /* Create label array to keep track of location => label name */
  206. pl.clear();
  207. pl.resize(numIcode,0);
  208. /* Write procedure header */
  209. if (pass != 3)
  210. fprintf(fp, "\t\t%s PROC %s\n", pProc->name.c_str(), (pProc->flg & PROC_FAR)? "FAR": "NEAR");
  211. /* Loop over array printing each record */
  212. for (i = nextInst = 0; i < numIcode; i++)
  213. {
  214. dis1Line(i, pass);
  215. }
  216. /* Write procedure epilogue */
  217. if (pass != 3)
  218. {
  219. fprintf(fp, "\n\t\t%s ENDP\n\n", pProc->name.c_str());
  220. fclose(fp);
  221. }
  222. pc.clear();
  223. destroySymTables();
  224. }
  225. /****************************************************************************
  226. * dis1Line() - disassemble one line to stream fp * *
  227. * i is index into Icode for this proc *
  228. * It is assumed that icode i is already scanned *
  229. ****************************************************************************/
  230. static void dis1Line(Int i, Int pass)
  231. {
  232. ostringstream oper_stream;
  233. ostringstream hex_bytes;
  234. ostringstream result_stream;
  235. ICODE * pIcode = &pc[i];
  236. oper_stream << uppercase;
  237. hex_bytes << uppercase;
  238. /* Disassembly stage 1 --
  239. * Do not try to display NO_CODE entries or synthetic instructions,
  240. * other than JMPs, that have been introduced for def/use analysis. */
  241. if ((option.asm1) &&
  242. ((pIcode->ic.ll.flg & NO_CODE) ||
  243. ((pIcode->ic.ll.flg & SYNTHETIC) && (pIcode->ic.ll.opcode != iJMP))))
  244. {
  245. return;
  246. }
  247. else if (pIcode->ic.ll.flg & NO_CODE)
  248. {
  249. return;
  250. }
  251. if (pIcode->ic.ll.flg & (TARGET | CASE))
  252. {
  253. if (pass == 3)
  254. cCode.appendCode("\n"); /* Print to c code buffer */
  255. else
  256. fprintf(fp, "\n"); /* No, print to the stream */
  257. }
  258. /* Find next instruction label and print hex bytes */
  259. if (pIcode->ic.ll.flg & SYNTHETIC)
  260. nextInst = pIcode->ic.ll.label;
  261. else
  262. {
  263. cb = (dword) pIcode->ic.ll.numBytes;
  264. nextInst = pIcode->ic.ll.label + cb;
  265. /* Output hexa code in program image */
  266. if (pass != 3)
  267. {
  268. for (j = 0; j < cb; j++)
  269. {
  270. hex_bytes << hex << setw(2) << setfill('0') << uint16_t(prog.Image[pIcode->ic.ll.label + j]);
  271. }
  272. hex_bytes << ' ';
  273. }
  274. }
  275. oper_stream << setw(POS_LAB) << left<< hex_bytes.str();
  276. /* Check if there is a symbol here */
  277. selectTable(Label);
  278. oper_stream << setw(5)<<left; // align for the labels
  279. {
  280. ostringstream lab_contents;
  281. if (readVal(lab_contents, pIcode->ic.ll.label, 0))
  282. {
  283. lab_contents << ':'; /* Also removes the null */
  284. }
  285. else if (pIcode->ic.ll.flg & TARGET) /* Symbols override Lnn labels */
  286. {
  287. /* Print label */
  288. if (! pl[i])
  289. {
  290. pl[i] = ++lab;
  291. }
  292. lab_contents<< "L"<<pl[i]<<':';
  293. }
  294. oper_stream<< lab_contents.str();
  295. }
  296. if (pIcode->ic.ll.opcode == iSIGNEX && (pIcode->ic.ll.flg & B))
  297. {
  298. pIcode->ic.ll.opcode = iCBW;
  299. }
  300. oper_stream << setw(15) << left <<szOps[pIcode->ic.ll.opcode];
  301. switch (pIcode->ic.ll.opcode)
  302. {
  303. case iADD: case iADC: case iSUB: case iSBB: case iAND: case iOR:
  304. case iXOR: case iTEST: case iCMP: case iMOV: case iLEA: case iXCHG:
  305. strDst(oper_stream,pIcode->ic.ll.flg, &pIcode->ic.ll.dst);
  306. strSrc(oper_stream,pIcode);
  307. break;
  308. case iESC:
  309. flops(pIcode,oper_stream);
  310. break;
  311. case iSAR: case iSHL: case iSHR: case iRCL: case iRCR: case iROL:
  312. case iROR:
  313. strDst(oper_stream,pIcode->ic.ll.flg | I, &pIcode->ic.ll.dst);
  314. if(pIcode->ic.ll.flg & I)
  315. strSrc(oper_stream,pIcode);
  316. else
  317. oper_stream<<", cl";
  318. break;
  319. case iINC: case iDEC: case iNEG: case iNOT: case iPOP:
  320. strDst(oper_stream,pIcode->ic.ll.flg | I, &pIcode->ic.ll.dst);
  321. break;
  322. case iPUSH:
  323. if (pIcode->ic.ll.flg & I)
  324. {
  325. oper_stream<<strHex(pIcode->ic.ll.src.op());
  326. // strcpy(p + WID_PTR, strHex(pIcode->ic.ll.immed.op));
  327. }
  328. else
  329. {
  330. strDst(oper_stream,pIcode->ic.ll.flg | I, &pIcode->ic.ll.dst);
  331. }
  332. break;
  333. case iDIV: case iIDIV: case iMUL: case iIMUL: case iMOD:
  334. if (pIcode->ic.ll.flg & I)
  335. {
  336. strDst(oper_stream,pIcode->ic.ll.flg, &pIcode->ic.ll.dst) <<", ";
  337. formatRM(oper_stream, pIcode->ic.ll.flg, &pIcode->ic.ll.src);
  338. strSrc(oper_stream,pIcode);
  339. }
  340. else
  341. strDst(oper_stream,pIcode->ic.ll.flg | I, &pIcode->ic.ll.src);
  342. break;
  343. case iLDS: case iLES: case iBOUND:
  344. strDst(oper_stream,pIcode->ic.ll.flg, &pIcode->ic.ll.dst)<<", dword ptr";
  345. strSrc(oper_stream,pIcode,true);
  346. break;
  347. case iJB: case iJBE: case iJAE: case iJA:
  348. case iJL: case iJLE: case iJGE: case iJG:
  349. case iJE: case iJNE: case iJS: case iJNS:
  350. case iJO: case iJNO: case iJP: case iJNP:
  351. case iJCXZ:case iLOOP: case iLOOPE:case iLOOPNE:
  352. case iJMP: case iJMPF:
  353. /* Check if there is a symbol here */
  354. selectTable(Label);
  355. if ((pIcode->ic.ll.src.op() < (dword)numIcode) && /* Ensure in range */
  356. readVal(oper_stream, pc[pIcode->ic.ll.src.op()].ic.ll.label, 0))
  357. {
  358. break; /* Symbolic label. Done */
  359. }
  360. if (pIcode->ic.ll.flg & NO_LABEL)
  361. {
  362. //strcpy(p + WID_PTR, strHex(pIcode->ic.ll.immed.op));
  363. oper_stream<<strHex(pIcode->ic.ll.src.op());
  364. }
  365. else if (pIcode->ic.ll.flg & I)
  366. {
  367. j = pIcode->ic.ll.src.op();
  368. if (! pl[j]) /* Forward jump */
  369. {
  370. pl[j] = ++lab;
  371. }
  372. if (pIcode->ic.ll.opcode == iJMPF)
  373. {
  374. oper_stream<<" far ptr ";
  375. }
  376. oper_stream<<"L"<<pl[j];
  377. }
  378. else if (pIcode->ic.ll.opcode == iJMPF)
  379. {
  380. oper_stream<<"dword ptr";
  381. strSrc(oper_stream,pIcode,true);
  382. }
  383. else
  384. {
  385. strDst(oper_stream,I, &pIcode->ic.ll.src);
  386. }
  387. break;
  388. case iCALL: case iCALLF:
  389. if (pIcode->ic.ll.flg & I)
  390. {
  391. if((pIcode->ic.ll.opcode == iCALL))
  392. oper_stream<< "near";
  393. else
  394. oper_stream<< " far";
  395. oper_stream<<" ptr "<<(pIcode->ic.ll.src.proc.proc)->name;
  396. }
  397. else if (pIcode->ic.ll.opcode == iCALLF)
  398. {
  399. oper_stream<<"dword ptr ";
  400. strSrc(oper_stream,pIcode,true);
  401. }
  402. else
  403. strDst(oper_stream,I, &pIcode->ic.ll.src);
  404. break;
  405. case iENTER:
  406. oper_stream<<strHex(pIcode->ic.ll.dst.off)<<", ";
  407. oper_stream<<strHex(pIcode->ic.ll.src.op());
  408. break;
  409. case iRET: case iRETF: case iINT:
  410. if (pIcode->ic.ll.flg & I)
  411. {
  412. oper_stream<<strHex(pIcode->ic.ll.src.op());
  413. }
  414. break;
  415. case iCMPS: case iREPNE_CMPS: case iREPE_CMPS:
  416. case iSCAS: case iREPNE_SCAS: case iREPE_SCAS:
  417. case iSTOS: case iREP_STOS:
  418. case iLODS: case iREP_LODS:
  419. case iMOVS: case iREP_MOVS:
  420. case iINS: case iREP_INS:
  421. case iOUTS: case iREP_OUTS:
  422. if (pIcode->ic.ll.src.segOver)
  423. {
  424. bool is_dx_src=(pIcode->ic.ll.opcode == iOUTS || pIcode->ic.ll.opcode == iREP_OUTS);
  425. if(is_dx_src)
  426. oper_stream<<"dx, "<<szPtr[pIcode->ic.ll.flg & B];
  427. else
  428. oper_stream<<szPtr[pIcode->ic.ll.flg & B];
  429. if (pIcode->ic.ll.opcode == iLODS ||
  430. pIcode->ic.ll.opcode == iREP_LODS ||
  431. pIcode->ic.ll.opcode == iOUTS ||
  432. pIcode->ic.ll.opcode == iREP_OUTS)
  433. {
  434. oper_stream<<szWreg[pIcode->ic.ll.src.segOver-rAX];
  435. }
  436. else
  437. {
  438. oper_stream<<"es:[di], "<<szWreg[pIcode->ic.ll.src.segOver - rAX];
  439. }
  440. oper_stream<<":[si]";
  441. }
  442. else
  443. oper_stream<<(pIcode->ic.ll.flg & B)? "B": "W";
  444. break;
  445. case iXLAT:
  446. if (pIcode->ic.ll.src.segOver)
  447. {
  448. oper_stream<<" "<<szPtr[1];
  449. oper_stream<<szWreg[pIcode->ic.ll.src.segOver-rAX]<<":[bx]";
  450. }
  451. break;
  452. case iIN:
  453. oper_stream<<(pIcode->ic.ll.flg & B)?"al, ": "ax, ";
  454. oper_stream<<(pIcode->ic.ll.flg & I)? strHex(pIcode->ic.ll.src.op()): "dx";
  455. break;
  456. case iOUT:
  457. oper_stream<<(pIcode->ic.ll.flg & I)? strHex(pIcode->ic.ll.src.op()): "dx";
  458. oper_stream<<(pIcode->ic.ll.flg & B)?", al": ", ax";
  459. break;
  460. default:
  461. break;
  462. }
  463. /* Comments */
  464. if (pIcode->ic.ll.flg & SYNTHETIC)
  465. {
  466. fImpure = FALSE;
  467. }
  468. else
  469. {
  470. for (j = pIcode->ic.ll.label, fImpure = 0; j > 0 && j < (Int)nextInst; j++)
  471. {
  472. fImpure |= BITMAP(j, BM_DATA);
  473. }
  474. }
  475. result_stream << setw(54) << left << oper_stream.str();
  476. /* Check for user supplied comment */
  477. selectTable(Comment);
  478. ostringstream cbuf;
  479. if (readVal(cbuf, pIcode->ic.ll.label, 0))
  480. {
  481. result_stream <<"; "<<cbuf.str();
  482. }
  483. else if (fImpure || (pIcode->ic.ll.flg & (SWITCH | CASE | SEG_IMMED | IMPURE | SYNTHETIC | TERMINATES)))
  484. {
  485. if (pIcode->ic.ll.flg & CASE)
  486. {
  487. result_stream << ";Case l"<< pIcode->ic.ll.caseTbl.numEntries;
  488. }
  489. if (pIcode->ic.ll.flg & SWITCH)
  490. {
  491. result_stream << ";Switch ";
  492. }
  493. if (fImpure)
  494. {
  495. result_stream << ";Accessed as data ";
  496. }
  497. if (pIcode->ic.ll.flg & IMPURE)
  498. {
  499. result_stream << ";Impure operand ";
  500. }
  501. if (pIcode->ic.ll.flg & SEG_IMMED)
  502. {
  503. result_stream << ";Segment constant";
  504. }
  505. if (pIcode->ic.ll.flg & TERMINATES)
  506. {
  507. result_stream << ";Exit to DOS";
  508. }
  509. }
  510. /* Comment on iINT icodes */
  511. if (pIcode->ic.ll.opcode == iINT)
  512. pIcode->writeIntComment (result_stream);
  513. /* Display output line */
  514. if(pass==3)
  515. {
  516. /* output to .b code buffer */
  517. if (pIcode->isLlFlag(SYNTHETIC))
  518. result_stream<<";Synthetic inst";
  519. if (pass == 3) /* output to .b code buffer */
  520. cCode.appendCode("%s\n", result_stream.str().c_str());
  521. }
  522. else
  523. {
  524. if (! (pIcode->ic.ll.flg & SYNTHETIC))
  525. {
  526. /* output to .a1 or .a2 file */
  527. fprintf (fp, "%03ld %06lX %s\n", i, pIcode->ic.ll.label, result_stream.str().c_str());
  528. }
  529. else /* SYNTHETIC instruction */
  530. {
  531. result_stream<<";Synthetic inst";
  532. fprintf (fp, "%03ld %s\n", i, result_stream.str().c_str());
  533. }
  534. }
  535. }
  536. /****************************************************************************
  537. * formatRM
  538. ***************************************************************************/
  539. static void formatRM(std::ostringstream &p, flags32 flg, LLOperand *pm)
  540. {
  541. char seg[4];
  542. if (pm->segOver)
  543. {
  544. strcat(strcpy(seg, szWreg[pm->segOver - rAX]), ":");
  545. }
  546. else *seg = '\0';
  547. if (pm->regi == 0)
  548. {
  549. p<<seg<<"["<<strHex((dword)pm->off)<<"]";
  550. }
  551. else if (pm->regi == (INDEXBASE - 1))
  552. {
  553. p<<"tmp";
  554. }
  555. else if (pm->regi < INDEXBASE)
  556. {
  557. if(flg & B)
  558. p << szBreg[pm->regi - rAL];
  559. else
  560. p << szWreg[pm->regi - rAX];
  561. }
  562. else if (pm->off)
  563. {
  564. if (pm->off < 0)
  565. {
  566. p <<seg<<"["<<szIndex[pm->regi - INDEXBASE]<<"-"<<strHex((dword)(- pm->off))<<"]";
  567. }
  568. else
  569. {
  570. p <<seg<<"["<<szIndex[pm->regi - INDEXBASE]<<"+"<<strHex((dword)(pm->off))<<"]";
  571. }
  572. }
  573. else
  574. p <<seg<<"["<<szIndex[pm->regi - INDEXBASE]<<"]";
  575. }
  576. /*****************************************************************************
  577. * strDst
  578. ****************************************************************************/
  579. static ostringstream & strDst(ostringstream &os,flags32 flg, LLOperand *pm)
  580. {
  581. /* Immediates to memory require size descriptor */
  582. //os << setw(WID_PTR);
  583. if ((flg & I) && (pm->regi == 0 || pm->regi >= INDEXBASE))
  584. os << szPtr[flg & B];
  585. formatRM(os, flg, pm);
  586. return os;
  587. }
  588. /****************************************************************************
  589. * strSrc *
  590. ****************************************************************************/
  591. static ostringstream &strSrc(ostringstream &os,ICODE *pc,bool skip_comma)
  592. {
  593. static char buf[30] = {", "};
  594. if(false==skip_comma)
  595. os<<", ";
  596. if (pc->ic.ll.flg & I)
  597. os<<strHex(pc->ic.ll.src.op());
  598. else if (pc->ic.ll.flg & IM_SRC) /* level 2 */
  599. os<<"dx:ax";
  600. else
  601. formatRM(os, pc->ic.ll.flg, &pc->ic.ll.src);
  602. return os;
  603. }
  604. /****************************************************************************
  605. * strHex *
  606. ****************************************************************************/
  607. static char *strHex(dword d)
  608. {
  609. static char buf[10];
  610. d &= 0xFFFF;
  611. sprintf(buf, "0%lX%s", d, (d > 9)? "h": "");
  612. return (buf + (buf[1] <= '9'));
  613. }
  614. /****************************************************************************
  615. * interactDis - interactive disassembler *
  616. ****************************************************************************/
  617. void interactDis(Function * initProc, Int initIC)
  618. {
  619. printf("Sorry - interactive disasassembler option not available for Unix\n");
  620. return;
  621. }
  622. /* Handle the floating point opcodes (icode iESC) */
  623. void flops(ICODE *pIcode,std::ostringstream &out)
  624. {
  625. char bf[30];
  626. byte op = (byte)pIcode->ic.ll.src.op();
  627. /* Note that op is set to the escape number, e.g.
  628. esc 0x38 is FILD */
  629. if ((pIcode->ic.ll.dst.regi == 0) || (pIcode->ic.ll.dst.regi >= INDEXBASE))
  630. {
  631. /* The mod/rm mod bits are not set to 11 (i.e. register). This is the normal floating point opcode */
  632. out<<szFlops1[op]<<' ';
  633. out <<setw(10);
  634. if ((op == 0x29) || (op == 0x1F))
  635. {
  636. strcpy(bf, "tbyte ptr ");
  637. }
  638. else switch (op & 0x30)
  639. {
  640. case 0x00:
  641. case 0x10:
  642. strcpy(bf, "dword ptr ");
  643. break;
  644. case 0x20:
  645. strcpy(bf, "qword ptr ");
  646. break;
  647. case 0x30:
  648. switch (op)
  649. {
  650. case 0x3C: /* FBLD */
  651. case 0x3E: /* FBSTP */
  652. strcpy(bf, "tbyte ptr ");
  653. break;
  654. case 0x3D: /* FILD 64 bit */
  655. case 0x3F: /* FISTP 64 bit */
  656. strcpy(bf, "qword ptr ");
  657. break;
  658. default:
  659. strcpy(bf, "word ptr ");
  660. break;
  661. }
  662. }
  663. formatRM(out, pIcode->ic.ll.flg, &pIcode->ic.ll.dst);
  664. }
  665. else
  666. {
  667. /* The mod/rm mod bits are set to 11 (i.e. register).
  668. Could be specials (0x0C-0x0F, etc), or the st(i) versions of
  669. normal opcodes. Because the opcodes are slightly different for
  670. this case (e.g. op=04 means FSUB if reg != 3, but FSUBR for
  671. reg == 3), a separate table is used (szFlops2). */
  672. switch (op)
  673. {
  674. case 0x0C:
  675. out << szFlops0C[pIcode->ic.ll.dst.regi - rAX];
  676. break;
  677. case 0x0D:
  678. out << szFlops0D[pIcode->ic.ll.dst.regi - rAX];
  679. break;
  680. case 0x0E:
  681. out << szFlops0E[pIcode->ic.ll.dst.regi - rAX];
  682. break;
  683. case 0x0F:
  684. out << szFlops0F[pIcode->ic.ll.dst.regi - rAX];
  685. break;
  686. case 0x15:
  687. out << szFlops15[pIcode->ic.ll.dst.regi - rAX];
  688. break;
  689. case 0x1C:
  690. out << szFlops1C[pIcode->ic.ll.dst.regi - rAX];
  691. break;
  692. case 0x33:
  693. out << szFlops33[pIcode->ic.ll.dst.regi - rAX];
  694. break;
  695. case 0x3C:
  696. out << szFlops3C[pIcode->ic.ll.dst.regi - rAX];
  697. break;
  698. default:
  699. out << szFlops2[op];
  700. if ((op >= 0x20) && (op <= 0x27))
  701. {
  702. /* This is the ST(i), ST form. */
  703. out << "ST("<<pIcode->ic.ll.dst.regi - rAX<<"),ST";
  704. }
  705. else
  706. {
  707. /* ST, ST(i) */
  708. out << "ST,ST("<<pIcode->ic.ll.dst.regi - rAX;
  709. }
  710. break;
  711. }
  712. }
  713. }