assemble.pas 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728
  1. {
  2. $Id$
  3. Copyright (c) 1998 by the FPC development team
  4. This unit handles the assemblerfile write and assembler calls of FPC
  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. unit assemble;
  18. interface
  19. uses
  20. dos,cobjects,globtype,globals,aasm;
  21. {$ifdef Ag386Bin}
  22. {$define NoAg386Att}
  23. {$define NoAg386Int}
  24. {$define NoAg386Nsm}
  25. {$endif}
  26. const
  27. {$ifdef tp}
  28. AsmOutSize=1024;
  29. {$else}
  30. AsmOutSize=32768;
  31. {$endif}
  32. type
  33. PAsmList=^TAsmList;
  34. TAsmList=object
  35. {filenames}
  36. path : pathstr;
  37. name : namestr;
  38. asmfile, { current .s and .o file }
  39. objfile,
  40. as_bin : string;
  41. IsEndFile : boolean; { special 'end' file for import dir ? }
  42. {outfile}
  43. AsmSize,
  44. AsmStartSize,
  45. outcnt : longint;
  46. outbuf : array[0..AsmOutSize-1] of char;
  47. outfile : file;
  48. Constructor Init;
  49. Destructor Done;
  50. Function FindAssembler:string;
  51. Function CallAssembler(const command,para:string):Boolean;
  52. Function DoAssemble:boolean;
  53. Procedure RemoveAsm;
  54. procedure NextSmartName;
  55. Procedure AsmFlush;
  56. Procedure AsmClear;
  57. Procedure AsmWrite(const s:string);
  58. Procedure AsmWritePChar(p:pchar);
  59. Procedure AsmWriteLn(const s:string);
  60. Procedure AsmLn;
  61. procedure AsmCreate;
  62. procedure AsmClose;
  63. procedure Synchronize;
  64. procedure WriteTree(p:paasmoutput);virtual;
  65. procedure WriteAsmList;virtual;
  66. end;
  67. Procedure GenerateAsm;
  68. Procedure OnlyAsm;
  69. var
  70. SmartLinkFilesCnt : longint;
  71. Implementation
  72. uses
  73. script,files,systems,verbose,comphook
  74. {$ifdef linux}
  75. ,linux
  76. {$endif}
  77. ,strings
  78. {$ifdef i386}
  79. {$ifdef Ag386Bin}
  80. ,ag386bin
  81. {$endif}
  82. {$ifndef NoAg386Att}
  83. ,ag386att
  84. {$endif NoAg386Att}
  85. {$ifndef NoAg386Nsm}
  86. ,ag386nsm
  87. {$endif NoAg386Nsm}
  88. {$ifndef NoAg386Int}
  89. ,ag386int
  90. {$endif NoAg386Int}
  91. {$ifdef Ag386Cof}
  92. ,ag386cof
  93. {$endif Ag386Cof}
  94. {$endif}
  95. {$ifdef m68k}
  96. {$ifndef NoAg68kGas}
  97. ,ag68kgas
  98. {$endif NoAg68kGas}
  99. {$ifndef NoAg68kMot}
  100. ,ag68kmot
  101. {$endif NoAg68kMot}
  102. {$ifndef NoAg68kMit}
  103. ,ag68kmit
  104. {$endif NoAg68kMit}
  105. {$ifndef NoAg68kMpw}
  106. ,ag68kmpw
  107. {$endif NoAg68kMpw}
  108. {$endif}
  109. ;
  110. {*****************************************************************************
  111. TAsmList
  112. *****************************************************************************}
  113. Function DoPipe:boolean;
  114. begin
  115. DoPipe:=(cs_asm_pipe in aktglobalswitches) and
  116. not(cs_asm_leave in aktglobalswitches)
  117. {$ifdef i386}
  118. and (aktoutputformat=as_i386_o)
  119. {$endif i386}
  120. {$ifdef m68k}
  121. and (aktoutputformat=as_m68k_o);
  122. {$endif m68k}
  123. end;
  124. const
  125. lastas : byte=255;
  126. var
  127. LastASBin : string;
  128. Function TAsmList.FindAssembler:string;
  129. var
  130. asfound : boolean;
  131. begin
  132. if lastas<>ord(target_asm.id) then
  133. begin
  134. lastas:=ord(target_asm.id);
  135. { is an assembler passed ? }
  136. if utilsdirectory<>'' then
  137. begin
  138. LastASBin:=Search(target_asm.asmbin+source_os.exeext,
  139. utilsdirectory,asfound)+target_asm.asmbin+source_os.exeext;
  140. end
  141. else
  142. LastASBin:=FindExe(target_asm.asmbin,asfound);
  143. if (not asfound) and not(cs_asm_extern in aktglobalswitches) then
  144. begin
  145. Message1(exec_w_assembler_not_found,LastASBin);
  146. aktglobalswitches:=aktglobalswitches+[cs_asm_extern];
  147. end;
  148. if asfound then
  149. Message1(exec_t_using_assembler,LastASBin);
  150. end;
  151. FindAssembler:=LastASBin;
  152. end;
  153. Function TAsmList.CallAssembler(const command,para:string):Boolean;
  154. begin
  155. callassembler:=true;
  156. if not(cs_asm_extern in aktglobalswitches) then
  157. begin
  158. swapvectors;
  159. exec(command,para);
  160. swapvectors;
  161. if (doserror<>0) then
  162. begin
  163. Message1(exec_w_cant_call_assembler,tostr(doserror));
  164. aktglobalswitches:=aktglobalswitches+[cs_asm_extern];
  165. callassembler:=false;
  166. end
  167. else
  168. if (dosexitcode<>0) then
  169. begin
  170. Message1(exec_w_error_while_assembling,tostr(dosexitcode));
  171. callassembler:=false;
  172. end;
  173. end
  174. else
  175. AsmRes.AddAsmCommand(command,para,name);
  176. end;
  177. procedure TAsmList.RemoveAsm;
  178. var
  179. g : file;
  180. i : word;
  181. begin
  182. if cs_asm_leave in aktglobalswitches then
  183. exit;
  184. if cs_asm_extern in aktglobalswitches then
  185. AsmRes.AddDeleteCommand(AsmFile)
  186. else
  187. begin
  188. assign(g,AsmFile);
  189. {$I-}
  190. erase(g);
  191. {$I+}
  192. i:=ioresult;
  193. end;
  194. end;
  195. Function TAsmList.DoAssemble:boolean;
  196. var
  197. s : string;
  198. begin
  199. DoAssemble:=true;
  200. if DoPipe then
  201. exit;
  202. if (SmartLinkFilesCnt<=1) and not(cs_asm_extern in aktglobalswitches) then
  203. Message1(exec_i_assembling,name);
  204. s:=target_asm.asmcmd;
  205. Replace(s,'$ASM',AsmFile);
  206. Replace(s,'$OBJ',ObjFile);
  207. if CallAssembler(FindAssembler,s) then
  208. RemoveAsm
  209. else
  210. begin
  211. DoAssemble:=false;
  212. inc(status.errorcount);
  213. end;
  214. end;
  215. procedure TAsmList.NextSmartName;
  216. var
  217. s : string;
  218. begin
  219. inc(SmartLinkFilesCnt);
  220. if SmartLinkFilesCnt>999999 then
  221. Message(assem_f_too_many_asm_files);
  222. if IsEndFile then
  223. begin
  224. s:=current_module^.asmprefix^+'e';
  225. IsEndFile:=false;
  226. end
  227. else
  228. s:=current_module^.asmprefix^;
  229. AsmFile:=Path+FixFileName(s+tostr(SmartLinkFilesCnt)+target_info.asmext);
  230. ObjFile:=Path+FixFileName(s+tostr(SmartLinkFilesCnt)+target_info.objext);
  231. end;
  232. {*****************************************************************************
  233. TAsmList AsmFile Writing
  234. *****************************************************************************}
  235. Procedure TAsmList.AsmFlush;
  236. begin
  237. if outcnt>0 then
  238. begin
  239. BlockWrite(outfile,outbuf,outcnt);
  240. outcnt:=0;
  241. end;
  242. end;
  243. Procedure TAsmList.AsmClear;
  244. begin
  245. outcnt:=0;
  246. end;
  247. Procedure TAsmList.AsmWrite(const s:string);
  248. begin
  249. if OutCnt+length(s)>=AsmOutSize then
  250. AsmFlush;
  251. Move(s[1],OutBuf[OutCnt],length(s));
  252. inc(OutCnt,length(s));
  253. inc(AsmSize,length(s));
  254. end;
  255. Procedure TAsmList.AsmWriteLn(const s:string);
  256. begin
  257. AsmWrite(s);
  258. AsmLn;
  259. end;
  260. Procedure TAsmList.AsmWritePChar(p:pchar);
  261. var
  262. i,j : longint;
  263. begin
  264. i:=StrLen(p);
  265. j:=i;
  266. while j>0 do
  267. begin
  268. i:=min(j,AsmOutSize);
  269. if OutCnt+i>=AsmOutSize then
  270. AsmFlush;
  271. Move(p[0],OutBuf[OutCnt],i);
  272. inc(OutCnt,i);
  273. inc(AsmSize,i);
  274. dec(j,i);
  275. p:=pchar(@p[i]);
  276. end;
  277. end;
  278. Procedure TAsmList.AsmLn;
  279. begin
  280. if OutCnt>=AsmOutSize-2 then
  281. AsmFlush;
  282. OutBuf[OutCnt]:=target_os.newline[1];
  283. inc(OutCnt);
  284. inc(AsmSize);
  285. if length(target_os.newline)>1 then
  286. begin
  287. OutBuf[OutCnt]:=target_os.newline[2];
  288. inc(OutCnt);
  289. inc(AsmSize);
  290. end;
  291. end;
  292. procedure TAsmList.AsmCreate;
  293. begin
  294. if (cs_smartlink in aktmoduleswitches) then
  295. NextSmartName;
  296. {$ifdef linux}
  297. if DoPipe then
  298. begin
  299. Message1(exec_i_assembling_pipe,asmfile);
  300. POpen(outfile,'as -o '+objfile,'W');
  301. end
  302. else
  303. {$endif}
  304. begin
  305. Assign(outfile,asmfile);
  306. {$I-}
  307. Rewrite(outfile,1);
  308. {$I+}
  309. if ioresult<>0 then
  310. Message1(exec_d_cant_create_asmfile,asmfile);
  311. end;
  312. outcnt:=0;
  313. AsmSize:=0;
  314. AsmStartSize:=0;
  315. end;
  316. procedure TAsmList.AsmClose;
  317. var
  318. f : file;
  319. l : longint;
  320. begin
  321. AsmFlush;
  322. {$ifdef linux}
  323. if DoPipe then
  324. Close(outfile)
  325. else
  326. {$endif}
  327. begin
  328. {Touch Assembler time to ppu time is there is a ppufilename}
  329. if Assigned(current_module^.ppufilename) then
  330. begin
  331. Assign(f,current_module^.ppufilename^);
  332. {$I-}
  333. reset(f,1);
  334. {$I+}
  335. if ioresult=0 then
  336. begin
  337. getftime(f,l);
  338. close(f);
  339. reset(outfile,1);
  340. setftime(outfile,l);
  341. end;
  342. end;
  343. close(outfile);
  344. end;
  345. end;
  346. {Touch Assembler and object time to ppu time is there is a ppufilename}
  347. procedure TAsmList.Synchronize;
  348. var
  349. f : file;
  350. l : longint;
  351. begin
  352. {Touch Assembler time to ppu time is there is a ppufilename}
  353. if Assigned(current_module^.ppufilename) then
  354. begin
  355. Assign(f,current_module^.ppufilename^);
  356. {$I-}
  357. reset(f,1);
  358. {$I+}
  359. if ioresult=0 then
  360. begin
  361. getftime(f,l);
  362. close(f);
  363. assign(f,asmfile);
  364. {$I-}
  365. reset(f,1);
  366. {$I+}
  367. if ioresult=0 then
  368. begin
  369. setftime(f,l);
  370. close(f);
  371. end;
  372. if not(cs_asm_extern in aktglobalswitches) then
  373. begin
  374. assign(f,objfile);
  375. {$I-}
  376. reset(f,1);
  377. {$I+}
  378. if ioresult=0 then
  379. begin
  380. setftime(f,l);
  381. close(f);
  382. end;
  383. end;
  384. end;
  385. end;
  386. end;
  387. procedure TAsmList.WriteTree(p:paasmoutput);
  388. begin
  389. end;
  390. procedure TAsmList.WriteAsmList;
  391. begin
  392. end;
  393. Constructor TAsmList.Init;
  394. var
  395. i : word;
  396. begin
  397. { load start values }
  398. asmfile:=current_module^.asmfilename^;
  399. objfile:=current_module^.objfilename^;
  400. name:=FixFileName(current_module^.modulename^);
  401. OutCnt:=0;
  402. SmartLinkFilesCnt:=0;
  403. IsEndFile:=false;
  404. { Which path will be used ? }
  405. if (cs_smartlink in aktmoduleswitches) then
  406. begin
  407. path:=current_module^.path^+FixFileName(current_module^.modulename^)+target_info.smartext;
  408. {$I-}
  409. mkdir(path);
  410. {$I+}
  411. i:=ioresult;
  412. path:=FixPath(path,false);
  413. end
  414. else
  415. path:=current_module^.path^;
  416. end;
  417. Destructor TAsmList.Done;
  418. begin
  419. end;
  420. {*****************************************************************************
  421. Generate Assembler Files Main Procedure
  422. *****************************************************************************}
  423. Procedure GenerateAsm;
  424. var
  425. a : PAsmList;
  426. {$ifdef i386}
  427. {$ifdef Ag386Bin}
  428. b : Pi386binasmlist;
  429. {$endif}
  430. {$endif}
  431. begin
  432. case aktoutputformat of
  433. {$ifdef i386}
  434. {$ifdef Ag386Bin}
  435. as_i386_dbg,
  436. as_i386_coff,
  437. as_i386_pecoff :
  438. begin
  439. case aktoutputformat of
  440. as_i386_dbg :
  441. b:=new(pi386binasmlist,Init(og_dbg));
  442. as_i386_coff :
  443. b:=new(pi386binasmlist,Init(og_coff));
  444. as_i386_pecoff :
  445. b:=new(pi386binasmlist,Init(og_pecoff));
  446. end;
  447. b^.WriteBin;
  448. dispose(b,done);
  449. exit;
  450. end;
  451. {$endif Ag386Bin}
  452. {$ifndef NoAg386Att}
  453. as_i386_o,
  454. as_i386_o_aout,
  455. as_i386_asw :
  456. a:=new(pi386attasmlist,Init);
  457. {$endif NoAg386Att}
  458. {$ifndef NoAg386Nsm}
  459. as_i386_nasmcoff,
  460. as_i386_nasmelf,
  461. as_i386_nasmobj :
  462. a:=new(pi386nasmasmlist,Init);
  463. {$endif NoAg386Nsm}
  464. {$ifndef NoAg386Int}
  465. as_i386_tasm :
  466. a:=new(pi386intasmlist,Init);
  467. {$endif NoAg386Int}
  468. {$endif}
  469. {$ifdef m68k}
  470. {$ifndef NoAg68kGas}
  471. as_m68k_o,
  472. as_m68k_gas :
  473. a:=new(pm68kgasasmlist,Init);
  474. {$endif NoAg86KGas}
  475. {$ifndef NoAg68kMot}
  476. as_m68k_mot :
  477. a:=new(pm68kmotasmlist,Init);
  478. {$endif NoAg86kMot}
  479. {$ifndef NoAg68kMit}
  480. as_m68k_mit :
  481. a:=new(pm68kmitasmlist,Init);
  482. {$endif NoAg86KMot}
  483. {$ifndef NoAg68kMpw}
  484. as_m68k_mpw :
  485. a:=new(pm68kmpwasmlist,Init);
  486. {$endif NoAg68kMpw}
  487. {$endif}
  488. else
  489. Message(assem_f_assembler_output_not_supported);
  490. end;
  491. a^.AsmCreate;
  492. a^.WriteAsmList;
  493. a^.AsmClose;
  494. a^.DoAssemble;
  495. a^.synchronize;
  496. dispose(a,Done);
  497. end;
  498. Procedure OnlyAsm;
  499. var
  500. a : PAsmList;
  501. begin
  502. a:=new(pasmlist,Init);
  503. a^.DoAssemble;
  504. dispose(a,Done);
  505. end;
  506. end.
  507. {
  508. $Log$
  509. Revision 1.37 1999-02-24 00:59:11 peter
  510. * small updates for ag386bin
  511. Revision 1.36 1999/02/22 02:15:01 peter
  512. * updates for ag386bin
  513. Revision 1.35 1999/02/17 10:16:26 peter
  514. * small fixes for the binary writer
  515. Revision 1.34 1999/01/10 15:37:52 peter
  516. * moved some tables from ra386*.pas -> i386.pas
  517. + start of coff writer
  518. * renamed asmutils unit to rautils
  519. Revision 1.33 1998/12/11 00:02:45 peter
  520. + globtype,tokens,version unit splitted from globals
  521. Revision 1.32 1998/11/06 09:46:46 pierre
  522. * assemble failure increments status errorcount again !!
  523. Revision 1.31 1998/10/26 22:23:28 peter
  524. + fixpath() has an extra option to allow a ./ as path
  525. Revision 1.30 1998/10/16 13:37:14 florian
  526. + switch -FD added to specify the path for utilities
  527. Revision 1.29 1998/10/15 16:19:42 peter
  528. * fixed asmsynchronize
  529. Revision 1.28 1998/10/14 15:56:43 pierre
  530. * all references to comp suppressed for m68k
  531. Revision 1.27 1998/10/13 16:50:01 pierre
  532. * undid some changes of Peter that made the compiler wrong
  533. for m68k (I had to reinsert some ifdefs)
  534. * removed several memory leaks under m68k
  535. * removed the meory leaks for assembler readers
  536. * cross compiling shoud work again better
  537. ( crosscompiling sysamiga works
  538. but as68k still complain about some code !)
  539. Revision 1.26 1998/10/13 13:10:11 peter
  540. * new style for m68k/i386 infos and enums
  541. Revision 1.25 1998/10/13 08:19:24 pierre
  542. + source_os is now set correctly for cross-processor compilers
  543. (tos contains all target_infos and
  544. we use CPU86 and CPU68 conditionnals to
  545. get the source operating system
  546. this only works if you do not undefine
  547. the source target !!)
  548. * several cg68k memory leaks fixed
  549. + started to change the code so that it should be possible to have
  550. a complete compiler (both for m68k and i386 !!)
  551. Revision 1.24 1998/10/08 23:28:50 peter
  552. * -vu shows unit info, -vt shows tried/used files
  553. Revision 1.23 1998/10/07 04:27:37 carl
  554. + MPW support
  555. Revision 1.22 1998/09/16 16:41:39 peter
  556. * merged fixes
  557. Revision 1.21.2.1 1998/09/16 16:11:38 peter
  558. * missing isendfile reset in .init
  559. Revision 1.21 1998/09/07 18:33:32 peter
  560. + smartlinking for win95 imports
  561. Revision 1.20 1998/09/04 17:34:20 pierre
  562. * bug with datalabel corrected
  563. + assembler errors better commented
  564. * one nested record crash removed
  565. Revision 1.19 1998/08/26 10:06:34 peter
  566. * reduce amount of asmfiles generated
  567. * no stabs are written in writefilelineinfo when debuginfo is off
  568. Revision 1.18 1998/08/21 14:08:39 pierre
  569. + TEST_FUNCRET now default (old code removed)
  570. works also for m68k (at least compiles)
  571. Revision 1.17 1998/08/17 09:17:43 peter
  572. * static/shared linking updates
  573. Revision 1.16 1998/08/14 21:56:30 peter
  574. * setting the outputfile using -o works now to create static libs
  575. Revision 1.15 1998/08/14 18:16:09 peter
  576. * return after a failed call will now add it to ppas
  577. Revision 1.14 1998/08/10 14:49:41 peter
  578. + localswitches, moduleswitches, globalswitches splitting
  579. Revision 1.13 1998/07/14 21:46:40 peter
  580. * updated messages file
  581. Revision 1.12 1998/07/08 14:58:34 daniel
  582. * First check if call to assembler is succesfull, then check it's exit code.
  583. This is more logical than first checking the exit code. For some mysterious
  584. reason this did not give problems on DOS & Linux. On OS/2 it did.
  585. Revision 1.11 1998/06/08 22:59:43 peter
  586. * smartlinking works for win32
  587. * some defines to exclude some compiler parts
  588. Revision 1.10 1998/06/04 23:51:33 peter
  589. * m68k compiles
  590. + .def file creation moved to gendef.pas so it could also be used
  591. for win32
  592. Revision 1.9 1998/05/23 01:21:01 peter
  593. + aktasmmode, aktoptprocessor, aktoutputformat
  594. + smartlink per module $SMARTLINK-/+ (like MMX) and moved to aktswitches
  595. + $LIBNAME to set the library name where the unit will be put in
  596. * splitted cgi386 a bit (codeseg to large for bp7)
  597. * nasm, tasm works again. nasm moved to ag386nsm.pas
  598. Revision 1.8 1998/05/11 13:07:53 peter
  599. + $ifdef NEWPPU for the new ppuformat
  600. + $define GDB not longer required
  601. * removed all warnings and stripped some log comments
  602. * no findfirst/findnext anymore to remove smartlink *.o files
  603. Revision 1.7 1998/05/07 00:17:00 peter
  604. * smartlinking for sets
  605. + consts labels are now concated/generated in hcodegen
  606. * moved some cpu code to cga and some none cpu depended code from cga
  607. to tree and hcodegen and cleanup of hcodegen
  608. * assembling .. output reduced for smartlinking ;)
  609. Revision 1.6 1998/05/04 17:54:24 peter
  610. + smartlinking works (only case jumptable left todo)
  611. * redesign of systems.pas to support assemblers and linkers
  612. + Unitname is now also in the PPU-file, increased version to 14
  613. Revision 1.5 1998/04/29 10:33:44 pierre
  614. + added some code for ansistring (not complete nor working yet)
  615. * corrected operator overloading
  616. * corrected nasm output
  617. + started inline procedures
  618. + added starstarn : use ** for exponentiation (^ gave problems)
  619. + started UseTokenInfo cond to get accurate positions
  620. Revision 1.4 1998/04/27 23:10:27 peter
  621. + new scanner
  622. * $makelib -> if smartlink
  623. * small filename fixes pmodule.setfilename
  624. * moved import from files.pas -> import.pas
  625. Revision 1.3 1998/04/10 14:41:43 peter
  626. * removed some Hints
  627. * small speed optimization for AsmLn
  628. Revision 1.2 1998/04/08 11:34:18 peter
  629. * nasm works (linux only tested)
  630. }