XTRAN Example — Translate In-line Function Arguments in Encore (SEL, Gould) Assembler
In some assemblers, you can code a "branch and link" instruction followed by in-line arguments in the form of data operators. The called function advances the Program Counter past the in-line arguments before returning. Encore assembler offers an example of this technique.
We have developed a standard set of rules for handling this situation when translating from such an assembler to C. The rules comprise 88 non-comment lines of XTRAN's rules language (which we call "meta-code"). They are almost assembler-independent, and therefore easily tailored for a particular assembler. They direct XTRAN to do the following things:
Before translation, find all such in-line argument data operators and mark them "do not translate" so they won't come out in the C code resulting from translation When translating each "branch and link" instruction For each in-line data operator following the instruction, if any Add its operands to an argument list we create for the call If it has comments, add them to the "branch and link" instruction so they will be preserved through translation Translate the instruction to a function call with the argument list (if any) we have generated from the in-line data operators following the instruction
The following example uses a standard set of XTRAN rules for parsing Encore assembler and translating it to C, plus the standard rule set described above for handling in-line function arguments. NOTE that the translation shown below was done with default conditions. XTRAN provides many options for controlling the way it translates.
Here is a flowchart for this process, in which the elements are color coded:
- BLUE for XTRAN versions (runnable programs)
- ORANGE for XTRAN rules (text files)
- RED for
Input to XTRAN:
WRD1 REZ 1W WRD1 REZ 1W START BL FUNC1 BL FUNC1 DATAW 1 DATAW 1 DATAW 2 DATAW 2 LW 1,WRD1 LW 1,WRD1 BL FUNC2 BL FUNC2 DATAW 1 BL FUNC2 BL FUNC2 LW 1,WRD1 LW 1,WRD1
Output from XTRAN:
extern long r1; extern unkn func1; extern unkn func2; long wrd1 = 0; /*wrd1 rez 1w*/ start: func1(1, 2); /*bl func1*/ /*dataw 1*/ /*dataw 2*/ r1 = wrd1; /*lw 1,wrd1*/ func2(1); /*bl func2*/ func2(); /*bl func2*/ r1 = wrd1; /*lw 1,wrd1*/