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
manual:chapter5:asm [2019/11/26 15:15]
jojo1973 Expanded and reformatted (part 2)
manual:chapter5:asm [2021/09/29 05:58] (current)
jojo1973 [Simple assignments with operators]
Line 5: Line 5:
 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**. 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**.
  
-The Assembly-like Instruction Set is not meant as a separate programming language neither its feature are intended to be sandboxed in exclusive environments: its statements can be freely intermingled with **newRPL** commands and to suit anyone's programming style.+The Assembly-like Instruction Set is not meant as a separate programming language neither its features are intended to be sandboxed in exclusive environments: its statements can be freely intermingled with **newRPL** commands to suit anyone's programming style.
  
 ==== Registers and pseudo-registers ==== ==== Registers and pseudo-registers ====
Line 27: Line 27:
 **Instructions** are divided in the following classes:  **Instructions** are divided in the following classes: 
  
-^ Assignment operators  ^ Math operators  ^ Math functions  ^ Flow control  ^ Data manipulation +^ Assignment  ^ Math (oper.)  ^ Math (functions)  ^ Tests  ^ Flow control  ^ Data manipulation 
-| ''=''  | ''+''  | ''IP''  | ''CMP''  | ''GET'' +| ''=''  | ''+''  | ''IP''  | ''CMP''  | ''SKIP''  | ''GET'' 
-| ''+=''  | ''-''  | ''LN''  | ''SKIP''  | ''PUT'' +| ''+=''  | ''-''  | ''LN''  | ''CHK''  | ''LOOP''   | ''PUT'' 
-| ''-=''  | ''*''  | ''EXP''  | ''LOOP''  | ''PUSH'' +| ''-=''  | ''*''  | ''EXP''  | ''AND''  |    | ''PUSH'' 
-| ''*=''  | ''/''  | ''SQRT''  | ''FPUSH''  | ''RPUSH'' +| ''*=''  | ''/''  | ''SQRT''  | ''OR''  |    | ''RPUSH'' 
-| ''/=''  | ''^''  | ''SIN''  |  :::  | ''POP'' +| ''/=''  | ''^''  | ''SIN''  | ''XOR''  |  :::  | ''POP'' 
- :::   :::  | ''COS''  |  :::  | ''RPOP'' +      | ''COS''  |    |  :::  | ''RPOP'' 
-|  :::  |  :::  | ''TAN'' |  :::  | ''MIN'' +|  :::  |  :::  | ''TAN'' |  :::  |  :::  | ''MIN'' 
-|  :::  |  :::  | ''ASIN''  |  :::  | ''MAX'' +|  :::  |  :::  | ''ASIN''   :::   :::  | ''MAX'' 
-|  :::  |  :::  | ''ACOS''  |  :::  | ''RND'' +|  :::  |  :::  | ''ACOS''   :::   :::  | ''RND'' 
-|  :::  |  :::  | ''ATAN'' |  :::  |  :::  | +|  :::  |  :::  | ''ATAN'' |  :::  |  :::  | ''CLR''  | 
-|  :::  |  :::  | ''SINH''  |  :::  |  :::  | +|  :::  |  :::  | ''SINH''  |  :::  |  :::  |   
-|  :::  |  :::  | ''COSH''  |  :::  |  :::  | +|  :::  |  :::  | ''COSH''  |  :::  |  :::  |    
-|  :::  |  :::  | ''TANH''  |  :::  |  :::  | +|  :::  |  :::  | ''TANH''   :::   :::  |  :::  | 
-|  :::  |  :::  | ''ASINH''  |  :::  |  :::  | +|  :::  |  :::  | ''ASINH''   :::   :::  |  :::  | 
-|  :::  |  :::  | ''ACOSH''  |  :::  |  :::  | +|  :::  |  :::  | ''ACOSH''   :::   :::  |  :::  | 
-|  :::  |  :::  | ''ATANH''  |  :::  |  :::  | +|  :::  |  :::  | ''ATANH''   :::   :::  |  :::  | 
-|  :::  |  :::  | ''FP''  |  :::  |  :::  | +|  :::  |  :::  | ''FP''   :::   :::  |  :::  | 
-|  :::  |  :::  | ''ABS''  |  :::  |  :::  | +|  :::  |  :::  | ''ABS''   :::   :::  |  :::  | 
-|  :::  |  :::  | ''ARG''  |  :::  |  :::  | +|  :::  |  :::  | ''ARG''   :::   :::  |  :::  | 
-|  :::  |  :::  | ''RE''  |  :::  |  :::  | +|  :::  |  :::  | ''RE''   :::   :::  |  :::  | 
-|  :::  |  :::  | ''IM''  |  :::  |  :::  |+|  :::  |  :::  | ''IM''   :::   :::  |  :::  |
  
-**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.+**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.
  
 **Statements** are divided in two categories: **Statements** are divided in two categories:
Line 58: Line 58:
     * an optional //assignment operator// (''='', ''+='', ''-='', ''*='' or ''/='');     * an optional //assignment operator// (''='', ''+='', ''-='', ''*='' or ''/='');
     * a //math operator//, a //math function// or a //data manipulation command//: operators are __infix__, functions and commands are __prefix__;     * 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 function. Arguments can be either a (pseudo-)register (''A''-''H'', ''S1''-''S7''), a reference (''R'') or a literal. The context makes clear if the arguments are to be interpreted as //direct// (e.g. register ''A'') or //indirect// (e.g. the stack level referenced by register ''A'').+    * 1 or 2 arguments to the operator or function. Arguments can be either a (pseudo-)register (''A''-''H'', ''S1''-''S7''), a reference (''R'') or a literal. 
  
   * **Commands**, which may be   * **Commands**, which may be
     * a //comparison// command, followed by the two arguments to be compared;     * a //comparison// command, followed by the two arguments to be compared;
     * a //flow control// command, followed by the condition to be tested;     * 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; +    * 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.  The context makes clear if the arguments are to be interpreted as //direct// (e.g. register ''A'') or //indirect// (e.g. the stack level referenced by register ''A'').+    * arguments can be either a register (''A''-''H'', ''S1''-''S7''), a reference (''R'') or a literal.
  
 ==== Simple assignments with operators ==== ==== Simple assignments with operators ====
  
 | '':A=B+#1'' | Add ''1'' to the value of register ''B'' and assign the result to register ''A''  | | '':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''  |+| '':E=R { 1 2 3 }'' Store the list ''{ 1 2 3 }'' in register ''E''  |
 | '':P=A''  | Push the value of register ''A'' to the stack  | | '':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  | | '':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''  | | '':C+=B^#2''  | Square the value register ''B'' and adds the result to register ''C''  |
 +| '':B=R^#2 π''  | Assign ''%%'%%π^2%%'%%'' to register B. This example shows that register ''R'' must not necessarily be the second argument of a binary operator  |
  
 ==== Assignment with math functions ==== ==== Assignment with math functions ====
Line 80: Line 81:
 | '':D=ATANH.R %%'e^2'%%'' | Assign the hyperbolic arctangent of ''%%'e^2'%%'' to register ''D''  | | '':D=ATANH.R %%'e^2'%%'' | Assign the hyperbolic arctangent of ''%%'e^2'%%'' to register ''D''  |
  
-==== Testing ====+==== Tests ==== 
 + 
 +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 equal) and 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). 
 + 
 +The ''CMP'' command is equivalent to the **newRPL** ''[[manual:chapter6:operators:cmd_ovr_cmp|CMP]]'' operator and accepts the same type of arguments. 
  
 | '':CMP.A.#1''  | Compare register ''A'' and literal ''1'', setting internal flags accordingly  | | '':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 false, true 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.  |
  
-The ''CMP'' command is equivalent to the **newRPL** ''[[manual:chapter6:operators:cmd_ovr_cmp|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 [[manual:appendix:flags#flag-58|-58]] if the two arguments are equal and flag [[manual:appendix:flags#flag-59|-59]] if the first argument is less than the second. 
  
 ==== Flow control ==== ==== Flow control ====
Line 93: Line 100:
 | ''AL''    | Always                 | ---       | ---       | | ''AL''    | Always                 | ---       | ---       |
 | ''LT''    | Less Than              | ---       | Set       | | ''LT''    | Less Than              | ---       | Set       |
-| ''EQ''    | Equals                 | Set       | ---       | +| ''EQ'' or ''Z''  | Equals                 | Set       | ---       | 
-| ''LTE''   | Less Than or Equals    | ---       | Set       |+| ''LE''    | Less Than or Equals    | ---       | Set       |
 | :::       | :::                    | Set       | ---       | | :::       | :::                    | Set       | ---       |
 | ''NA''    | Never                  | ---       | ---       | | ''NA''    | Never                  | ---       | ---       |
-| ''GTE''   | Greater Than or Equals | ---       | Clear     | +| ''GE''    | Greater Than or Equals | ---       | Clear     | 
-| ''NE''    | Not Equals             | Clear     | ---       |+| ''NE'' or ''NZ''  | Not Equals             | Clear     | ---       |
 | ''GT''    | Greater Than           | Clear     | Clear     | | ''GT''    | Greater Than           | Clear     | Clear     |
  
 ---- ----
  
-| '':SKIP.EQ''  | Skip next instruction if the result of last comparison was //Equals// +| '':SKIP.EQ''  | Skip next instruction if the state of the flags was //Equals// 
-| '':LOOP.LTE''  | Must be followed by a program ''« ... »'' or a secondary '':: ... ;''. 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.[Y].[Z]'' statement or it will loop indefintely  | +| '':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  | 
-| '':FPUSH.GT'' Push True (''1''to the stack if the result of the last comparison is //Greater Than//, otherwise push False (''0'' |+| '':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 ''FPUSH'' command is useful to combine assembly-like statements into **newRPL** flow control structures. For example<code>+The ''CHK'' command is useful to combine assembly-like statements into **newRPL** flow control structures. For example<code>
 « IF  « IF 
-    :CMP.A.#0 +    :CMP.A.#3    @@ COMPARE A WITH 3 
-    :FPUSH.EQ+    :P=CHK.EQ    @@ AND CHECK IF IT'S EQUAL, PUSHING TRUE/FALSE TO THE STACK
   THEN   THEN
     ...     ...
Line 127: Line 134:
 | '':PUSH.A.#3'' | Reverse of '':POP''. In this example will do '':P=C'', '':P=B'' and '':P=A''  | | '':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''  | | '':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
 +  :AND.A.C            @ Are either zero?
 +  :SKIP.NZ            @ Skip next seco if both A and C were non-zero
 +  :: "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.1574810120.txt.gz
  • Last modified: 2019/11/26 15:15
  • by jojo1973