mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-12 19:09:35 +02:00

ADD ADC and AND are also sign extended nasm output OK (program still crashes at end and creates wrong assembler files !!) procsym types sym in tdef removed !!
809 lines
30 KiB
ObjectPascal
809 lines
30 KiB
ObjectPascal
{
|
|
$Id$
|
|
Copyright (c) 1996,97 by Florian Klaempfl
|
|
|
|
This unit implements an asmoutput class for Intel syntax with Intel i386+
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
****************************************************************************
|
|
}
|
|
unit ag386int;
|
|
|
|
interface
|
|
|
|
uses aasm,assemble;
|
|
|
|
type
|
|
pi386intasmlist=^ti386intasmlist;
|
|
ti386intasmlist = object(tasmlist)
|
|
procedure WriteTree(p:paasmoutput);virtual;
|
|
procedure WriteAsmList;virtual;
|
|
end;
|
|
|
|
implementation
|
|
|
|
uses
|
|
dos,globals,systems,cobjects,i386,
|
|
strings,files,verbose
|
|
{$ifdef GDB}
|
|
,gdb
|
|
{$endif GDB}
|
|
;
|
|
|
|
const
|
|
line_length = 70;
|
|
|
|
extstr : array[EXT_NEAR..EXT_ABS] of String[8] =
|
|
('NEAR','FAR','PROC','BYTE','WORD','DWORD',
|
|
'CODEPTR','DATAPTR','FWORD','PWORD','QWORD','TBYTE','ABS');
|
|
|
|
function getreferencestring(const ref : treference) : string;
|
|
var
|
|
s : string;
|
|
first : boolean;
|
|
begin
|
|
if ref.isintvalue then
|
|
s:= tostr(ref.offset)
|
|
else
|
|
{$ifdef ver0_6}
|
|
begin
|
|
first:=true;
|
|
{ have we a segment prefix ? }
|
|
if ref.segment<>R_DEFAULT_SEG then
|
|
begin
|
|
if current_module^.output_format in [of_nasm,of_obj] then
|
|
s:='['+_reg2str[ref.segment]+':'
|
|
else
|
|
s:=_reg2str[ref.segment]+':[';
|
|
end
|
|
else s:='[';
|
|
|
|
if assigned(ref.symbol) then
|
|
begin
|
|
s:=s+ref.symbol^;
|
|
first:=false;
|
|
end;
|
|
if (ref.base<>R_NO) then
|
|
begin
|
|
if not(first) then
|
|
s:=s+'+'
|
|
else
|
|
first:=false;
|
|
s:=s+_reg2str[ref.base];
|
|
end;
|
|
if (ref.index<>R_NO) then
|
|
begin
|
|
if not(first) then
|
|
s:=s+'+'
|
|
else
|
|
first:=false;
|
|
s:=s+_reg2str[ref.index];
|
|
if ref.scalefactor<>0 then
|
|
s:=s+'*'+tostr(ref.scalefactor);
|
|
end;
|
|
if ref.offset<0 then
|
|
s:=s+tostr(ref.offset)
|
|
else if (ref.offset>0) then
|
|
s:=s+'+'+tostr(ref.offset);
|
|
s:=s+']';
|
|
end;
|
|
{$else}
|
|
with ref do
|
|
begin
|
|
first:=true;
|
|
if ref.segment<>R_DEFAULT_SEG then
|
|
begin
|
|
if current_module^.output_format in [of_nasm,of_obj] then
|
|
s:='['+int_reg2str[segment]+':'
|
|
else
|
|
s:=int_reg2str[segment]+':[';
|
|
end
|
|
else
|
|
s:='[';
|
|
|
|
if assigned(symbol) then
|
|
begin
|
|
s:=s+symbol^;
|
|
first:=false;
|
|
end;
|
|
if (base<>R_NO) then
|
|
begin
|
|
if not(first) then
|
|
s:=s+'+'
|
|
else
|
|
first:=false;
|
|
s:=s+int_reg2str[base];
|
|
end;
|
|
if (index<>R_NO) then
|
|
begin
|
|
if not(first) then
|
|
s:=s+'+'
|
|
else
|
|
first:=false;
|
|
s:=s+int_reg2str[index];
|
|
if scalefactor<>0 then
|
|
s:=s+'*'+tostr(scalefactor);
|
|
end;
|
|
if offset<0 then
|
|
s:=s+tostr(offset)
|
|
else if (offset>0) then
|
|
s:=s+'+'+tostr(offset);
|
|
s:=s+']';
|
|
end;
|
|
{$endif}
|
|
getreferencestring:=s;
|
|
end;
|
|
|
|
function getopstr(t : byte;o : pointer;s : topsize; _operator: tasmop;dest : boolean) : string;
|
|
|
|
var
|
|
hs : string;
|
|
|
|
begin
|
|
case t of
|
|
top_reg : { a floating point register can be only a register operand }
|
|
if current_module^.output_format in [of_nasm,of_obj] then
|
|
getopstr:=int_nasmreg2str[tregister(o)]
|
|
else
|
|
getopstr:=int_reg2str[tregister(o)];
|
|
top_const,
|
|
top_ref : begin
|
|
if t=top_const then
|
|
hs := tostr(longint(o))
|
|
else
|
|
hs:=getreferencestring(preference(o)^);
|
|
if current_module^.output_format in [of_nasm,of_obj] then
|
|
if (_operator = A_LEA) or (_operator = A_LGS)
|
|
or (_operator = A_LSS) or (_operator = A_LFS)
|
|
or (_operator = A_LES) or (_operator = A_LDS)
|
|
or (_operator = A_SHR) or (_operator = A_SHL)
|
|
or (_operator = A_SAR) or (_operator = A_SAL)
|
|
or (_operator = A_OUT) or (_operator = A_IN) then
|
|
begin
|
|
end
|
|
else
|
|
case s of
|
|
S_B : hs:='byte '+hs;
|
|
S_W : hs:='word '+hs;
|
|
S_L : hs:='dword '+hs;
|
|
S_S : hs:='dword '+hs;
|
|
S_Q : hs:='qword '+hs;
|
|
S_X : if current_module^.output_format in [of_nasm,of_obj] then
|
|
hs:='tword '+hs
|
|
else
|
|
hs:='tbyte '+hs;
|
|
S_BW : if dest then
|
|
hs:='word '+hs
|
|
else
|
|
hs:='byte '+hs;
|
|
S_BL : if dest then
|
|
hs:='dword '+hs
|
|
else
|
|
hs:='byte '+hs;
|
|
S_WL : if dest then
|
|
hs:='dword '+hs
|
|
else
|
|
hs:='word '+hs;
|
|
end
|
|
else
|
|
Begin
|
|
{ can possibly give a range check error under tp }
|
|
{ if using in... }
|
|
if ((_operator <> A_LGS) and (_operator <> A_LSS) and
|
|
(_operator <> A_LFS) and (_operator <> A_LDS) and
|
|
(_operator <> A_LES)) then
|
|
Begin
|
|
case s of
|
|
S_B : hs:='byte ptr '+hs;
|
|
S_W : hs:='word ptr '+hs;
|
|
S_L : hs:='dword ptr '+hs;
|
|
S_BW : if dest then
|
|
hs:='word ptr '+hs
|
|
else
|
|
hs:='byte ptr '+hs;
|
|
S_BL : if dest then
|
|
hs:='dword ptr '+hs
|
|
else
|
|
hs:='byte ptr '+hs;
|
|
S_WL : if dest then
|
|
hs:='dword ptr '+hs
|
|
else
|
|
hs:='word ptr '+hs;
|
|
end;
|
|
end;
|
|
end;
|
|
getopstr:=hs;
|
|
end;
|
|
top_symbol : begin
|
|
hs[0]:=chr(strlen(pchar(pcsymbol(o)^.symbol)));
|
|
move(pchar(pcsymbol(o)^.symbol)^,hs[1],byte(hs[0]));
|
|
if current_module^.output_format=of_masm then
|
|
hs:='offset '+hs
|
|
else
|
|
hs:='dword '+hs;
|
|
|
|
if pcsymbol(o)^.offset>0 then
|
|
hs:=hs+'+'+tostr(pcsymbol(o)^.offset)
|
|
else if pcsymbol(o)^.offset<0 then
|
|
hs:=hs+tostr(pcsymbol(o)^.offset);
|
|
getopstr:=hs;
|
|
end;
|
|
else internalerror(10001);
|
|
end;
|
|
end;
|
|
|
|
function getopstr_jmp(t : byte;o : pointer) : string;
|
|
|
|
var
|
|
hs : string;
|
|
|
|
begin
|
|
case t of
|
|
top_reg : getopstr_jmp:=int_reg2str[tregister(o)];
|
|
top_ref : getopstr_jmp:=getreferencestring(preference(o)^);
|
|
top_const : getopstr_jmp:=tostr(longint(o));
|
|
top_symbol : begin
|
|
hs[0]:=chr(strlen(pchar(pcsymbol(o)^.symbol)));
|
|
move(pchar(pcsymbol(o)^.symbol)^,hs[1],byte(hs[0]));
|
|
if pcsymbol(o)^.offset>0 then
|
|
hs:=hs+'+'+tostr(pcsymbol(o)^.offset)
|
|
else if pcsymbol(o)^.offset<0 then
|
|
hs:=hs+tostr(pcsymbol(o)^.offset);
|
|
getopstr_jmp:=hs;
|
|
end;
|
|
else internalerror(10001);
|
|
end;
|
|
end;
|
|
|
|
{****************************************************************************
|
|
TI386INTASMLIST
|
|
****************************************************************************}
|
|
|
|
const
|
|
ait_const2str:array[ait_const_32bit..ait_const_8bit] of string[8]=
|
|
(#9'DD'#9,'',#9'DW'#9,#9'DB'#9);
|
|
|
|
Function PadTabs(p:pchar;addch:char):string;
|
|
var
|
|
s : string;
|
|
i : longint;
|
|
begin
|
|
i:=strlen(p);
|
|
if addch<>#0 then
|
|
begin
|
|
inc(i);
|
|
s:=StrPas(p)+addch;
|
|
end
|
|
else
|
|
s:=StrPas(p);
|
|
if i<8 then
|
|
PadTabs:=s+#9#9
|
|
else
|
|
PadTabs:=s+#9;
|
|
end;
|
|
|
|
procedure ti386intasmlist.WriteTree(p:paasmoutput);
|
|
type
|
|
twowords=record
|
|
word1,word2:word;
|
|
end;
|
|
var
|
|
s,
|
|
prefix,
|
|
suffix : string;
|
|
hp : pai;
|
|
counter,
|
|
lines,
|
|
i,j,l : longint;
|
|
consttyp : tait;
|
|
found,
|
|
quoted : boolean;
|
|
begin
|
|
hp:=pai(p^.first);
|
|
while assigned(hp) do
|
|
begin
|
|
case hp^.typ of
|
|
ait_comment : ;
|
|
ait_align : begin
|
|
{ align not supported at all with nasm v095 }
|
|
{ align with specific value not supported by }
|
|
{ turbo assembler. }
|
|
{ CAUSES PROBLEMS WITH THE SEGMENT DEFINITION }
|
|
{ SEGMENT DEFINITION SHOULD MATCH TYPE OF ALIGN }
|
|
{ HERE UNDER TASM! }
|
|
{ if current_module^.output_format<>of_nasm then
|
|
AsmWriteLn(#9'ALIGN '+tostr(pai_align(hp)^.aligntype));}
|
|
end;
|
|
ait_external : begin
|
|
if current_module^.output_format in [of_nasm,of_obj] then
|
|
AsmWriteLn('EXTERN '+StrPas(pai_external(hp)^.name))
|
|
else
|
|
AsmWriteLn(#9#9'EXTRN'#9+StrPas(pai_external(hp)^.name)+
|
|
' :'+extstr[pai_external(hp)^.exttyp]);
|
|
end;
|
|
ait_datablock : begin
|
|
if current_module^.output_format in [of_nasm,of_obj] then
|
|
begin
|
|
if pai_datablock(hp)^.is_global then
|
|
AsmWriteLn('GLOBAL '+StrPas(pai_datablock(hp)^.name));
|
|
AsmWriteLn(PadTabs(pai_datablock(hp)^.name,':')+'RESB'#9+tostr(pai_datablock(hp)^.size));
|
|
end
|
|
else
|
|
begin
|
|
if pai_datablock(hp)^.is_global then
|
|
AsmWriteLn(#9#9'PUBLIC'#9+StrPas(pai_datablock(hp)^.name));
|
|
AsmWriteLn(PadTabs(pai_datablock(hp)^.name,#0)+'DB'#9+tostr(pai_datablock(hp)^.size)+' DUP(?)');
|
|
end;
|
|
end;
|
|
ait_const_32bit,
|
|
ait_const_8bit,
|
|
ait_const_16bit : begin
|
|
AsmWrite(ait_const2str[hp^.typ]+tostr(pai_const(hp)^.value));
|
|
consttyp:=hp^.typ;
|
|
l:=0;
|
|
repeat
|
|
found:=(not (Pai(hp^.next)=nil)) and (Pai(hp^.next)^.typ=consttyp);
|
|
if found then
|
|
begin
|
|
hp:=Pai(hp^.next);
|
|
s:=','+tostr(pai_const(hp)^.value);
|
|
AsmWrite(s);
|
|
inc(l,length(s));
|
|
end;
|
|
until (not found) or (l>line_length);
|
|
AsmLn;
|
|
end;
|
|
ait_const_symbol : begin
|
|
if current_module^.output_format<>of_nasm then
|
|
AsmWrite(#9#9+'DD '#9'offset ')
|
|
else
|
|
AsmWrite(#9#9+'DD '#9);
|
|
AsmWriteLn(StrPas(pchar(pai_const(hp)^.value)));
|
|
end;
|
|
ait_real_32bit : AsmWriteLn(#9#9'DD'#9+double2str(pai_single(hp)^.value));
|
|
ait_real_64bit : AsmWriteLn(#9#9'DQ'#9+double2str(pai_double(hp)^.value));
|
|
ait_real_extended : begin
|
|
{ nasm v095 does not like DT with real constants }
|
|
{ therefore write as double. }
|
|
{ other possible solution: decode directly to hex}
|
|
{ value. }
|
|
if current_module^.output_format<>of_nasm then
|
|
AsmWriteLn(#9#9'DT'#9+double2str(pai_extended(hp)^.value))
|
|
else
|
|
begin
|
|
{$ifdef EXTDEBUG}
|
|
AsmLn;
|
|
AsmWriteLn('; NASM bug work around for extended real');
|
|
{$endif}
|
|
AsmWriteLn(#9#9'DD'#9+double2str(pai_extended(hp)^.value))
|
|
end;
|
|
end;
|
|
ait_comp : AsmWriteLn(#9#9'DQ'#9+comp2str(pai_extended(hp)^.value));
|
|
ait_string : begin
|
|
counter := 0;
|
|
lines := pai_string(hp)^.len div line_length;
|
|
{ separate lines in different parts }
|
|
if pai_string(hp)^.len > 0 then
|
|
Begin
|
|
for j := 0 to lines-1 do
|
|
begin
|
|
AsmWrite(#9#9'DB'#9);
|
|
quoted:=false;
|
|
for i:=counter to counter+line_length do
|
|
begin
|
|
{ it is an ascii character. }
|
|
if (ord(pai_string(hp)^.str[i])>31) and
|
|
(ord(pai_string(hp)^.str[i])<128) and
|
|
(pai_string(hp)^.str[i]<>'"') then
|
|
begin
|
|
if not(quoted) then
|
|
begin
|
|
if i>counter then
|
|
AsmWrite(',');
|
|
AsmWrite('"');
|
|
end;
|
|
AsmWrite(pai_string(hp)^.str[i]);
|
|
quoted:=true;
|
|
end { if > 31 and < 128 and ord('"') }
|
|
else
|
|
begin
|
|
if quoted then
|
|
AsmWrite('"');
|
|
if i>counter then
|
|
AsmWrite(',');
|
|
quoted:=false;
|
|
AsmWrite(tostr(ord(pai_string(hp)^.str[i])));
|
|
end;
|
|
end; { end for i:=0 to... }
|
|
if quoted then AsmWrite('"');
|
|
AsmWrite(target_info.newline);
|
|
counter := counter+line_length;
|
|
end; { end for j:=0 ... }
|
|
{ do last line of lines }
|
|
AsmWrite(#9#9'DB'#9);
|
|
quoted:=false;
|
|
for i:=counter to pai_string(hp)^.len-1 do
|
|
begin
|
|
{ it is an ascii character. }
|
|
if (ord(pai_string(hp)^.str[i])>31) and
|
|
(ord(pai_string(hp)^.str[i])<128) and
|
|
(pai_string(hp)^.str[i]<>'"') then
|
|
begin
|
|
if not(quoted) then
|
|
begin
|
|
if i>counter then
|
|
AsmWrite(',');
|
|
AsmWrite('"');
|
|
end;
|
|
AsmWrite(pai_string(hp)^.str[i]);
|
|
quoted:=true;
|
|
end { if > 31 and < 128 and " }
|
|
else
|
|
begin
|
|
if quoted then
|
|
AsmWrite('"');
|
|
if i>counter then
|
|
AsmWrite(',');
|
|
quoted:=false;
|
|
AsmWrite(tostr(ord(pai_string(hp)^.str[i])));
|
|
end;
|
|
end; { end for i:=0 to... }
|
|
if quoted then
|
|
AsmWrite('"');
|
|
end;
|
|
AsmLn;
|
|
end;
|
|
ait_label : begin
|
|
AsmWrite(lab2str(pai_label(hp)^.l));
|
|
if (current_module^.output_format in [of_obj,of_nasm]) or
|
|
(assigned(hp^.next) and not(pai(hp^.next)^.typ in
|
|
[ait_const_32bit,ait_const_16bit,ait_const_8bit,ait_const_symbol,
|
|
ait_real_32bit,ait_real_64bit,ait_real_extended,ait_string])) then
|
|
AsmWriteLn(':');
|
|
end;
|
|
ait_direct : begin
|
|
AsmWritePChar(pai_direct(hp)^.str);
|
|
AsmLn;
|
|
end;
|
|
ait_labeled_instruction :
|
|
begin
|
|
if (current_module^.output_format in [of_nasm,of_obj]) and
|
|
not (pai_labeled(hp)^._operator in [A_JMP,A_LOOP,A_LOOPZ,A_LOOPE,
|
|
A_LOOPNZ,A_LOOPNE,A_JCXZ,A_JECXZ]) then
|
|
AsmWriteLn(#9#9+int_op2str[pai_labeled(hp)^._operator]+#9+'near '+lab2str(pai_labeled(hp)^.lab))
|
|
else
|
|
AsmWriteLn(#9#9+int_op2str[pai_labeled(hp)^._operator]+#9+lab2str(pai_labeled(hp)^.lab));
|
|
end;
|
|
ait_symbol : begin
|
|
if pai_symbol(hp)^.is_global then
|
|
begin
|
|
if current_module^.output_format in [of_nasm,of_obj] then
|
|
AsmWriteLn('GLOBAL '+StrPas(pai_symbol(hp)^.name))
|
|
else
|
|
AsmWriteLn(#9#9'PUBLIC'#9+StrPas(pai_symbol(hp)^.name));
|
|
end;
|
|
AsmWritePChar(pai_symbol(hp)^.name);
|
|
if assigned(hp^.next) and not(pai(hp^.next)^.typ in
|
|
[ait_const_32bit,ait_const_16bit,ait_const_8bit,ait_const_symbol,
|
|
ait_real_64bit,ait_string]) then
|
|
AsmWriteLn(':')
|
|
end;
|
|
ait_instruction : begin
|
|
suffix:='';
|
|
prefix:= '';
|
|
{ added prefix instructions, must be on same line as opcode }
|
|
if (pai386(hp)^.op1t = top_none) and
|
|
((pai386(hp)^._operator = A_REP) or
|
|
(pai386(hp)^._operator = A_LOCK) or
|
|
(pai386(hp)^._operator = A_REPE) or
|
|
(pai386(hp)^._operator = A_REPNE)) then
|
|
Begin
|
|
prefix:=int_op2str[pai386(hp)^._operator]+#9;
|
|
hp:=Pai(hp^.next);
|
|
{ this is theorically impossible... }
|
|
if hp=nil then
|
|
begin
|
|
s:=#9#9+prefix;
|
|
AsmWriteLn(s);
|
|
break;
|
|
end;
|
|
{ nasm prefers prefix on a line alone }
|
|
if (current_module^.output_format in [of_nasm,of_obj]) then
|
|
begin
|
|
AsmWriteln(#9#9+prefix);
|
|
prefix:='';
|
|
end;
|
|
end
|
|
else
|
|
prefix:= '';
|
|
{ A_FNSTS need the w as suffix at least for nasm}
|
|
if (current_module^.output_format in [of_nasm,of_obj]) then
|
|
if (pai386(hp)^._operator = A_FNSTS) then
|
|
pai386(hp)^._operator:=A_FNSTSW
|
|
else if (pai386(hp)^._operator = A_FSTS) then
|
|
pai386(hp)^._operator:=A_FSTSW;
|
|
if pai386(hp)^.op1t<>top_none then
|
|
begin
|
|
if pai386(hp)^._operator in [A_CALL] then
|
|
begin
|
|
if output_format=of_nasm then
|
|
s:=getopstr_jmp(pai386(hp)^.op1t,pai386(hp)^.op1)
|
|
else
|
|
s:='near ptr '+getopstr_jmp(pai386(hp)^.op1t,pai386(hp)^.op1);
|
|
end
|
|
else
|
|
begin
|
|
s:=getopstr(pai386(hp)^.op1t,pai386(hp)^.op1,pai386(hp)^.size,pai386(hp)^._operator,false);
|
|
if pai386(hp)^.op3t<>top_none then
|
|
begin
|
|
if pai386(hp)^.op2t<>top_none then
|
|
s:=getopstr(pai386(hp)^.op2t,pointer(longint(twowords(pai386(hp)^.op2).word1)),
|
|
pai386(hp)^.size,pai386(hp)^._operator,true)+','+s;
|
|
s:=getopstr(pai386(hp)^.op3t,pointer(longint(twowords(pai386(hp)^.op2).word2)),
|
|
pai386(hp)^.size,pai386(hp)^._operator,false)+','+s;
|
|
end
|
|
else
|
|
if pai386(hp)^.op2t<>top_none then
|
|
s:=getopstr(pai386(hp)^.op2t,pai386(hp)^.op2,pai386(hp)^.size,
|
|
pai386(hp)^._operator,true)+','+s;
|
|
end;
|
|
s:=#9+s;
|
|
end
|
|
else
|
|
begin
|
|
{ check if string instruction }
|
|
{ long form, otherwise may give range check errors }
|
|
{ in turbo pascal... }
|
|
if ((pai386(hp)^._operator = A_CMPS) or
|
|
(pai386(hp)^._operator = A_INS) or
|
|
(pai386(hp)^._operator = A_OUTS) or
|
|
(pai386(hp)^._operator = A_SCAS) or
|
|
(pai386(hp)^._operator = A_STOS) or
|
|
(pai386(hp)^._operator = A_MOVS) or
|
|
(pai386(hp)^._operator = A_LODS) or
|
|
(pai386(hp)^._operator = A_XLAT)) then
|
|
Begin
|
|
case pai386(hp)^.size of
|
|
S_B: suffix:='b';
|
|
S_W: suffix:='w';
|
|
S_L: suffix:='d';
|
|
else
|
|
Message(assem_f_invalid_suffix_intel);
|
|
end;
|
|
end;
|
|
s:='';
|
|
end;
|
|
AsmWriteLn(#9#9+prefix+int_op2str[pai386(hp)^._operator]+suffix+s);
|
|
end;
|
|
{$ifdef GDB}
|
|
ait_stabn,
|
|
ait_stabs,
|
|
ait_stab_function_name : ;
|
|
{$endif GDB}
|
|
else
|
|
internalerror(10000);
|
|
end;
|
|
hp:=pai(hp^.next);
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure ti386intasmlist.WriteAsmList;
|
|
begin
|
|
{$ifdef EXTDEBUG}
|
|
if assigned(current_module^.mainsource) then
|
|
comment(v_info,'Start writing intel-styled assembler output for '+current_module^.mainsource^);
|
|
{$endif}
|
|
if current_module^.output_format in [of_nasm,of_obj] then
|
|
begin
|
|
WriteTree(externals);
|
|
{ INTEL ASM doesn't support stabs
|
|
WriteTree(debuglist);}
|
|
|
|
AsmWriteLn('BITS 32');
|
|
AsmWriteLn('SECTION .text');
|
|
{
|
|
AsmWriteLn(#9#9'ASSUME'#9'CS:_TEXT,ES:DGROUP,DS:DGROUP,SS:DGROUP');
|
|
}
|
|
WriteTree(codesegment);
|
|
|
|
AsmLn;
|
|
AsmWriteLn('SECTION .data');
|
|
{$ifdef EXTDEBUG}
|
|
AsmWriteLn(#9#9'DB'#9'"compiled by FPC '+version_string+'\0"');
|
|
AsmWriteLn(#9#9'DB'#9'"target: '+target_info.target_name+'\0"');
|
|
{$endif EXTDEBUG}
|
|
WriteTree(datasegment);
|
|
WriteTree(consts);
|
|
|
|
AsmLn;
|
|
AsmWriteLn('SECTION .bss');
|
|
WriteTree(bsssegment);
|
|
end
|
|
else
|
|
begin
|
|
AsmWriteLn('.386p');
|
|
|
|
WriteTree(externals);
|
|
{ INTEL ASM doesn't support stabs
|
|
WriteTree(debuglist);}
|
|
|
|
AsmWriteLn('DGROUP'#9#9'GROUP'#9'_BSS,_DATA');
|
|
AsmWriteLn('_TEXT'#9#9'SEGMENT'#9'BYTE PUBLIC USE32 ''CODE''');
|
|
AsmWriteLn(#9#9'ASSUME'#9'CS:_TEXT,ES:DGROUP,DS:DGROUP,SS:DGROUP');
|
|
AsmLn;
|
|
WriteTree(codesegment);
|
|
AsmWriteLn('_TEXT'#9#9'ENDS');
|
|
|
|
AsmLn;
|
|
AsmWriteLn('_DATA'#9#9'SEGMENT'#9'DWORD PUBLIC USE32 ''DATA''');
|
|
{$ifdef EXTDEBUG}
|
|
AsmWriteLn(#9#9'DB'#9'"compiled by FPC '+version_string+'\0"');
|
|
AsmWriteLn(#9#9'DB'#9'"target: '+target_info.target_name+'\0"');
|
|
{$endif EXTDEBUG}
|
|
WriteTree(datasegment);
|
|
WriteTree(consts);
|
|
AsmWriteLn('_DATA'#9#9'ENDS');
|
|
|
|
AsmLn;
|
|
AsmWriteLn('_BSS'#9#9'SEGMENT'#9'DWORD PUBLIC USE32 ''BSS''');
|
|
WriteTree(bsssegment);
|
|
AsmWriteLn('_BSS'#9#9'ENDS');
|
|
|
|
AsmLn;
|
|
AsmWriteLn(#9#9'END');
|
|
end;
|
|
{$ifdef EXTDEBUG}
|
|
if assigned(current_module^.mainsource) then
|
|
comment(v_info,'Done writing intel-styled assembler output for '+current_module^.mainsource^);
|
|
{$endif EXTDEBUG}
|
|
end;
|
|
|
|
end.
|
|
{
|
|
$Log$
|
|
Revision 1.3 1998-04-08 16:58:01 pierre
|
|
* several bugfixes
|
|
ADD ADC and AND are also sign extended
|
|
nasm output OK (program still crashes at end
|
|
and creates wrong assembler files !!)
|
|
procsym types sym in tdef removed !!
|
|
|
|
Revision 1.2 1998/04/08 11:34:17 peter
|
|
* nasm works (linux only tested)
|
|
|
|
Revision 1.1.1.1 1998/03/25 11:18:16 root
|
|
* Restored version
|
|
|
|
Revision 1.1 1998/03/10 01:26:09 peter
|
|
+ new uniform names
|
|
|
|
Revision 1.18 1998/03/09 12:58:11 peter
|
|
* FWait warning is only showed for Go32V2 and $E+
|
|
* opcode tables moved to i386.pas/m68k.pas to reduce circular uses (and
|
|
for m68k the same tables are removed)
|
|
+ $E for i386
|
|
|
|
Revision 1.17 1998/03/06 00:52:23 peter
|
|
* replaced all old messages from errore.msg, only ExtDebug and some
|
|
Comment() calls are left
|
|
* fixed options.pas
|
|
|
|
Revision 1.16 1998/03/02 01:48:41 peter
|
|
* renamed target_DOS to target_GO32V1
|
|
+ new verbose system, merged old errors and verbose units into one new
|
|
verbose.pas, so errors.pas is obsolete
|
|
|
|
Revision 1.15 1998/02/23 02:57:41 carl
|
|
* small bugfix when compiling $extdebug
|
|
|
|
Revision 1.14 1998/02/15 21:16:20 peter
|
|
* all assembler outputs supported by assemblerobject
|
|
* cleanup with assembleroutputs, better .ascii generation
|
|
* help_constructor/destructor are now added to the externals
|
|
- generation of asmresponse is not outputformat depended
|
|
|
|
Revision 1.13 1998/02/13 10:35:07 daniel
|
|
* Made Motorola version compilable.
|
|
* Fixed optimizer
|
|
|
|
Revision 1.12 1998/02/12 17:19:07 florian
|
|
* fixed to get remake3 work, but needs additional fixes (output, I don't like
|
|
also that aktswitches isn't a pointer)
|
|
|
|
Revision 1.11 1998/02/12 11:50:11 daniel
|
|
Yes! Finally! After three retries, my patch!
|
|
|
|
Changes:
|
|
|
|
Complete rewrite of psub.pas.
|
|
Added support for DLL's.
|
|
Compiler requires less memory.
|
|
Platform units for each platform.
|
|
|
|
Revision 1.10 1997/12/13 18:59:48 florian
|
|
+ I/O streams are now also declared as external, if neccessary
|
|
* -Aobj generates now a correct obj file via nasm
|
|
|
|
Revision 1.9 1997/12/12 13:28:26 florian
|
|
+ version 0.99.0
|
|
* all WASM options changed into MASM
|
|
+ -O2 for Pentium II optimizations
|
|
|
|
Revision 1.8 1997/12/09 13:45:10 carl
|
|
* bugfix of DT under nasm (not allowed if non integral - nasm v095)
|
|
+ added pai_align --> useless here see file for more info
|
|
* bugfix of problems with in,out instructions under nasm
|
|
* bugfix of call under nasm (not fully tested though -- not sure)
|
|
* some range check errors removed (probably a few left though)
|
|
* bugfix of checking for extended type when emitting ':'
|
|
|
|
Revision 1.7 1997/12/04 15:20:47 carl
|
|
* esthetic bugfix with extdebug on.
|
|
|
|
Revision 1.6 1997/12/03 13:46:40 carl
|
|
* bugfix of my bug with near, now near in nasm mode for all non-rel8
|
|
instructions. (jcxz,jecxz still does not work thoug - assumed short now).
|
|
|
|
Revision 1.5 1997/12/02 15:52:26 carl
|
|
* bugfix of string (again...) - would be sometimes invalid.
|
|
* bugfix of segment overrides under nasm.
|
|
- removed near in labeled instructions (would cause errors).
|
|
|
|
Revision 1.4 1997/12/01 17:42:51 pierre
|
|
+ added some more functionnality to the assembler parser
|
|
|
|
Revision 1.3 1997/11/28 18:14:36 pierre
|
|
working version with several bug fixes
|
|
|
|
Revision 1.2 1997/11/28 14:54:50 carl
|
|
+ added popfd instruction.
|
|
|
|
Revision 1.1.1.1 1997/11/27 08:32:57 michael
|
|
FPC Compiler CVS start
|
|
|
|
|
|
Pre-CVS log:
|
|
|
|
CEC Carl-Eric Codere
|
|
FK Florian Klaempfl
|
|
PM Pierre Muller
|
|
+ feature added
|
|
- removed
|
|
* bug fixed or changed
|
|
|
|
History:
|
|
|
|
9th october 1997:
|
|
* bugfix of string write, closing quotes would never be written. (CEC)
|
|
23 october 1997:
|
|
* fixed problem with writing strings of length = 0 (CEC).
|
|
+ added line separation of long string chains. (CEC).
|
|
31st october 1997:
|
|
+ completed the table of opcodes. (CEC)
|
|
3rd november 1997:
|
|
+ MMX instructions added (FK)
|
|
9th november 1997:
|
|
* movsb represented the AT&T movsx - fixed, absolute values
|
|
in getreferencestring would be preceded by $ - fixed (CEC).
|
|
|
|
What's to do:
|
|
o Fix problems regarding the segment names under NASM
|
|
o generate extern entries for typed constants and variables
|
|
o write lines numbers and file names to output file
|
|
o comments
|
|
}
|