Differences
This shows you the differences between two versions of the page.
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 [2019/12/05 14:03] (current) jojo1973 [Simple assignments with operators] Added a particular syntax regarding register R |
||
---|---|---|---|
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 ==== | ||
Line 73: | Line 73: | ||
| '':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.#3 @ 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 @ 2*A | ||
+ | :P=F/E @ (-B-SIGN(B)*√(B^2-4*A*C))/2/A is R1, the largest root in absolute value | ||
+ | :P=C/A @ 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> |