ag386int.pas 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833
  1. {
  2. $Id$
  3. Copyright (c) 1996,97 by Florian Klaempfl
  4. This unit implements an asmoutput class for Intel syntax with Intel i386+
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit ag386int;
  19. interface
  20. uses aasm,assemble;
  21. type
  22. pi386intasmlist=^ti386intasmlist;
  23. ti386intasmlist = object(tasmlist)
  24. procedure WriteTree(p:paasmoutput);virtual;
  25. procedure WriteAsmList;virtual;
  26. end;
  27. implementation
  28. uses
  29. dos,globals,systems,cobjects,i386,
  30. strings,files,verbose
  31. {$ifdef GDB}
  32. ,gdb
  33. {$endif GDB}
  34. ;
  35. const
  36. line_length = 70;
  37. extstr : array[EXT_NEAR..EXT_ABS] of String[8] =
  38. ('NEAR','FAR','PROC','BYTE','WORD','DWORD',
  39. 'CODEPTR','DATAPTR','FWORD','PWORD','QWORD','TBYTE','ABS');
  40. function getreferencestring(const ref : treference) : string;
  41. var
  42. s : string;
  43. first : boolean;
  44. begin
  45. if ref.isintvalue then
  46. s:= tostr(ref.offset)
  47. else
  48. {$ifdef ver0_6}
  49. begin
  50. first:=true;
  51. { have we a segment prefix ? }
  52. if ref.segment<>R_DEFAULT_SEG then
  53. begin
  54. if current_module^.output_format in [of_nasm,of_obj] then
  55. s:='['+_reg2str[ref.segment]+':'
  56. else
  57. s:=_reg2str[ref.segment]+':[';
  58. end
  59. else s:='[';
  60. if assigned(ref.symbol) then
  61. begin
  62. s:=s+ref.symbol^;
  63. first:=false;
  64. end;
  65. if (ref.base<>R_NO) then
  66. begin
  67. if not(first) then
  68. s:=s+'+'
  69. else
  70. first:=false;
  71. s:=s+_reg2str[ref.base];
  72. end;
  73. if (ref.index<>R_NO) then
  74. begin
  75. if not(first) then
  76. s:=s+'+'
  77. else
  78. first:=false;
  79. s:=s+_reg2str[ref.index];
  80. if ref.scalefactor<>0 then
  81. s:=s+'*'+tostr(ref.scalefactor);
  82. end;
  83. if ref.offset<0 then
  84. s:=s+tostr(ref.offset)
  85. else if (ref.offset>0) then
  86. s:=s+'+'+tostr(ref.offset);
  87. s:=s+']';
  88. end;
  89. {$else}
  90. with ref do
  91. begin
  92. first:=true;
  93. if ref.segment<>R_DEFAULT_SEG then
  94. begin
  95. if current_module^.output_format in [of_nasm,of_obj] then
  96. s:='['+int_reg2str[segment]+':'
  97. else
  98. s:=int_reg2str[segment]+':[';
  99. end
  100. else
  101. s:='[';
  102. if assigned(symbol) then
  103. begin
  104. s:=s+symbol^;
  105. first:=false;
  106. end;
  107. if (base<>R_NO) then
  108. begin
  109. if not(first) then
  110. s:=s+'+'
  111. else
  112. first:=false;
  113. s:=s+int_reg2str[base];
  114. end;
  115. if (index<>R_NO) then
  116. begin
  117. if not(first) then
  118. s:=s+'+'
  119. else
  120. first:=false;
  121. s:=s+int_reg2str[index];
  122. if scalefactor<>0 then
  123. s:=s+'*'+tostr(scalefactor);
  124. end;
  125. if offset<0 then
  126. s:=s+tostr(offset)
  127. else if (offset>0) then
  128. s:=s+'+'+tostr(offset);
  129. s:=s+']';
  130. end;
  131. {$endif}
  132. getreferencestring:=s;
  133. end;
  134. function getopstr(t : byte;o : pointer;s : topsize; _operator: tasmop;dest : boolean) : string;
  135. var
  136. hs : string;
  137. begin
  138. case t of
  139. top_reg : { a floating point register can be only a register operand }
  140. if current_module^.output_format in [of_nasm,of_obj] then
  141. getopstr:=int_nasmreg2str[tregister(o)]
  142. else
  143. getopstr:=int_reg2str[tregister(o)];
  144. top_const,
  145. top_ref : begin
  146. if t=top_const then
  147. hs := tostr(longint(o))
  148. else
  149. hs:=getreferencestring(preference(o)^);
  150. if current_module^.output_format in [of_nasm,of_obj] then
  151. if (_operator = A_LEA) or (_operator = A_LGS)
  152. or (_operator = A_LSS) or (_operator = A_LFS)
  153. or (_operator = A_LES) or (_operator = A_LDS)
  154. or (_operator = A_SHR) or (_operator = A_SHL)
  155. or (_operator = A_SAR) or (_operator = A_SAL)
  156. or (_operator = A_OUT) or (_operator = A_IN) then
  157. begin
  158. end
  159. else
  160. case s of
  161. S_B : hs:='byte '+hs;
  162. S_W : hs:='word '+hs;
  163. S_L : hs:='dword '+hs;
  164. S_IS : hs:='word '+hs;
  165. S_IL : hs:='dword '+hs;
  166. S_IQ : hs:='qword '+hs;
  167. S_FS : hs:='dword '+hs;
  168. S_FL : hs:='qword '+hs;
  169. S_FX : hs:='tword '+hs;
  170. S_BW : if dest then
  171. hs:='word '+hs
  172. else
  173. hs:='byte '+hs;
  174. S_BL : if dest then
  175. hs:='dword '+hs
  176. else
  177. hs:='byte '+hs;
  178. S_WL : if dest then
  179. hs:='dword '+hs
  180. else
  181. hs:='word '+hs;
  182. end
  183. else
  184. Begin
  185. { can possibly give a range check error under tp }
  186. { if using in... }
  187. if ((_operator <> A_LGS) and (_operator <> A_LSS) and
  188. (_operator <> A_LFS) and (_operator <> A_LDS) and
  189. (_operator <> A_LES)) then
  190. Begin
  191. case s of
  192. S_B : hs:='byte ptr '+hs;
  193. S_W : hs:='word ptr '+hs;
  194. S_L : hs:='dword ptr '+hs;
  195. S_IS : hs:='word ptr '+hs;
  196. S_IL : hs:='dword ptr '+hs;
  197. S_IQ : hs:='qword ptr '+hs;
  198. S_FS : hs:='dword ptr '+hs;
  199. S_FL : hs:='qword ptr '+hs;
  200. S_FX : hs:='tbyte ptr '+hs;
  201. S_BW : if dest then
  202. hs:='word ptr '+hs
  203. else
  204. hs:='byte ptr '+hs;
  205. S_BL : if dest then
  206. hs:='dword ptr '+hs
  207. else
  208. hs:='byte ptr '+hs;
  209. S_WL : if dest then
  210. hs:='dword ptr '+hs
  211. else
  212. hs:='word ptr '+hs;
  213. end;
  214. end;
  215. end;
  216. getopstr:=hs;
  217. end;
  218. top_symbol : begin
  219. hs[0]:=chr(strlen(pchar(pcsymbol(o)^.symbol)));
  220. move(pchar(pcsymbol(o)^.symbol)^,hs[1],byte(hs[0]));
  221. if current_module^.output_format=of_masm then
  222. hs:='offset '+hs
  223. else
  224. hs:='dword '+hs;
  225. if pcsymbol(o)^.offset>0 then
  226. hs:=hs+'+'+tostr(pcsymbol(o)^.offset)
  227. else if pcsymbol(o)^.offset<0 then
  228. hs:=hs+tostr(pcsymbol(o)^.offset);
  229. getopstr:=hs;
  230. end;
  231. else internalerror(10001);
  232. end;
  233. end;
  234. function getopstr_jmp(t : byte;o : pointer) : string;
  235. var
  236. hs : string;
  237. begin
  238. case t of
  239. top_reg : getopstr_jmp:=int_reg2str[tregister(o)];
  240. top_ref : getopstr_jmp:=getreferencestring(preference(o)^);
  241. top_const : getopstr_jmp:=tostr(longint(o));
  242. top_symbol : begin
  243. hs[0]:=chr(strlen(pchar(pcsymbol(o)^.symbol)));
  244. move(pchar(pcsymbol(o)^.symbol)^,hs[1],byte(hs[0]));
  245. if pcsymbol(o)^.offset>0 then
  246. hs:=hs+'+'+tostr(pcsymbol(o)^.offset)
  247. else if pcsymbol(o)^.offset<0 then
  248. hs:=hs+tostr(pcsymbol(o)^.offset);
  249. getopstr_jmp:=hs;
  250. end;
  251. else internalerror(10001);
  252. end;
  253. end;
  254. {****************************************************************************
  255. TI386INTASMLIST
  256. ****************************************************************************}
  257. const
  258. ait_const2str:array[ait_const_32bit..ait_const_8bit] of string[8]=
  259. (#9'DD'#9,'',#9'DW'#9,#9'DB'#9);
  260. Function PadTabs(p:pchar;addch:char):string;
  261. var
  262. s : string;
  263. i : longint;
  264. begin
  265. i:=strlen(p);
  266. if addch<>#0 then
  267. begin
  268. inc(i);
  269. s:=StrPas(p)+addch;
  270. end
  271. else
  272. s:=StrPas(p);
  273. if i<8 then
  274. PadTabs:=s+#9#9
  275. else
  276. PadTabs:=s+#9;
  277. end;
  278. procedure ti386intasmlist.WriteTree(p:paasmoutput);
  279. type
  280. twowords=record
  281. word1,word2:word;
  282. end;
  283. var
  284. s,
  285. prefix,
  286. suffix : string;
  287. hp : pai;
  288. counter,
  289. lines,
  290. i,j,l : longint;
  291. consttyp : tait;
  292. found,
  293. quoted : boolean;
  294. begin
  295. hp:=pai(p^.first);
  296. while assigned(hp) do
  297. begin
  298. case hp^.typ of
  299. ait_comment :
  300. Begin
  301. AsmWrite(As_comment);
  302. AsmWritePChar(pai_asm_comment(hp)^.str);
  303. AsmLn;
  304. End;
  305. ait_align : begin
  306. { align not supported at all with nasm v095 }
  307. { align with specific value not supported by }
  308. { turbo assembler. }
  309. { CAUSES PROBLEMS WITH THE SEGMENT DEFINITION }
  310. { SEGMENT DEFINITION SHOULD MATCH TYPE OF ALIGN }
  311. { HERE UNDER TASM! }
  312. { if current_module^.output_format<>of_nasm then }
  313. AsmWriteLn(#9'ALIGN '+tostr(pai_align(hp)^.aligntype));
  314. end;
  315. ait_external : begin
  316. if current_module^.output_format in [of_nasm,of_obj] then
  317. AsmWriteLn('EXTERN '+StrPas(pai_external(hp)^.name))
  318. else
  319. AsmWriteLn(#9#9'EXTRN'#9+StrPas(pai_external(hp)^.name)+
  320. ' :'+extstr[pai_external(hp)^.exttyp]);
  321. end;
  322. ait_datablock : begin
  323. if current_module^.output_format in [of_nasm,of_obj] then
  324. begin
  325. if pai_datablock(hp)^.is_global then
  326. AsmWriteLn('GLOBAL '+StrPas(pai_datablock(hp)^.name));
  327. AsmWriteLn(PadTabs(pai_datablock(hp)^.name,':')+'RESB'#9+tostr(pai_datablock(hp)^.size));
  328. end
  329. else
  330. begin
  331. if pai_datablock(hp)^.is_global then
  332. AsmWriteLn(#9#9'PUBLIC'#9+StrPas(pai_datablock(hp)^.name));
  333. AsmWriteLn(PadTabs(pai_datablock(hp)^.name,#0)+'DB'#9+tostr(pai_datablock(hp)^.size)+' DUP(?)');
  334. end;
  335. end;
  336. ait_const_32bit,
  337. ait_const_8bit,
  338. ait_const_16bit : begin
  339. AsmWrite(ait_const2str[hp^.typ]+tostr(pai_const(hp)^.value));
  340. consttyp:=hp^.typ;
  341. l:=0;
  342. repeat
  343. found:=(not (Pai(hp^.next)=nil)) and (Pai(hp^.next)^.typ=consttyp);
  344. if found then
  345. begin
  346. hp:=Pai(hp^.next);
  347. s:=','+tostr(pai_const(hp)^.value);
  348. AsmWrite(s);
  349. inc(l,length(s));
  350. end;
  351. until (not found) or (l>line_length);
  352. AsmLn;
  353. end;
  354. ait_const_symbol : begin
  355. if current_module^.output_format<>of_nasm then
  356. AsmWrite(#9#9+'DD '#9'offset ')
  357. else
  358. AsmWrite(#9#9+'DD '#9);
  359. AsmWriteLn(StrPas(pchar(pai_const(hp)^.value)));
  360. end;
  361. ait_real_32bit : AsmWriteLn(#9#9'DD'#9+double2str(pai_single(hp)^.value));
  362. ait_real_64bit : AsmWriteLn(#9#9'DQ'#9+double2str(pai_double(hp)^.value));
  363. ait_real_extended : begin
  364. { nasm v095 does not like DT with real constants }
  365. { therefore write as double. }
  366. { other possible solution: decode directly to hex}
  367. { value. }
  368. if current_module^.output_format<>of_nasm then
  369. AsmWriteLn(#9#9'DT'#9+double2str(pai_extended(hp)^.value))
  370. else
  371. begin
  372. {$ifdef EXTDEBUG}
  373. AsmLn;
  374. AsmWriteLn('; NASM bug work around for extended real');
  375. {$endif}
  376. AsmWriteLn(#9#9'DD'#9+double2str(pai_extended(hp)^.value))
  377. end;
  378. end;
  379. ait_comp : AsmWriteLn(#9#9'DQ'#9+comp2str(pai_extended(hp)^.value));
  380. ait_string : begin
  381. counter := 0;
  382. lines := pai_string(hp)^.len div line_length;
  383. { separate lines in different parts }
  384. if pai_string(hp)^.len > 0 then
  385. Begin
  386. for j := 0 to lines-1 do
  387. begin
  388. AsmWrite(#9#9'DB'#9);
  389. quoted:=false;
  390. for i:=counter to counter+line_length do
  391. begin
  392. { it is an ascii character. }
  393. if (ord(pai_string(hp)^.str[i])>31) and
  394. (ord(pai_string(hp)^.str[i])<128) and
  395. (pai_string(hp)^.str[i]<>'"') then
  396. begin
  397. if not(quoted) then
  398. begin
  399. if i>counter then
  400. AsmWrite(',');
  401. AsmWrite('"');
  402. end;
  403. AsmWrite(pai_string(hp)^.str[i]);
  404. quoted:=true;
  405. end { if > 31 and < 128 and ord('"') }
  406. else
  407. begin
  408. if quoted then
  409. AsmWrite('"');
  410. if i>counter then
  411. AsmWrite(',');
  412. quoted:=false;
  413. AsmWrite(tostr(ord(pai_string(hp)^.str[i])));
  414. end;
  415. end; { end for i:=0 to... }
  416. if quoted then AsmWrite('"');
  417. AsmWrite(target_info.newline);
  418. counter := counter+line_length;
  419. end; { end for j:=0 ... }
  420. { do last line of lines }
  421. AsmWrite(#9#9'DB'#9);
  422. quoted:=false;
  423. for i:=counter to pai_string(hp)^.len-1 do
  424. begin
  425. { it is an ascii character. }
  426. if (ord(pai_string(hp)^.str[i])>31) and
  427. (ord(pai_string(hp)^.str[i])<128) and
  428. (pai_string(hp)^.str[i]<>'"') then
  429. begin
  430. if not(quoted) then
  431. begin
  432. if i>counter then
  433. AsmWrite(',');
  434. AsmWrite('"');
  435. end;
  436. AsmWrite(pai_string(hp)^.str[i]);
  437. quoted:=true;
  438. end { if > 31 and < 128 and " }
  439. else
  440. begin
  441. if quoted then
  442. AsmWrite('"');
  443. if i>counter then
  444. AsmWrite(',');
  445. quoted:=false;
  446. AsmWrite(tostr(ord(pai_string(hp)^.str[i])));
  447. end;
  448. end; { end for i:=0 to... }
  449. if quoted then
  450. AsmWrite('"');
  451. end;
  452. AsmLn;
  453. end;
  454. ait_label : begin
  455. AsmWrite(lab2str(pai_label(hp)^.l));
  456. if (current_module^.output_format in [of_obj,of_nasm]) or
  457. (assigned(hp^.next) and not(pai(hp^.next)^.typ in
  458. [ait_const_32bit,ait_const_16bit,ait_const_8bit,ait_const_symbol,
  459. ait_real_32bit,ait_real_64bit,ait_real_extended,ait_string])) then
  460. AsmWriteLn(':');
  461. end;
  462. ait_direct : begin
  463. AsmWritePChar(pai_direct(hp)^.str);
  464. AsmLn;
  465. end;
  466. ait_labeled_instruction :
  467. begin
  468. if (current_module^.output_format in [of_nasm,of_obj]) and
  469. not (pai_labeled(hp)^._operator in [A_JMP,A_LOOP,A_LOOPZ,A_LOOPE,
  470. A_LOOPNZ,A_LOOPNE,A_JCXZ,A_JECXZ]) then
  471. AsmWriteLn(#9#9+int_op2str[pai_labeled(hp)^._operator]+#9+'near '+lab2str(pai_labeled(hp)^.lab))
  472. else
  473. AsmWriteLn(#9#9+int_op2str[pai_labeled(hp)^._operator]+#9+lab2str(pai_labeled(hp)^.lab));
  474. end;
  475. ait_symbol : begin
  476. if pai_symbol(hp)^.is_global then
  477. begin
  478. if current_module^.output_format in [of_nasm,of_obj] then
  479. AsmWriteLn('GLOBAL '+StrPas(pai_symbol(hp)^.name))
  480. else
  481. AsmWriteLn(#9#9'PUBLIC'#9+StrPas(pai_symbol(hp)^.name));
  482. end;
  483. AsmWritePChar(pai_symbol(hp)^.name);
  484. if assigned(hp^.next) and not(pai(hp^.next)^.typ in
  485. [ait_const_32bit,ait_const_16bit,ait_const_8bit,ait_const_symbol,
  486. ait_real_64bit,ait_string]) then
  487. AsmWriteLn(':')
  488. end;
  489. ait_instruction : begin
  490. suffix:='';
  491. prefix:= '';
  492. { added prefix instructions, must be on same line as opcode }
  493. if (pai386(hp)^.op1t = top_none) and
  494. ((pai386(hp)^._operator = A_REP) or
  495. (pai386(hp)^._operator = A_LOCK) or
  496. (pai386(hp)^._operator = A_REPE) or
  497. (pai386(hp)^._operator = A_REPNE)) then
  498. Begin
  499. prefix:=int_op2str[pai386(hp)^._operator]+#9;
  500. hp:=Pai(hp^.next);
  501. { this is theorically impossible... }
  502. if hp=nil then
  503. begin
  504. s:=#9#9+prefix;
  505. AsmWriteLn(s);
  506. break;
  507. end;
  508. { nasm prefers prefix on a line alone }
  509. if (current_module^.output_format in [of_nasm,of_obj]) then
  510. begin
  511. AsmWriteln(#9#9+prefix);
  512. prefix:='';
  513. end;
  514. end
  515. else
  516. prefix:= '';
  517. { A_FNSTS need the w as suffix at least for nasm}
  518. if (current_module^.output_format in [of_nasm,of_obj]) then
  519. if (pai386(hp)^._operator = A_FNSTS) then
  520. pai386(hp)^._operator:=A_FNSTSW
  521. else if (pai386(hp)^._operator = A_FSTS) then
  522. pai386(hp)^._operator:=A_FSTSW;
  523. if pai386(hp)^.op1t<>top_none then
  524. begin
  525. if pai386(hp)^._operator in [A_CALL] then
  526. begin
  527. if output_format=of_nasm then
  528. s:=getopstr_jmp(pai386(hp)^.op1t,pai386(hp)^.op1)
  529. { with tasm call near ptr [edi+12] does not
  530. work but call near [edi+12] works ?? (PM)}
  531. else if pai386(hp)^.op1t=top_ref then
  532. s:='near '+getopstr_jmp(pai386(hp)^.op1t,pai386(hp)^.op1)
  533. else
  534. s:='near ptr '+getopstr_jmp(pai386(hp)^.op1t,pai386(hp)^.op1);
  535. end
  536. else
  537. begin
  538. s:=getopstr(pai386(hp)^.op1t,pai386(hp)^.op1,pai386(hp)^.size,pai386(hp)^._operator,false);
  539. if pai386(hp)^.op3t<>top_none then
  540. begin
  541. if pai386(hp)^.op2t<>top_none then
  542. s:=getopstr(pai386(hp)^.op2t,pointer(longint(twowords(pai386(hp)^.op2).word1)),
  543. pai386(hp)^.size,pai386(hp)^._operator,true)+','+s;
  544. s:=getopstr(pai386(hp)^.op3t,pointer(longint(twowords(pai386(hp)^.op2).word2)),
  545. pai386(hp)^.size,pai386(hp)^._operator,false)+','+s;
  546. end
  547. else
  548. if pai386(hp)^.op2t<>top_none then
  549. s:=getopstr(pai386(hp)^.op2t,pai386(hp)^.op2,pai386(hp)^.size,
  550. pai386(hp)^._operator,true)+','+s;
  551. end;
  552. s:=#9+s;
  553. end
  554. else
  555. begin
  556. { check if string instruction }
  557. { long form, otherwise may give range check errors }
  558. { in turbo pascal... }
  559. if ((pai386(hp)^._operator = A_CMPS) or
  560. (pai386(hp)^._operator = A_INS) or
  561. (pai386(hp)^._operator = A_OUTS) or
  562. (pai386(hp)^._operator = A_SCAS) or
  563. (pai386(hp)^._operator = A_STOS) or
  564. (pai386(hp)^._operator = A_MOVS) or
  565. (pai386(hp)^._operator = A_LODS) or
  566. (pai386(hp)^._operator = A_XLAT)) then
  567. Begin
  568. case pai386(hp)^.size of
  569. S_B: suffix:='b';
  570. S_W: suffix:='w';
  571. S_L: suffix:='d';
  572. else
  573. Message(assem_f_invalid_suffix_intel);
  574. end;
  575. end;
  576. s:='';
  577. end;
  578. AsmWriteLn(#9#9+prefix+int_op2str[pai386(hp)^._operator]+suffix+s);
  579. end;
  580. {$ifdef GDB}
  581. ait_stabn,
  582. ait_stabs,
  583. ait_stab_function_name : ;
  584. {$endif GDB}
  585. else
  586. internalerror(10000);
  587. end;
  588. hp:=pai(hp^.next);
  589. end;
  590. end;
  591. procedure ti386intasmlist.WriteAsmList;
  592. begin
  593. {$ifdef EXTDEBUG}
  594. if assigned(current_module^.mainsource) then
  595. comment(v_info,'Start writing intel-styled assembler output for '+current_module^.mainsource^);
  596. {$endif}
  597. if current_module^.output_format in [of_nasm,of_obj] then
  598. begin
  599. WriteTree(externals);
  600. { INTEL ASM doesn't support stabs
  601. WriteTree(debuglist);}
  602. AsmWriteLn('BITS 32');
  603. AsmWriteLn('SECTION .text');
  604. {
  605. AsmWriteLn(#9#9'ASSUME'#9'CS:_TEXT,ES:DGROUP,DS:DGROUP,SS:DGROUP');
  606. }
  607. WriteTree(codesegment);
  608. AsmLn;
  609. AsmWriteLn('SECTION .data');
  610. {$ifdef EXTDEBUG}
  611. AsmWriteLn(#9#9'DB'#9'"compiled by FPC '+version_string+'\0"');
  612. AsmWriteLn(#9#9'DB'#9'"target: '+target_info.target_name+'\0"');
  613. {$endif EXTDEBUG}
  614. WriteTree(datasegment);
  615. WriteTree(consts);
  616. AsmLn;
  617. AsmWriteLn('SECTION .bss');
  618. WriteTree(bsssegment);
  619. end
  620. else
  621. begin
  622. AsmWriteLn(#9'.386p');
  623. AsmWriteLn(#9'LOCALS '+target_info.labelprefix);
  624. WriteTree(externals);
  625. { INTEL ASM doesn't support stabs
  626. WriteTree(debuglist);}
  627. AsmWriteLn('DGROUP'#9#9'GROUP'#9'_BSS,_DATA');
  628. AsmWriteLn('_TEXT'#9#9'SEGMENT'#9'PARA PUBLIC USE32 ''CODE''');
  629. AsmWriteLn(#9#9'ASSUME'#9'CS:_TEXT,ES:DGROUP,DS:DGROUP,SS:DGROUP');
  630. AsmLn;
  631. WriteTree(codesegment);
  632. AsmWriteLn('_TEXT'#9#9'ENDS');
  633. AsmLn;
  634. AsmWriteLn('_DATA'#9#9'SEGMENT'#9'PARA PUBLIC USE32 ''DATA''');
  635. {$ifdef EXTDEBUG}
  636. AsmWriteLn(#9#9'DB'#9'"compiled by FPC '+version_string+'\0"');
  637. AsmWriteLn(#9#9'DB'#9'"target: '+target_info.target_name+'\0"');
  638. {$endif EXTDEBUG}
  639. WriteTree(datasegment);
  640. WriteTree(consts);
  641. AsmWriteLn('_DATA'#9#9'ENDS');
  642. AsmLn;
  643. AsmWriteLn('_BSS'#9#9'SEGMENT'#9'PARA PUBLIC USE32 ''BSS''');
  644. WriteTree(bsssegment);
  645. AsmWriteLn('_BSS'#9#9'ENDS');
  646. AsmLn;
  647. AsmWriteLn(#9#9'END');
  648. end;
  649. {$ifdef EXTDEBUG}
  650. if assigned(current_module^.mainsource) then
  651. comment(v_info,'Done writing intel-styled assembler output for '+current_module^.mainsource^);
  652. {$endif EXTDEBUG}
  653. end;
  654. end.
  655. {
  656. $Log$
  657. Revision 1.4 1998-04-29 10:33:41 pierre
  658. + added some code for ansistring (not complete nor working yet)
  659. * corrected operator overloading
  660. * corrected nasm output
  661. + started inline procedures
  662. + added starstarn : use ** for exponentiation (^ gave problems)
  663. + started UseTokenInfo cond to get accurate positions
  664. Revision 1.3 1998/04/08 16:58:01 pierre
  665. * several bugfixes
  666. ADD ADC and AND are also sign extended
  667. nasm output OK (program still crashes at end
  668. and creates wrong assembler files !!)
  669. procsym types sym in tdef removed !!
  670. Revision 1.2 1998/04/08 11:34:17 peter
  671. * nasm works (linux only tested)
  672. Revision 1.1.1.1 1998/03/25 11:18:16 root
  673. * Restored version
  674. Revision 1.1 1998/03/10 01:26:09 peter
  675. + new uniform names
  676. Revision 1.18 1998/03/09 12:58:11 peter
  677. * FWait warning is only showed for Go32V2 and $E+
  678. * opcode tables moved to i386.pas/m68k.pas to reduce circular uses (and
  679. for m68k the same tables are removed)
  680. + $E for i386
  681. Revision 1.17 1998/03/06 00:52:23 peter
  682. * replaced all old messages from errore.msg, only ExtDebug and some
  683. Comment() calls are left
  684. * fixed options.pas
  685. Revision 1.16 1998/03/02 01:48:41 peter
  686. * renamed target_DOS to target_GO32V1
  687. + new verbose system, merged old errors and verbose units into one new
  688. verbose.pas, so errors.pas is obsolete
  689. Revision 1.15 1998/02/23 02:57:41 carl
  690. * small bugfix when compiling $extdebug
  691. Revision 1.14 1998/02/15 21:16:20 peter
  692. * all assembler outputs supported by assemblerobject
  693. * cleanup with assembleroutputs, better .ascii generation
  694. * help_constructor/destructor are now added to the externals
  695. - generation of asmresponse is not outputformat depended
  696. Revision 1.13 1998/02/13 10:35:07 daniel
  697. * Made Motorola version compilable.
  698. * Fixed optimizer
  699. Revision 1.12 1998/02/12 17:19:07 florian
  700. * fixed to get remake3 work, but needs additional fixes (output, I don't like
  701. also that aktswitches isn't a pointer)
  702. Revision 1.11 1998/02/12 11:50:11 daniel
  703. Yes! Finally! After three retries, my patch!
  704. Changes:
  705. Complete rewrite of psub.pas.
  706. Added support for DLL's.
  707. Compiler requires less memory.
  708. Platform units for each platform.
  709. Revision 1.10 1997/12/13 18:59:48 florian
  710. + I/O streams are now also declared as external, if neccessary
  711. * -Aobj generates now a correct obj file via nasm
  712. Revision 1.9 1997/12/12 13:28:26 florian
  713. + version 0.99.0
  714. * all WASM options changed into MASM
  715. + -O2 for Pentium II optimizations
  716. Revision 1.8 1997/12/09 13:45:10 carl
  717. * bugfix of DT under nasm (not allowed if non integral - nasm v095)
  718. + added pai_align --> useless here see file for more info
  719. * bugfix of problems with in,out instructions under nasm
  720. * bugfix of call under nasm (not fully tested though -- not sure)
  721. * some range check errors removed (probably a few left though)
  722. * bugfix of checking for extended type when emitting ':'
  723. Revision 1.7 1997/12/04 15:20:47 carl
  724. * esthetic bugfix with extdebug on.
  725. Revision 1.6 1997/12/03 13:46:40 carl
  726. * bugfix of my bug with near, now near in nasm mode for all non-rel8
  727. instructions. (jcxz,jecxz still does not work thoug - assumed short now).
  728. Revision 1.5 1997/12/02 15:52:26 carl
  729. * bugfix of string (again...) - would be sometimes invalid.
  730. * bugfix of segment overrides under nasm.
  731. - removed near in labeled instructions (would cause errors).
  732. Revision 1.4 1997/12/01 17:42:51 pierre
  733. + added some more functionnality to the assembler parser
  734. Revision 1.3 1997/11/28 18:14:36 pierre
  735. working version with several bug fixes
  736. Revision 1.2 1997/11/28 14:54:50 carl
  737. + added popfd instruction.
  738. Revision 1.1.1.1 1997/11/27 08:32:57 michael
  739. FPC Compiler CVS start
  740. Pre-CVS log:
  741. CEC Carl-Eric Codere
  742. FK Florian Klaempfl
  743. PM Pierre Muller
  744. + feature added
  745. - removed
  746. * bug fixed or changed
  747. History:
  748. 9th october 1997:
  749. * bugfix of string write, closing quotes would never be written. (CEC)
  750. 23 october 1997:
  751. * fixed problem with writing strings of length = 0 (CEC).
  752. + added line separation of long string chains. (CEC).
  753. 31st october 1997:
  754. + completed the table of opcodes. (CEC)
  755. 3rd november 1997:
  756. + MMX instructions added (FK)
  757. 9th november 1997:
  758. * movsb represented the AT&T movsx - fixed, absolute values
  759. in getreferencestring would be preceded by $ - fixed (CEC).
  760. What's to do:
  761. o Fix problems regarding the segment names under NASM
  762. o generate extern entries for typed constants and variables
  763. o write lines numbers and file names to output file
  764. o comments
  765. }