|Re: HP-41: a M-code question|
Message #9 Posted by Doug on 2 July 2007, 8:13 a.m.,
in response to message #7 by Doug
"the Gaussian formula needs to compute
the function at several arguments, so I don't see
how the M-code routine could change these arguments
if it is inserted in the function itself."
Guess I am not being sufficiently clear: A user code subroutine cannot be called by a microcode function, it will never return.
Thus one needs to use a "trick". One possible trick is to push the address of the function into the user code return stack so that when a user code RTN is hit, it returns to the function. It will return to the microcode at the entry point of the function.
In this code:
GAUSS9 your function
SIN user code subroutine, f(X)
RTN must end with RTN
SIN LASTX X^2 RTN is repeatedly executed until the integral is completed, for 5 point gauss with 10 sections it is executed 50 times. Your function must supply the value of X in X at each point and do your summation of the integral upon reentry (because at that point the result of the integrand, f(X), will be in X).
At entry to the function, it is necessary to determine which time we are going through the function, thus a ram counter is required, that's what the CLA ASTO 00 lines accomplish: initialize the counter (or use CLX STO 00).
At entry, READ e RCR 3 RAMSEL READ and the counter is now in C. If it's zero we know that this is the first time through (a result is not in X). Then increment the counter and WRITE (for next time through).
Except for the first time through: multiply f(X) (now in X) by the appropriate weight (determined by the counter) and sum it into a ram register. Every time through, except the last, using the counter, get the next abscissa and put it in X.
The function then modifies the user code return stack and falls into the user code subroutine. Here is what the exit from your function could look like (except for the last time through):
XQNC 2950 GETPC
B=A WPT save address of PC for re-insert
XQNC 29C8 DECAD+1 backup two bytes
XQNC 29C8 DECAD+1
XQNC 27D5 SAVR10 it's our return address
GONC 24F3 XEQ20+1 put it in the user code return stack
For the last time through, one could simply recall the value of the integral and put it in X and stop. Or one could jump to the line following the RTN and use user code to recall the result. Here is one way to do that:
XQNC 2950 GETPC
LDI 085 (hex value of RTN line, there must be a RTN)
XQNC 2AF7 NXLSST
JNC -9 (NXLSST)
GONC 232F PUTPCX
As far as generating the abscissas and weights one option to consider is using synthetic functions RCL N and RCL M. One uses a synthetic 14 character text string in program then the above lines get the full precision data into X, for storage into registers.
Or, the first time into the function, the data could be generated and placed into registers, that's a lot of load digit instructions! Anyway, for multiple sections, ram registers should be used to avoid generating the Xi and Wi repeatedly.
On the other hand, if you are determined to not use registers for the Xi and Wi, or to generate higher order coef, a table grabber could be used so that each word holds a byte, instead of LD which takes two words to load a byte. For 12th order the table would be 84 words and possibly 10 words for the grabber.
Edited: 2 July 2007, 9:50 a.m.