home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Oakland CPM Archive
/
oakcpm.iso
/
cpm
/
parasol
/
asm-a86.ark
/
ASM-A86.SRC
< prev
Wrap
Text File
|
1986-10-07
|
22KB
|
818 lines
[number match level address]
ASM.to.A86.translator:
begin
{-------------------------------------------------------------
{
{ A program to convert CP/M ASM files into MSDOS ASM files
{
{ This program is invoked with the following command:
{
{ A>ASM-A86 sourcename
{
{ Note that source-name should have NO file-type specified.
{
{ The input file is assumed to have a file-type of .ASM
{ The output file will be given a filetype of .A86
{
{ This program does only a surface-level translation. It
{ does not do the exhaustive analysis that XLT-86 (from DRI)
{ does. You will likely need to do quite a bit of editing on
{ the A86 file to make it useable. Conditional jumps are not
{ checked to see that they are within range, etc. When the 8080
{ code does a PUSH PSW, this program does a PUSH AX. This will
{ usually work, but will fail when the PUSH PSW was intended to
{ save the condition-codes rather than simply preserving the value
{ in the accumulator.
{ Still, considering the cost of XLT-86, it's not such a
{ bad deal.
{
{ Copyright (C) 1986 by Shay O. Walters and Para-Soft.
{
{ Permission is granted for this program to be used without
{ restriction for private non-commercial use.
{
{---------------------------------------------------------------------
byte source.char;
string source.line 133;
word source.line.num value 0;
pointer to byte source.line.ptr value #source.line;
string source.buf 512;
file source,
file1,
text,
disk,
record source.char,
buffer source.buf,
value "X.ASM";
byte output.char;
string output.line 133;
pointer to byte output.line.ptr value #output.line;
string output.buff 256;
byte output.line.colm;
file output.file,
disk, file1,
text,
record output.char,
buffer output.buff,
value "X.A86";
{--------miscellaneous variables----------}
string output.word 81;
word word.length;
string work.word 81;
string curr.address 5;
byte curr.delim;
byte value 0; {-string ender-}
bit flag;
bit equ.flag;
bit blank.address;
word generated.label.num value 1000;
string decimal.work 8;
string gen.lbl.char 2 value "X";
string high.value.word 2;
redefine high.value.word;
byte value ^hff, value 0;
endredef;
string delimiters 24;
redefine delimiters;
byte
value " " ,value "(" ,value "+" ,value ";"
,value ^h09 ,value ")" ,value "-" ,value "="
,value ^h0d ,value "<" ,value "*" ,value ":"
,value ^h0a ,value ">" ,value "/" ,value ","
,value '!' ,value '[' ,value ']'
,value ^h1a ,value "'" ,value '"' ,value 0;
endredef;
byte wk.byte;
pointer to byte wk.bp;
external label entry address 5;
external word bdos.ptr address 6;
external byte cmd.gen.char address ^h6d;
{---reserved word table---}
record reserved.word.table;
string 4 value 'ACI'; byte value 1;
string 4 value 'ADC'; byte value 2;
string 4 value 'ADD'; byte value 2;
string 4 value 'ADI'; byte value 1;
string 4 value 'ANA'; byte value 2;
string 4 value 'ANI'; byte value 1;
string 5 value 'CALL'; byte value 4;
string 3 value 'CC'; byte value 9;
string 3 value 'CM'; byte value 9;
string 4 value 'CMA'; byte value 3;
string 4 value 'CMC'; byte value 3;
string 4 value 'CMP'; byte value 2;
string 4 value 'CNC'; byte value 9;
string 4 value 'CNZ'; byte value 9;
string 3 value 'CP'; byte value 9;
string 4 value 'CPE'; byte value 9;
string 4 value 'CPI'; byte value 1;
string 4 value 'CPO'; byte value 9;
string 3 value 'CZ'; byte value 9;
string 4 value 'DAA'; byte value 3;
string 4 value 'DAD'; byte value 10;
string 4 value 'DCR'; byte value 16;
string 4 value 'DCX'; byte value 10;
string 3 value 'DI'; byte value 3;
string 3 value 'EI'; byte value 3;
string 4 value 'HLT'; byte value 3;
string 3 value 'IN'; byte value 1;
string 4 value 'INR'; byte value 16;
string 4 value 'INX'; byte value 10;
string 3 value 'JC'; byte value 4;
string 3 value 'JM'; byte value 4;
string 4 value 'JMP'; byte value 4;
string 4 value 'JNC'; byte value 4;
string 4 value 'JNZ'; byte value 4;
string 3 value 'JP'; byte value 4;
string 4 value 'JPE'; byte value 4;
string 4 value 'JPO'; byte value 4;
string 3 value 'JZ'; byte value 4;
string 4 value 'LDA'; byte value 4;
string 5 value 'LDAX'; byte value 11;
string 5 value 'LHLD'; byte value 4;
string 4 value 'LXI'; byte value 13;
string 4 value 'MOV'; byte value 7;
string 4 value 'MVI'; byte value 15;
string 4 value 'NOP'; byte value 3;
string 4 value 'ORA'; byte value 2;
string 4 value 'ORI'; byte value 1;
string 4 value 'OUT'; byte value 0; {-don't bother-}
string 5 value 'PCHL'; byte value 3;
string 4 value 'POP'; byte value 10;
string 5 value 'PUSH'; byte value 10;
string 4 value 'RAL'; byte value 3;
string 4 value 'RAR'; byte value 3;
string 3 value 'RC'; byte value 8;
string 4 value 'RET'; byte value 3;
string 4 value 'RLC'; byte value 3;
string 3 value 'RM'; byte value 8;
string 4 value 'RNC'; byte value 8;
string 4 value 'RNZ'; byte value 8;
string 3 value 'RP'; byte value 8;
string 4 value 'RPE'; byte value 8;
string 4 value 'RPO'; byte value 8;
string 4 value 'RRC'; byte value 3;
string 4 value 'RST'; byte value 0; {-don't bother-}
string 3 value 'RZ'; byte value 8;
string 4 value 'SBB'; byte value 2;
string 4 value 'SBI'; byte value 1;
string 5 value 'SHLD'; byte value 6;
string 5 value 'SPHL'; byte value 3;
string 4 value 'STA'; byte value 5;
string 4 value 'STC'; byte value 3;
string 5 value 'STAX'; byte value 12;
string 4 value 'SUB'; byte value 2;
string 4 value 'SUI'; byte value 1;
string 5 value 'XCHG'; byte value 3;
string 4 value 'XRA'; byte value 2;
string 4 value 'XRI'; byte value 1;
string 5 value 'XTHL'; byte value 3;
string 4 value 'EQU'; byte value 0;
string 3 value 'DB'; byte value 0;
string 3 value 'DW'; byte value 0;
string 3 value 'DS'; byte value 14;
string 4 value 'ORG'; byte value 0;
string 4 value 'END'; byte value 0;
string 5 value "~FFFFFFFF~";
endrec;
pointer to string rsvd.wd.tbl.ptr;
byte rsvd.wd.length;
byte rsvd.word.found;
byte op.class;
{-------- start of procedures --------}
procedure get.source.line:
begin
fill output.word with 0;
fill source.line with 0;
while source.char = ^h0a
do
read source;
od;
while source.char = ^h00
do
read source;
od;
move #source.line to source.line.ptr;
while source.char <> ^h0d
and source.char <> "!"
do
move source.char to @source.line.ptr;
add 1 to source.line.ptr;
if source.char = ^h0a then
read source;
move ^h0a to source.char;
fi;
if source.char = ^h1a
then
move ^h00 to @source.line.ptr;
move #source.line to source.line.ptr;
exit;
fi;
read source;
od;
read source; {-skip c/r or "!"-}
move ^h00 to @source.line.ptr;
move #source.line to source.line.ptr;
end;
{----------------------------------}
procedure put.output.char:
begin
write output.file;
mcall entry using 2,output.char; {*debug*}
end;
procedure put.cr.lf:
begin
move ^h0d to output.char;
call put.output.char;
move ^h0a to output.char;
call put.output.char;
move 1 to output.line.colm;
end;
{----------------------------------------}
procedure put.output.word:
begin
mcall entry using 11 giving ,,,wk.byte;
if wk.byte <> 0 then
mcall entry using 1 giving ,,,wk.byte;
and wk.byte with ^h7f;
if wk.byte = ^h03 then
goto end;
fi; fi;
move #output.word to wk.bp;
while @wk.bp <> 0 do
if @wk.bp = "." then
move "_" to @wk.bp;
fi;
move @wk.bp to output.char;
call put.output.char;
add 1 to wk.bp;
od;
end;
{-------------------------------------------}
procedure skip.white.space:
begin
while @source.line.ptr[bp] = " "
or @source.line.ptr[bp] = ^h09 do
add 1 to source.line.ptr;
od;
end;
procedure get.next.output.word:
begin
call skip.white.space;
scan @source.line.ptr[sp] for any " ,!;:()~090d~" giving word.length;
move @source.line.ptr[sp] to output.word length word.length;
add word.length to source.line.ptr;
add word.length to #output.word giving wk.bp;
move 0 to @wk.bp;
end;
procedure copy.rest.of.line:
begin
while @source.line.ptr[bp] <> ^h0d
and @source.line.ptr[bp] <> 0
and @source.line.ptr[bp] <> ^h0a
and @source.line.ptr[bp] <> ^h1a do
if @source.line.ptr[bp] = '.' then
move "_" to @source.line.ptr[bp];
fi;
move @source.line.ptr[bp] to output.char;
call put.output.char;
add 1 to source.line.ptr;
od;
call put.cr.lf;
end;
procedure output.8.bit.reg:
begin
convert output.word to upper case;
switch on output.word:
"A": move "al" to output.word;
"B": move "ch" to output.word;
"C": move "cl" to output.word;
"D": move "dh" to output.word;
"E": move "dl" to output.word;
"H": move "bh" to output.word;
"L": move "bl" to output.word;
"M": move "[bx]" to output.word;
endswitch;
call put.output.word;
end;
procedure output.16.bit.reg:
begin
convert output.word to upper case;
switch on output.word:
"H": move "bx" to output.word;
"B": move "cx" to output.word;
"D": move "dx" to output.word;
"PSW": move "ax" to output.word;
"SP": move "sp" to output.word;
endswitch;
call put.output.word;
end;
{---------- main program ----------}
if cmd.gen.char <> " " then
move cmd.gen.char to gen.lbl.char[byte];
fi;
open source input
error begin
display "no source file found";
goto end;
end;
open output.file output
error begin
display "output file open error";
goto end;
end;
read source;
get.next.source.line:
call get.source.line;
{--------------------------------------
{ Skip over any label
{--------------------------------------
restart.this.line:
if @source.line.ptr[bp] = ^h1a then
goto translation.finished;
fi;
if @source.line.ptr[bp] = 0 then
goto get.next.source.line;
fi;
if @source.line.ptr[bp] >= "A"
and @source.line.ptr[bp] <= "z" then
scan @source.line.ptr[sp] for any " :;~090d0a~"
giving word.length;
move @source.line.ptr[sp] to output.word
length word.length;
add word.length to #output.word giving wk.bp;
move 0 to @wk.bp;
call put.output.word;
add word.length to source.line.ptr;
if @source.line.ptr = ":" then
move ":" to output.char;
call put.output.char;
add 1 to source.line.ptr;
if @source.line.ptr[bp] <> " "
and @source.line.ptr[bp] <> 0
and @source.line.ptr[bp] <> ^h09
and @source.line.ptr[bp] <> ^h0d then
subtract 1 from source.line.ptr;
move ^h09 to @source.line.ptr[bp];
fi; fi;
if @source.line.ptr[bp] <> " "
and @source.line.ptr[bp] <> ^h09 then
call put.cr.lf;
fi;
goto restart.this.line;
fi;
{------------------------------------------------
{ skip any leading white space
{------------------------------------------------
while @source.line.ptr[bp] = " "
or @source.line.ptr[bp] = ^h09 do
move @source.line.ptr[bp] to output.char;
call put.output.char;
add 1 to source.line.ptr;
od;
{-----------------------------------------------
{ Check for comment line
{-----------------------------------------------
if @source.line.ptr[bp] = ";" then
call copy.rest.of.line;
goto get.next.source.line;
fi;
{--------------------------------------------
{ Check for null line
{--------------------------------------------
if @source.line.ptr[bp] = ^h0d then
call put.cr.lf;
goto get.next.source.line;
fi;
{--------------------------------------------
{ it's not a label, white space or comment
{ it must be an op-code
{--------------------------------------------
scan @source.line.ptr[sp] for any " ;:()~090d~" giving word.length;
move @source.line.ptr[sp] to output.word length word.length;
add word.length to source.line.ptr;
add word.length to #output.word giving wk.bp;
move 0 to @wk.bp;
move output.word to work.word;
convert work.word to upper case;
move "N" to rsvd.word.found;
move #reserved.word.table to rsvd.wd.tbl.ptr;
do
if @rsvd.wd.tbl.ptr = work.word
size @rsvd.wd.tbl.ptr giving rsvd.wd.length;
add rsvd.wd.length to rsvd.wd.tbl.ptr;
add 1 to rsvd.wd.tbl.ptr;
move @rsvd.wd.tbl.ptr[bp] to op.class;
move "Y" to rsvd.word.found;
exitdo;
fi;
size @rsvd.wd.tbl.ptr giving rsvd.wd.length;
add rsvd.wd.length to rsvd.wd.tbl.ptr;
add 2 to rsvd.wd.tbl.ptr;
od until @rsvd.wd.tbl.ptr[bp] = 0;
{------------------------------------------
{ don't know what it is.
{ output it and start over
{-----------------------------------------
if rsvd.word.found = "N" then
call put.output.word;
goto restart.this.line;
fi;
{------------------------------------------
{ found a reserved word - translate it
{------------------------------------------
switch on op.class:
1: begin
{-----------------------------
{ ACI, ADI, etc. (also IN)
{------------------------------
switch on work.word:
"ACI": move "adc" to output.word;
"ADI": move "add" to output.word;
"ANI": move "and" to output.word;
"CPI": move "cmp" to output.word;
"IN": move "in" to output.word;
"ORI": move "or" to output.word;
"SBI": move "sbb" to output.word;
"SUI": move "sub" to output.word;
"XRI": move "xor" to output.word;
endswitch;
append "~09~al," to output.word;
call put.output.word;
call skip.white.space;
call copy.rest.of.line;
goto get.next.source.line;
end;
2: begin
{-----------------------------
{ ADC ADD etc.
{------------------------------
switch on work.word:
"ADC": move "adc" to output.word;
"ADD": move "add" to output.word;
"ANA": move "and" to output.word;
"CMP": move "cmp" to output.word;
"ORA": move "or" to output.word;
"SBB": move "sbb" to output.word;
"SUB": move "sub" to output.word;
"XRA": move "xor" to output.word;
endswitch;
append "~09~al," to output.word;
call put.output.word;
call skip.white.space;
call get.next.output.word;
call output.8.bit.reg;
call copy.rest.of.line;
goto get.next.source.line;
end;
3: begin
{-----------------------------
{ op's with no arguments
{------------------------------
switch on work.word:
"CMA": move "not~09~al" to output.word;
"CMC": move "cmc" to output.word;
"DAA": move "daa" to output.word;
"DI": move "cli" to output.word;
"EI": move "sti" to output.word;
"HLT": move "halt" to output.word;
"NOP": move "nop" to output.word;
"PCHL": move "jmp~09~bx" to output.word;
"RAL": move "rcl~09~al,1" to output.word;
"RAR": move "rcr~09~al,1" to output.word;
"RET": move "ret" to output.word;
"RLC": move "rol~09~al,1" to output.word;
"RRC": move "ror~09~al,1" to output.word;
"SPHL": move "mov~09~sp,bx" to output.word;
"XCHG": move "xchg~09~bx,dx" to output.word;
"XTHL": move "pop bp ! push bx ! mov bx,bp"
to output.word;
endswitch;
call put.output.word;
call copy.rest.of.line;
goto get.next.source.line;
end;
4: begin
{-----------------------------------
{ op with single label
{-----------------------------------
switch on work.word:
"CALL": move "call~09~" to output.word;
"JMP": move "jmp~09~" to output.word;
"JC": move "jc~09~" to output.word;
"JM": move "js~09~" to output.word;
"JNC": move "jnc~09~" to output.word;
"JNZ": move "jnz~09~" to output.word;
"JP": move "jns~09~" to output.word;
"JPE": move "jpe~09~" to output.word;
"JPO": move "jpo~09~" to output.word;
"JZ": move "jz~09~" to output.word;
"LDA": move "mov~09~al," to output.word;
"LHLD": move "mov~09~bx," to output.word;
endswitch;
call put.output.word;
call skip.white.space;
call copy.rest.of.line;
goto get.next.source.line;
end;
5: begin
{-----------------------------------
{ STA
{-----------------------------------
move "mov~09~" to output.word;
call put.output.word;
call skip.white.space;
call get.next.output.word;
call put.output.word;
move ",al" to output.word;
call put.output.word;
call copy.rest.of.line;
goto get.next.source.line;
end;
6: begin
{-----------------------------------
{ SHLD
{-----------------------------------
move "mov~09~" to output.word;
call put.output.word;
call skip.white.space;
call get.next.output.word;
call put.output.word;
move ",bx" to output.word;
call put.output.word;
call copy.rest.of.line;
goto get.next.source.line;
end;
7: begin
{---------------------
{ MOV
{---------------------
move "mov~09~" to output.word;
call put.output.word;
call skip.white.space;
call get.next.output.word;
call output.8.bit.reg;
call skip.white.space;
if @source.line.ptr[bp] <> "," then {--error--}
call copy.rest.of.line;
goto get.next.source.line;
fi;
move ',' to output.char;
call put.output.char;
add 1 to source.line.ptr;
call get.next.output.word;
call output.8.bit.reg;
call copy.rest.of.line;
goto get.next.source.line;
end;
8: begin
{--------------------------------------
{ conditional RETURN
{--------------------------------------
switch on work.word:
"RC": move "jnc" to output.word;
"RM": move "jns" to output.word;
"RNC": move "jc" to output.word;
"RNZ": move "jz" to output.word;
"RP": move "js" to output.word;
"RPE": move "jpo" to output.word;
"RPO": move "jpe" to output.word;
"RZ": move "jnz" to output.word;
endswitch;
append "~09~" to output.word;
append gen.lbl.char to output.word;
convert generated.label.num to decimal.work;
append decimal.work to output.word;
call put.output.word;
call put.cr.lf;
move "~09~ret" to output.word;
call put.output.word;
call copy.rest.of.line;
move gen.lbl.char[byte] to output.word[byte];
move decimal.work to output.word[+1];
append ":" to output.word;
call put.output.word;
call put.cr.lf;
add 1 to generated.label.num;
goto get.next.source.line;
end;
9: begin
{--------------------------------------
{ conditional CALL
{--------------------------------------
switch on work.word:
"CC": move "jnc" to output.word;
"CM": move "jns" to output.word;
"CNC": move "jc" to output.word;
"CNZ": move "jz" to output.word;
"CP": move "js" to output.word;
"CPE": move "jpo" to output.word;
"CPO": move "jpe" to output.word;
"CZ": move "jnz" to output.word;
endswitch;
append "~09~" to output.word;
append gen.lbl.char to output.word;
convert generated.label.num to decimal.work;
append decimal.work to output.word;
call put.output.word;
call put.cr.lf;
move "~09~call" to output.word;
call put.output.word;
call copy.rest.of.line;
move gen.lbl.char[byte] to output.word[byte];
move decimal.work to output.word[+1];
append ":" to output.word;
call put.output.word;
call put.cr.lf;
add 1 to generated.label.num;
goto get.next.source.line;
end;
10: begin
{------------------------------
{ op with single double-reg arg
{------------------------------
switch on work.word:
"DAD": move "add~09~bx," to output.word;
"DCX": move "dec~09~" to output.word;
"INX": move "inc~09~" to output.word;
"POP": move "pop~09~" to output.word;
"PUSH": move "push~09~" to output.word;
endswitch;
call put.output.word;
call skip.white.space;
call get.next.output.word;
call output.16.bit.reg;
call copy.rest.of.line;
goto get.next.source.line;
end;
11: begin
{-----------------
{ LDAX
{-----------------
call skip.white.space;
move "mov~09~si," to output.word;
call put.output.word;
call get.next.output.word;
call output.16.bit.reg;
move " ! mov al,[si]" to output.word;
call put.output.word;
call copy.rest.of.line;
goto get.next.source.line;
end;
12: begin
{-----------------
{ STAX
{-----------------
call skip.white.space;
move "mov~09~di," to output.word;
call put.output.word;
call get.next.output.word;
call output.16.bit.reg;
move " ! mov [di],al" to output.word;
call put.output.word;
call copy.rest.of.line;
goto get.next.source.line;
end;
13: begin
{-----------------
{ LXI
{-----------------
call skip.white.space;
move "mov~09~" to output.word;
call put.output.word;
call get.next.output.word;
call output.16.bit.reg;
if @source.line.ptr[bp] <> "," then
call copy.rest.of.line;
goto get.next.source.line;
fi;
add 1 to source.line.ptr;
move "," to output.char;
call put.output.char;
call skip.white.space;
if @source.line.ptr <> "-" then
if @source.line.ptr[bp] < "0"
or @source.line.ptr[bp] > "9" then
move " offset " to output.word;
call put.output.word;
fi; fi;
call copy.rest.of.line;
goto get.next.source.line;
end;
14: begin
{------------------------
{ DS
{------------------------
move "rs" to output.word;
call put.output.word;
call copy.rest.of.line;
goto get.next.source.line;
end;
15: begin
{-----------------------------
{ MVI
{------------------------------
move "mov~09~" to output.word;
call put.output.word;
call skip.white.space;
call get.next.output.word;
call output.8.bit.reg;
call skip.white.space;
call copy.rest.of.line;
goto get.next.source.line;
end;
16: begin
{-----------------------------
{ INR DCR
{------------------------------
switch on work.word:
"DCR": move "dec" to output.word;
"INR": move "inc" to output.word;
endswitch;
append "~09~" to output.word;
call put.output.word;
call skip.white.space;
call get.next.output.word;
call output.8.bit.reg;
call copy.rest.of.line;
goto get.next.source.line;
end;
endswitch;
call put.output.word;
call copy.rest.of.line;
goto get.next.source.line;
translation.finished:
close output.file;
display "finished";
end;