CREXX

REXX Language implementation

View the Project on GitHub adesutherland/CREXX

rxdas - the cRexx Disassembler

A disassembler reverses the actions of an assembler; where the assembler turns a text file containing instructions and directives into a binary executable, the disassembler returns this binary file into its text form\footnote{as much as possible, given the fact that some information on literals has disappeared};in this case it delivers a disassembly which in itself can be re-assembled - and still works.

Input/Output

The \code{rxdas} disassembler has a \code{.rxbin} file as input and produces a text file as output which goes to \code{stdout}. In this text file a disassembly has taken place; labels are synthetic and based on the combination of instructions around them. As clearly can be seen in the above, the labels generated by the cRexx compiler are not the same as the ones generated by the disassembler. With option \code{-p}, the constant pool of the \code{.rxbin} file is printed first, before the rest of the disassembly.

The current \code{003} \code{.rxbin} format is fully supported, including pooled float literals, packed code and constant sections, and the interface/class metadata directives \code{.class}, \code{.attr}, \code{.interface}, \code{.implements}, and \code{.member}.

Command Line Arguments

When the command line argument -h is specified the options are shown:\

\fontspec{IBM Plex Mono} \begin{terminaloutput} \small \obeylines \splice{rxdas -h | sed ‘s/\&/\\&/g’} \end{terminaloutput} \fontspec{TeX Gyre Pagella}

Example

```rexx /* compute sum of numbers 1 to 100 (5050) / options levelb / compute sum of numbers 1 to 100000 */ sum = 0 do i=1 to 100000 sum = i+sum end say “the sum of the numbers 1 to 100000 is:” sum return


This program, when compiled by the 'rxc' compiler, produces the following assembly source:

```rxas <!--sumloop.rxas-->
/*
 * SOURCE                 : sumLoop1000.crexx
 * BUILT                  : 2026-05-27 18:03:17
 */

.globals=0

main() .locals=4
   .meta "sumloop1000.main"="b" ".void" main() ""
   setnumdgts 18
   setnumfuz 0
   setnumfrm 1
   setnumcas 1
   setnumstd 1
   .srcstep 1 1 17 "sumLoop1000.crexx" 4 1 8 "sum = 0"
   .meta "sumloop1000.main.sum"="b" ".int" r0
   load r0,0
   .traceevent "L" 4 "R" "I" "r" 0 1 1 0 "" ""
   .traceevent "A" 6 "R" "I" "r" 0 1 1 0 "sum" ""
   .srcstep 6 6 17 "sumLoop1000.crexx" 5 1 3 "do i=1 to 100000"
   .srcstep 2 2 17 "sumLoop1000.crexx" 5 4 7 "do i=1 to 100000"
   .meta "sumloop1000.main.i"="b" ".int" r1
   load r1,1
   .traceevent "L" 4 "R" "I" "r" 1 2 2 0 "" ""
   .traceevent "A" 6 "R" "I" "r" 1 2 2 0 "i" ""
   .srcstep 3 3 17 "sumLoop1000.crexx" 5 8 17 "do i=1 to 100000"
   load r2,100000
   .traceevent "L" 4 "R" "I" "r" 2 0 0 0 "" ""
l7dostart:
   .srcstep 3 3 17 "sumLoop1000.crexx" 5 8 17 "do i=1 to 100000"
   igt r3,r1,r2
   brt l7doend,r3
   .srcstep 5 5 17 "sumLoop1000.crexx" 6 4 15 "   sum = i+sum"
   .traceevent "V" 6 "R" "I" "r" 1 5 5 0 "i" ""
   .traceevent "V" 6 "R" "I" "r" 0 5 5 0 "sum" ""
   iadd r0,r1,r0
   .traceevent "O" 4 "R" "I" "r" 0 5 5 0 "" ""
   .traceevent "A" 6 "R" "I" "r" 0 5 5 0 "sum" ""
l7doinc:
   .srcstep 4 4 17 "sumLoop1000.crexx" 5 4 5 "do i=1 to 100000"
   inc r1
   .srcstep 7 7 17 "sumLoop1000.crexx" 7 1 4 "end"
   br l7dostart
l7doend:
   .srcstep 8 8 17 "sumLoop1000.crexx" 8 1 49 "say \"the sum of the numbers 1 to 100000 is:\" sum"
   itos r0
   .traceevent "V" 6 "R" "S" "r" 0 8 8 0 "sum" ""
   sconcat r3,"the sum of the numbers 1 to 100000 is:",r0
   .traceevent "O" 4 "R" "S" "r" 3 8 8 0 "" ""
   say r3
   .srcstep 9 9 17 "sumLoop1000.crexx" 9 1 7 "return"
   ret
   .meta "sumloop1000.main.sum"

The assembler produces an ‘rxbin’ file from that. What follows is the disassembly from this ‘rxbin’ file.

```rxas

.globals=0

main() .locals=4 .meta “sumloop1000.main”=”b” “.void” main() “” setnumdgts 18 * 0x000000:00f6 Set Numeric Digits digits=op1 (>4) setnumfuz 0 * 0x000002:00f9 Set Numeric Fuzz digits=op1 (>=0) setnumfrm 1 * 0x000004:00fc Set Numeric Form=op1 (1=sci,2=eng) setnumcas 1 * 0x000006:00ff Set Numeric Case=op1 (1=lower,2=upper) setnumstd 1 * 0x000008:0102 Set Numeric Standard=op1 (1=common,2=classic) .srcstep 1 1 17 “sumLoop1000.crexx” 4 1 8 “sum = 0” .meta “sumloop1000.main.sum”=”b” “.int” r0 load r0,0 * 0x00000a:0001 Load op1 with op2 .traceevent “L” 4 “R” “I” “r” 0 1 1 0 “” “” .traceevent “A” 6 “R” “I” “r” 0 1 1 0 “sum” “” .srcstep 6 6 17 “sumLoop1000.crexx” 5 1 3 “do i=1 to 100000” .srcstep 2 2 17 “sumLoop1000.crexx” 5 4 7 “do i=1 to 100000” .meta “sumloop1000.main.i”=”b” “.int” r1 load r1,1 * 0x00000d:0001 Load op1 with op2 .traceevent “L” 4 “R” “I” “r” 1 2 2 0 “” “” .traceevent “A” 6 “R” “I” “r” 1 2 2 0 “i” “” .srcstep 3 3 17 “sumLoop1000.crexx” 5 8 17 “do i=1 to 100000” load r2,100000 * 0x000010:0001 Load op1 with op2 .traceevent “L” 4 “R” “I” “r” 2 0 0 0 “” “” .srcstep 3 3 17 “sumLoop1000.crexx” 5 8 17 “do i=1 to 100000” lb_13: igtbr lb_1e,r1,r2 * 0x000013:0157 Int Greater than if (op2>op3) goto op1 .srcstep 5 5 17 “sumLoop1000.crexx” 6 4 15 “ sum = i+sum” .traceevent “V” 6 “R” “I” “r” 1 5 5 0 “i” “” .traceevent “V” 6 “R” “I” “r” 0 5 5 0 “sum” “” iadd r0,r1,r0 * 0x000017:000f Integer Add (op1=op2+op3) .traceevent “O” 4 “R” “I” “r” 0 5 5 0 “” “” .traceevent “A” 6 “R” “I” “r” 0 5 5 0 “sum” “” .srcstep 4 4 17 “sumLoop1000.crexx” 5 4 5 “do i=1 to 100000” inc1 * 0x00001b:0020 Increment R1++ Int .srcstep 7 7 17 “sumLoop1000.crexx” 7 1 4 “end” br lb_13 * 0x00001c:0024 Branch to op1 .srcstep 8 8 17 “sumLoop1000.crexx” 8 1 49 “say "the sum of the numbers 1 to 100000 is:" sum” lb_1e: itos r0 * 0x00001e:00e5 Set register string value from its int value .traceevent “V” 6 “R” “S” “r” 0 8 8 0 “sum” “” sconcat r3,”the sum of the numbers 1 to 100000 is:”,r0 * 0x000020:008b String Concat with space (op1=op2||op3) .traceevent “O” 4 “R” “S” “r” 3 8 8 0 “” “” say r3 * 0x000024:01c2 Say op1 .srcstep 9 9 17 “sumLoop1000.crexx” 9 1 7 “return” ret * 0x000026:0030 Return VOID .meta “sumloop1000.main.sum” ```

This file has the output of the disassembler; the procedure name, \code{main}, is identical, but the first label generated by the compiler, \code{l7dostart:} is called \code{lb_9} in the disassembler output. This is of no consequence for a subsequent re-assembly and execution of the program.

Do note that the lines are longer than expected, because every disassembled line has the binary representation and a standard explanation of the generated instruction. This makes it easier to find back instructions in an .rxbin load module.

The instructions, however, can be different than expected due to the optimizations the assembler performs. When the compiler has performed optimizations, this is already visible in the \code{.rxas} file. The assembler optimizations are visible in the disassembled object.

The standard instruction documentation the disassembler affixes is the same as displayed by the rxas -i command, in a line comment after the instructions and their operands.

When stepping through a program using the cRexx Debugger (which is mentioned in the next chapter), the disassembly is the most representative record of what is in the .rxbin executable.