manual:chapter5:asm

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
Next revision Both sides next revision
manual:chapter5:asm [2019/11/19 15:04]
claudio
manual:chapter5:asm [2019/12/04 15:33]
claudio [Data manipulation]
Line 1: Line 1:
-===== Assembly-like instructions in newRPL =====+===== Assembly-like Instruction Set =====
  
-=== Registers and pseudo-registers ===+Sometimes managing a more than three or four values on the stack leads to an excessive use of stack manipulation commands (the so-called //stackrobatics//) resulting in convolute code.
  
-There are 8 global and persistent registers, named ''A'' through ''H'', free for the users to assign any object to them.+In these cases a compact subset of instructions, with a different syntax and based on the manipulation of a small number of global registers, may achieve greater clarity; this subset of the language, given its compact format, is called **Assembly-like Instruction Set**.
  
-There's 7 pseudo-registers that correspond to the stack levels: ''S1'' through ''S7''.+The Assembly-like Instruction Set is not meant as a separate programming language neither its feature are intended to be sandboxed in exclusive environmentsits statements can be freely intermingled with **newRPL** commands and to suit anyone's programming style.
  
-Finally there's 2 additional pseudo-registers ''P'' and ''R''. ''P'' pushes a result to the stack, and it is used only as a destination register, not as an argument. ''R'' is a reference to the next object in the executing program. ''R'' cannot be used as a destination.+==== Registers and pseudo-registers ====
  
-=== Instruction syntax ===+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__.
  
-Asm instructions always must start with colon '':'' and may not have any spaces. Wherever a separator is needed, use the dot ''.''.+  * There are 8 **proper registers**, named ''A'' through ''H'', free for the users to assign any object to themThese registers are **global** and **persistent**;
  
-Statements always have: +  also, there are 7 **pseudo-registers** that correspond to the 7 topmost stack levelsnamed ''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__.
-  An optional destination (''A-H'', ''S1-S7'' or ''P''+
-  * An optional assignment operator (''='', ''+='', ''-='', ''*='' or ''/=''+
-  An operator or command (''+'',''-'',''*'',''/'',''^'' as operators, or other commands as listed below) +
-  One or 2 arguments to the operator or commandArguments can be a register or reference (''A-H'', ''S1-S7'' or ''R''), or an integer number in the range 0-15.+
  
-Examples:+  * 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.
  
-a) Simple assignments with operators:+==== Instruction set and syntax ====
  
-'':A=B+1''  Adds one to the register B and assigns the result to A.+**WARNINGall 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.**
  
-'':P=A''  Pushes the register A to the stack+Assembly-like statements __must always start with a colon__ '':'' and must not have any spaces within. Wherever a separator is needed, use the dot ''.''.
  
-'':A=S2'' '':S2=S1'' '':S1=A'' Equivalent to SWAP+**Instructions** are divided in the following classes
  
-'':C+=B^2''  Squares B, adds the result to C+^ Assignment  ^ Math (oper.)  ^ Math (functions)  ^ Tests  ^ Flow control  ^ Data manipulation 
 +| ''=''  | ''+''  | ''IP''  | ''CMP''  | ''SKIP''  | ''GET'' 
 +''+=''  | ''-''  | ''LN''  | ''CHK''  | ''LOOP''   | ''PUT'' 
 +| ''-=''  | ''*''  | ''EXP''  | ''AND''  |    | ''PUSH'' 
 +| ''*=''  | ''/''  | ''SQRT''  | ''OR''  |    | ''RPUSH'' 
 +| ''/=''  | ''^''  | ''SIN''  | ''XOR''  |  :::  | ''POP'' 
 +|    |    | ''COS''  |    |  :::  | ''RPOP'' 
 +|  :::  |  :::  | ''TAN'' |  :::  |  :::  | ''MIN'' 
 +|  :::  |  :::  | ''ASIN''  |  :::  |  :::  | ''MAX'' 
 +|  :::  |  :::  | ''ACOS''  |  :::  |  :::  | ''RND'' 
 +|  :::  |  :::  | ''ATAN'' |  :::  |  :::  | ''CLR'' 
 +|  :::  |  :::  | ''SINH''  |  :::  |  :::  |   | 
 +|  :::  |  :::  | ''COSH''  |  :::  |  :::  |    | 
 +|  :::  |  :::  | ''TANH''  |  :::  |  :::  |  :::  | 
 +|  :::  |  :::  | ''ASINH''  |  :::  |  :::  |  :::  | 
 +|  :::  |  :::  | ''ACOSH''  |  :::  |  :::  |  :::  | 
 +|  :::  |  :::  | ''ATANH''  |  :::  |  :::  |  :::  | 
 +|  :::  |  :::  | ''FP''  |  :::  |  :::  |  :::  | 
 +|  :::  |  :::  | ''ABS''  |  :::  |  :::  |  :::  | 
 +|  :::  |  :::  | ''ARG''  |  :::  |  :::  |  :::  | 
 +|  :::  |  :::  | ''RE''  |  :::  |  :::  |  :::  | 
 +|  :::  |  :::  | ''IM''  |  :::  |  :::  |  :::  |
  
-b) Assignment with math functions or commands+**Literals** are integer constants from ''0'' to ''15''. They can optionally be prefixed with a hash (''#''or expressed in hexadecimal (''#0H''-''#FH''). In the latter case the leading ''#'' and trailing ''H'' are compulsory.
  
-'':A+=ABS.S1'' Adds ABS(Stack level 1) to the value of A.+**Statements** are divided in two categories:
  
-'':C*=SIN.A'' Compute SIN(Aand multiply with the content of C.+  * **Assignments**, which may have 
 +    * an optional //destination register// (''A''-''H'', ''S1''-''S7'' or ''P''); 
 +    an optional //assignment operator// (''='', ''+='', ''-='', ''*='' or ''/=''); 
 +    * a //math operator//, a //math function// or a //data manipulation command//: operators are __infix__, functions and commands are __prefix__; 
 +    * 1 or 2 arguments to the operator or functionArguments can be either a (pseudo-)register (''A''-''H'', ''S1''-''S7''), a reference (''R''or a literal
  
-cComparison+  * **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, followed 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.
  
-'':CMP.A.B'' Compares A and B and sets internal flags+==== Simple assignments with operators ====
  
-d) Flow control+| '':A=B+#1'' | Add ''1'' to the value of register ''B'' and assign the result to register ''A'' 
 +| '':E=R { 1 2 3 }''  | Assign the list ''{ 1 2 3 }'' to register ''E'' 
 +| '':P=A''  | Push the value of register ''A'' to the stack  | 
 +| '':A=S2'' '':S2=S1'' '':S1=A''  | Swap stack level 1 with level 2 using register ''A'' as temporary storage. An error is raised if the stack contains less than 2 levels 
 +| '':C+=B^#2''  | Square the value register ''B'' and adds the result to register ''C''  |
  
-'':SKIP.EQ'' Skip next instruction if result of last comparison was Equal. Other possible comparison results are ''LT'' (less than), ''LTE'' (less than or equal), ''GT'' (greater than), ''GTE'' (greater than or equal), or ''NE'' (not equal)+==== Assignment with math functions ====
  
-'':LOOP.EQ'' Must be followed by a program or secondary ''<< ... >>'' or '':: ..;''. It will repeat the secondary while the result of the last comparison matches, see '':SKIP'' for other comparisons. Notice the program that follows MUST update the internal flags with '':CMP.x.y'' type instruction or it will loop indefintely.+'':A+=ABS.S1''  | Add the absolute value of stack level 1 to the value of register ''A''  | 
 +'':C*=SIN.A''  | Compute the sine of register ''A'' and multiplies it with the content of register ''C'' 
 +'':D=ATANH.R %%'e^2'%%'' | Assign the hyperbolic arctangent of ''%%'e^2'%%'' to register ''D''  |
  
-'':FPUSH.EQ'' Pushes True (1) to the stack if the result of the last comparison matches (see '':SKIP'' for other comparisons), otherwise pushes False (0) to the stack. This is useful to combine standard RPL flow control structures  +==== Tests ====
-''<< IF :CMP.A.0 :FPUSH.EQ  THEN ... END >>''.+
  
-eStack helpers+Test instructions will, when the result is not stored or assigned to any register, affect two system flags: flag [[manual:appendix:flags#flag-58|-58]] if the result of the test was zero (in the case of ''CMP'', if the two arguments are equaland flag [[manual:appendix:flags#flag-59|-59]] if the result is negative (in the case of ''CMP'', when the first argument is less than the second).
  
-'':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.+The ''CMP'' command is equivalent to the **newRPL** ''[[manual:chapter6:operators:cmd_ovr_cmp|CMP]]'' operator and accepts the same type of arguments
  
-'':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''+'':CMP.A.#1''  | Compare register ''A'' and literal ''1'', setting internal flags accordingly 
 +| '':C=CMP.A.#1''  | Compare register ''A'' and literal ''1'', store the result of the comparison in ''C''. In this case internal flags will **not** be set.  | 
 +'':AND.A.#1''  | Logical ''AND'' between ''A'' and literal ''1'' (always true)therefore resulting in ''0'' (false) if ''A'' is falsetrue otherwise. Internal flags will be set accordingly. 
 +'':C=AND.A.#1''  | Same as above, store the result of the test (true/false) in ''C''. In this case internal flags will **not** be set |
  
-'':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''+==== Flow control ====
  
 +The following commands accept one argument expressing a test condition. the argument expresses mnemonically the state of flags [[manual:appendix:flags#flag-58|-58]] and [[manual:appendix:flags#flag-59|-59]], according to the following table.
  
 +^ Mnemonic  ^ Test condition         ^ Flag [[manual:appendix:flags#flag-58|-58]] (Zero) ^ Flag [[manual:appendix:flags#flag-59|-59]] (Negative) ^
 +| ''AL''    | Always                 | ---       | ---       |
 +| ''LT''    | Less Than              | ---       | Set       |
 +| ''EQ'' or ''Z''  | Equals                 | Set       | ---       |
 +| ''LE''    | Less Than or Equals    | ---       | Set       |
 +| :::       | :::                    | Set       | ---       |
 +| ''NA''    | Never                  | ---       | ---       |
 +| ''GE''    | Greater Than or Equals | ---       | Clear     |
 +| ''NE'' or ''NZ''  | Not Equals             | Clear     | ---       |
 +| ''GT''    | Greater Than           | Clear     | Clear     |
  
 +----
  
 +| '':SKIP.EQ''  | Skip next instruction if the state of the flags was //Equals//  |
 +| '':LOOP.LE''  | Must be followed by a program ''« ... »'' or a secondary '':: ... ;''. Repeat the object that follows while the state of the flags is //Less Than or Equals//. Notice the program or secondary that follows **must** update the internal flags with a '':CMP.[Y].[Z]'' or other test statement or it will loop indefinitely  |
 +| '':A=CHK.GT''  | Results in true (''1'') if the state of flags is //Greater Than//, otherwise results in False (''0''). Result may be stored into a register or pseudo-register. If the result is not stored, flags will be affected accordingly  |
 +
 +The ''CHK'' command is useful to combine assembly-like statements into **newRPL** flow control structures. For example<code>
 +« IF 
 +    :CMP.A.#   @@ COMPARE A WITH 3
 +    :P=CHK.EQ    @@ AND CHECK IF IT'S EQUAL, PUSHING TRUE/FALSE TO THE STACK
 +  THEN
 +    ...
 +  END
 +»
 +</code>
 +
 +==== Data manipulation ====
 +
 +These instructions allow manipulation of composite objects (lists, vectors and matrices) as well data retrieval or storage from and to the stack, therefore some of them are assignments and others are commands.
 +
 +| '':A=GET.S2.#5''  | Retrieve the 5th element of the composite stored at stack level 2 and store it in register ''A'' |
 +| '':C=PUT.#3.R 9''  | Store the object on the ninth level of stack at third position of the composite stored in register ''C''. In other words ''C(3)=S9''  |
 +| '':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 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 will do '':A=S3'', '':B=S2'', and '':C=S1'' 
 +| '':PUSH.A.#3'' | Reverse of '':POP''. In this example will do '':P=C'', '':P=B'' and '':P=A''  |
 +| '':RPUSH.A.#3''  | Reverse of '':RPOP''. In this example will do '':P=A'', '':P=B'', and '':P=C''  |
 +| '':CLR.A.#3'' | Set registers to zero (clear) starting with ''A'', and as many registers as requested. In this example will do '':A=0'', '':B=0'' and '':C=0''  |
 +
 +==== Example code ====
 +
 +The following programs show the Assembly-like Instruction Set features in action: they are meant to be didactic rather than clever.
 +
 +----
 +
 +  * ''Q2'' is an almost line-per-line translation of the program presented in chapter 2 of the //HP-42S Programming Examples and Techniques// manual.
 +
 +<code>
 +« @@ Q2: Solve aX^2+bX+c=0 where a≠0, c≠0
 +  -103 SF             @ Complex results
 +  :A=RPOP.S1.#      @ Store coefficients in registers
 +  :CMP.A.#0 :D=CHK.EQ @ a=0?
 +  :CMP.C.#0 :E=CHK.EQ @ c=0?
 +  :OR.D.E             @ Are either zero?
 +  :SKIP.EQ            @ Skip next seco if both tests were false
 +  :: "Zero Input Invalid"
 +     DOERR            @ Abort with error
 +  ;
 +  :D=#0-B             @ -B
 +  :E=B*B              @ B^2
 +  :F=#4*A :F*=C       @ 4*A*C
 +  :E-=F   :E=SQRT.E   @ √(B^2-4*A*C)
 +  
 +  :CMP.B.#0
 +  :SKIP.GE :F=D+E     @ -B+√(B^2-4*A*C) when B<=0
 +  :SKIP.LT :F=D-E     @ -B-√(B^2-4*A*C) when B>0
 +  
 +  :E=A*#            @ 2*A
 +  :P=F/             @ (-B-SIGN(B)*√(B^2-4*A*C))/2/A is R1, the largest root in absolute value
 +  :P=C/             @ R1, C/A
 +  :S1/=S2             @ C/(R1*A) is R2, the other root
 +»
 +</code>
 +
 +----
 +
 +  * ''STRAIGHT'' computes the equation of the straight line passing through the points p<sub>1</sub>=(x<sub>1</sub>,y<sub>1</sub>) and p<sub>2</sub>=(x<sub>2</sub>,y<sub>2</sub>).
 +<code>
 +« @@ STRAIGHT: compute aX+bY+c passing through p1 and p2
 +  → p1 p2         @ Get the two points
 +  « p1 C→R        @ Split the first
 +    p2 C→R        @ Split the second
 +    :C=RPOP.S1.#4 @ Store x1, y1, x2 and y2 in C, D, E and F registers
 +    :A=R 'X'      @ Registers can store anything
 +    :B=R 'Y'      @ if 'R' pseudo-register is used
 +    :B-=D         @ B='Y-y1'
 +    :A-=C         @ A='X-x1'
 +    :F-=D         @ F=y2-y1
 +    :E-=C         @ E=x2-x1
 +    :B*=E         @ B='(Y-y1)*(x2-x1)'
 +    :F*=A         @ F='(y2-y1)*(X-x1)'
 +    :B-=F         @ B='(Y-y1)*(x2-x1)-(y2-y1)*(X-x1)'
 +    :P=B          @ Push result on the stack
 +  »
 +»
 +</code> 
  • manual/chapter5/asm.txt
  • Last modified: 2019/12/05 14:03
  • by jojo1973