$title ('HEX OUTPUT MODULE') hexout: do; /* modified 3/28/81 R. Silberstein modified 3/30/81 R. Silberstein modified 4/9/81 R. Silberstein */ /* This is the module to produce the (hex-)output from the assembler. The interface to other modules goes through the subroutine EMITCODEBYTE (outputbyte,segmenttype). This routine outputs one byte of generated code of a specified segment type (code,data,stack,extra). The subroutine also updates the value of the current instruction pointer of the current segment (CIP), and prints the output code on the print line. */ $include (:f1:macro.lit) $include (:f1:struc.lit) $include (:f1:outp.lit) $include (:f1:subr2.ext) $include (:f1:files.ext) $include (:f1:global.ext) dcl empty lit '0ffh', /* buffer empty value */ recordlimit lit '30', /* max no of bytes pr record */ loccip addr, /* local copy of instruction pointer */ startfound byte, /* true if start record sent */ gtyp byte, /* incomming byte type */ gbyt byte, /* incomming byte */ curtyp byte, /* current byte type */ sum byte, /* used to compute check sum */ buffer (35) byte, /* record buffer (RECORDLIMIT+5) */ recordlg byte at (.buffer(0)), recordtype byte at (.buffer(3)), offsetaddr addr at (.buffer(1)), bufpt byte, /* buffer index */ /* Record type conversion table */ /* ( to be changed later ??? ) */ rectyp$I$tab(12) byte data (0ffh,eoftype,0ffh,starttype,INTELdata,INTELdata, INTELdata,INTELdata,INTELsegment,INTELsegment,INTELsegment, INTELsegment), rectyp$D$tab(12) byte data (0ffh,eoftype,0ffh,starttype,DRcodedata,DRdatadata, DRstackdata,DRextradata,DRcodesegm,DRdatasegm,DRstacksegm, DRextrasegm); /*********** subroutines **********/ rectyptab: procedure(n) byte; declare n byte; if intel$hex$on then$do return rectyp$I$tab(n); else$do return rectyp$D$tab(n); end$if; end rectyptab; switch$high$low: procedure(p); declare p address, ch based p byte, (s1,s2) byte; s1=ch; p=p+1; s2=ch; ch=s1; p=p-1; ch=s2; end switch$high$low; writebyt: proc (ch); dcl ch byte; call outhexbyte(ch); end writebyt; writerecord: proc; /* write current recor to file */ call switch$high$low(.offsetaddr); recordlg=bufpt-4; sum=0; /* compute check sum */ i=0ffh; do while (i:=i+1) < bufpt; sum=sum+buffer(i); end$while; buffer(bufpt)=-sum; /* check sum */ call writebyt(':'); do i=0 to bufpt; /* print hexbytes to file */ call hex1out(buffer(i),.help(0)); call writebyt(help(0)); call writebyt(help(1)); end$do; call writebyt(cr); call writebyt(lf); end writerecord; enternewbyt: proc(b); /* enter a new byte into buffer */ dcl b byte; if bufpt > recordlimit then$do /* test if record full */ call writerecord; offsetaddr=cip; bufpt=4; end$if; buffer(bufpt)=b; bufpt=bufpt+1; end enternewbyt; enterinput: proc; call enternewbyt(gbyt); end enterinput; eofrecord: proc; /* write end-of-file record to file */ if curtyp<>empty then call writerecord; recordtype=rectyptab(eoftype); offsetaddr=0; bufpt=4; call writerecord; end eofrecord; startrecord: proc; /* write a start record to file */ dcl seglow byte at (.csegvalue),seghigh byte at (.csegvalue+1), offslow byte at (.cip),offshigh byte at (.cip+1); if pass=2 then$do startfound=true; if curtyp <> empty then call writerecord; bufpt=4; offsetaddr=0; recordtype=rectyptab(starttype); if csegspec then$do call enternewbyt(seghigh); call enternewbyt(seglow); else$do call enternewbyt(0); call enternewbyt(0); end$if; call enternewbyt(offshigh); call enternewbyt(offslow); call writerecord; curtyp=empty; end$if; end startrecord; segmbyte: proc; /* write a segment value byte to file */ if pass = 2 then$do if curtyp <> gtyp then$do if curtyp <> empty then call writerecord; curtyp=gtyp; recordtype=rectyptab(gtyp); offsetaddr=0; bufpt=4; call enterinput; else$do call enterinput; call writerecord; curtyp=empty; end$if; end$if; end segmbyte; databyte: proc; /* write a data byte to file */ if pass=2 then$do if (curtyp <> gtyp) or (loccip <> cip) then$do if curtyp<>empty then call writerecord; curtyp=gtyp; recordtype=rectyptab(gtyp); offsetaddr=cip; bufpt=4; end$if; call enterinput; call hex1out(gbyt,.prefix(prefixptr)); /* output to listing */ prefixptr=prefixptr+2; end$if; cip=cip+1; /* update instruction pointer */ loccip=cip; end databyte; emitinit: proc public; startfound=false; curtyp=empty; end emitinit; emitterminate: proc public; call eofrecord; /* write EOF record */ end emitterminate; emitcodebyte: proc (b,typ) public; dcl (b,typ) byte; gbyt=b; /* move to global variables */ gtyp=typ; do case typ-CSdata; do; /* CS data */ if not startfound then$do call startrecord; end$if; call databyte; end; call databyte; /* DS data */ call databyte; /* SS data */ call databyte; /* ES data */ call segmbyte; /* CS value */ call segmbyte; /* DS value */ call segmbyte; /* SS value */ call segmbyte; /* ES value */ end$case; end emitcodebyte; end$module hexout;