This is an old revision of the document!

Sometimes managing a more than three values on the stack leads to an excessive use of stack manipulation commands (the so-called stackrobatics) resulting in code excessively convolute.

In these cases a different syntax, based on the manipulation of few, global registers achieves greater clarity; this subset of the language, given its resemblance, is called Assembly-like Instruction Set.

The Assembly-like Instruction Set is not meant as a separate programming language neither its feature are to be sandboxed in exclusive environments: its statements can be freely intermingled with newRPL commands and suit to one's programming style.

The programming paradigm is based on the manipulation of a small number of registers and pseudo-registers which act as top-level global variables, accessible anywhere in the code. It must be stressed that registers and pseudo-registers are totally distinct from any local or global identifier that shares the same name.

  • There are 8 proper registers, named A through H, free for the users to assign any object to them. These registers are global and persistent;
  • also, there are 7 pseudo-registers that correspond to the 7 topmost stack levels, named S1 through S7; these pseudo-registers are not persistent and exist only if the corresponding stack level is occupied by an object. If the stack is empty, read or write operations on e.g. S1 will trigger a Stack index out of bounds error.
  • finally there are 2 additional pseudo-registers: P and R.
    • any value assigned to P is pushed immediately to the stack, thus P can be used only as a destination register, not as an argument.
    • R references to the object immediately following it in the runstream. R cannot be used as a destination.

WARNING: all of these instructions are present in the specification but some of them may not be implemented yet at the time of the writing of this document.

Assembly-like statements must always start with a colon : and must not have any spaces within. Wherever a separator is needed, use the dot ..

Instructions are divided in the following classes:

Assignment operators Math operators Math functions Flow control Data manipulation
/= ^ SIN POP

Literals are integer constants from 0 to 15. They can optionally prefixed with a hash (#) or expressed in hexadecimal (#0H-#FH). In the latter case the leading # and trailing H are compulsory.

Statements are divided in two categories:

  • Assignments, which may have
    • an optional destination register (A-H, S1-S7 or P);
    • an optional assignment operator (=, +=, -=, *= or /=);
    • a math operator or function: operators are infix and functions are prefix;
    • 1 or 2 arguments to the operator or function. Arguments can be either a register (A-H, S1-S7), a reference (R) or a literal.
  • Commands, which may be
    • a comparison command, followed by the two arguments to be compared;
    • a flow control command, followed by the condition to be tested;
    • a data manipulation command, followied by two arguments defining the extent of the manipulation;
    • arguments can be either a register (A-H, S1-S7), a reference (R) or a literal.
:A=B+1 Adds 1 to the value of register B and assigns the result to A
:E=R { 1 2 3 } Assigns the list { 1 2 3 } to E
:P=A Pushes the register A to the stack
:A=S2 :S2=S1 :S1=A Swaps stack level 1 with level 2
:C+=B^2 Squares B and adds the result to C
:A+=ABS.S1 Adds the absolute value of stack level 1 to the value of A
:C*=SIN.A Computes the sine of A and multiplies it with the content of C
:D=ATANH.R 'e^2' Assigns the hyperbolic arctangent of 'e^2' to D
:CMP.A.#1 Compares A and 1 and sets internal flags

The CMP command is equivalent to the newRPL CMP operator and accepts the same type of arguments, but instead of returning a value representing the result of the comparison it merely sets two system flags: flag -58, if the two arguments are equal and flag -59 if the first argument is less than the second.

The following commands accept one argument expressing a test condition. the argument expresses mnemonically the state of flags -58 and -59, according to the following table.

Mnemonic Test condition Flag -58 Flag -59
AL Always
LT Less Than Set
EQ Equals Set
LTE Less Than or Equals Set
NA Never
GTE Greater Than or Equals Clear
NE Not Equals Clear
GT Greater Than Clear Clear

:SKIP.EQ Skips next instruction if the result of last comparison was Equals
:LOOP.LTE Must be followed by a program « … » or a secondary :: … ;. It will repeat the object that follows while the result of the last comparison is Less Than or Equals; notice the program or secondary that follows must update the internal flags with a :CMP.x.y command or it will loop indefintely
:FPUSH.GT Pushes True (1) to the stack if the result of the last comparison is Greater Than, otherwise pushes False (0) to the stack

The FPUSH command is useful to combine Assembly-like statements into newRPL flow control structures. For example

« IF 

:A=POP.S1.3 Remove values from the stack (pop) from the given stack levels and store the values on registers A, B, C… starting with A, and as many values as needed. The first argument refers to a stack level (1 to current stack depth), and can be given as a literal number, as another register containing an integer number object or reference to the actual stack level (S1 as used in this example). The second arguments refers to the number of items to pop, and in a similar way, it can be given as a literal number (3 in this example), a register or reference to an integer number object. The example given will assign :A=S1, :B=S2 and :C=S3, while also removing the values from the stack.

:A=RPOP.S1.3 Similar to :POP but the assignment is done in reverse order. In this example :A=S3, :B=S2, and :C=S1.

:PUSH.A.3 Reverse of :POP, this example will do :P=C, :P=B and :P=A

:RPUSH.A.3 Reverse of :RPOP, this example will do :P=A, :P=B, and :P=C

  • manual/chapter5/asm.1574727443.txt.gz
  • Last modified: 2019/11/25 16:17
  • by jojo1973