Hi all.

I'm trying to find the most effective way to perform a register exchange function that minimizes stack disruption. Although on the 34C and 67, and later models the I register and x<>(i) functions are available, how can x<>Rn be accomplished with the 25 or 33 without disrupting the stack drastically?

Thanks

(06-11-2017 08:58 PM)Matt Agajanian Wrote: [ -> ]I'm trying to find the most effective way to perform a register exchange function that minimizes stack disruption. Although on the 34C and 67, and later models the I register and x<>(i) functions are available, how can x<>Rn be accomplished with the 25 or 33 without disrupting the stack drastically?

The obvious solution (assuming X is exchanged with register 1) would be:

Code:

`RCL 1`

x<>y

STO 1

R↓

Since the current X-value and the content of R1 require two stack registers, this solution loses the T-register:

Code:

`before after`

T X

Z Z

Y Y

X R1

LastX LastX

Replacing the final R↓ with CLX + duplicates the previous Z to T while it clears LastX.

As far as I can see you always have to sacrifice one register.

Dieter

Thank you, Dieter. These two variations will help.

Save the stack in registers first?

Neither of those devices have indirect addressing which is a big impediment.

Pauli

Yes. That's why I'm trying to optimize translating my SR-56 programs for Woodstock and the 33E/C.

(06-11-2017 11:08 PM)Paul Dale Wrote: [ -> ]Save the stack in registers first?

Neither of those devices have indirect addressing which is a big impediment.

Pauli

It's either I put R/S into the program to manually save and restore the stack so as to save program steps or clutter up my program with save/restore stack code.

(06-11-2017 11:57 PM)Matt Agajanian Wrote: [ -> ]save program steps or clutter up my program with save/restore stack code.

When translating a program from one calculator to another it's usually not a good idea to mirror the original code 1:1 on the other device. IMHO the best approach is trying to understand how the original code works and translate this idea (!!, not the code) into code for the other machine.

So if you have, say, TI-programs with Exc-commands you should not try to simulate this Exc-instruction in your HP code. Instead see how the program works and do it in RPN with the special features of the target calculator – which may be even shorter and more effective.

Often in RPN things can be done quite relaxed. Here is an example:

Code:

`TI-58/59 HP-25/33`

---------------------

( RCL 1

RCL RCL 2

01 +

+ RCL 3

RCL x<>y

02 STO 3

) *

*

EXC

03

=

No need to worry about stack registers or how to emulate that Exc-instruction.

Another example – swap the contents of R1 and R2:

Code:

`TI-58/59 HP-25/33`

---------------------

RCL RCL 2

01 RCL 1

EXC STO 2

02 x<>y

STO STO 1

01

Again, there's no need to save the stack or emulate the Exc-instruction.

Dieter

Yes, an even better mousetrap. To be honest, the hard work of understanding AOS programming, intermediate results, and trying to understand what contents are needing to be saved for pending operations and register operations are worth the work for RPN transation.

(06-12-2017 12:08 PM)Dieter Wrote: [ -> ] (06-11-2017 11:57 PM)Matt Agajanian Wrote: [ -> ]save program steps or clutter up my program with save/restore stack code.

When translating a program from one calculator to another it's usually not a good idea to mirror the original code 1:1 on the other device. IMHO the best approach is trying to understand how the original code works and translate this idea (!!, not the code) into code for the other machine.

So if you have, say, TI-programs with Exc-commands you should not try to simulate this Exc-instruction in your HP code. Instead see how the program works and do it in RPN with the special features of the target calculator – which may be even shorter and more effective.

Often in RPN things can be done quite relaxed. Here is an example:

Code:

`TI-58/59 HP-25/33`

---------------------

( RCL 1

RCL RCL 2

01 +

+ RCL 3

RCL x<>y

02 STO 3

) *

*

EXC

03

=

No need to worry about stack registers or how to emulate that Exc-instruction.

Another example – swap the contents of R1 and R2:

Code:

`TI-58/59 HP-25/33`

---------------------

RCL RCL 2

01 RCL 1

EXC STO 2

02 x<>y

STO STO 1

01

Again, there's no need to save the stack or emulate the Exc-instruction.

Dieter

Dieter, on second look I'm confused. This actually loses several stack register value when an exchange occurs in the midst of a calculation. At the end of a calculation, an exchange like this is acceptable. But, if you have seen several SR-56 Application Library and TI-58/59 Specialty Packette/Solid State Module programs, exchange operations occasionally are within a calculation. So, how do I code for those instances?

Thanks

(06-12-2017 07:48 PM)Matt Agajanian Wrote: [ -> ]But, if you have seen several SR-56 Application Library and TI-58/59 Specialty Packette/Solid State Module programs, exchange operations occasionally are within a calculation. So, how do I code for those instances?

Please provide an example with the complete program code and the way the program is supposed to work.

Dieter

Okay. I'm going to focus on examining the SR-56 Application Library in more detail in the event I scanned over a code too quickly. Also, I'm redirecting my concentration to see the flow of the program so as to reprogram myself out of my 'straight translation' habit.

I've been trying to figure this out and I'm getting confused and forgetting the stack at the exchange steps. So, please help me. Maybe you've already responded with the answer. But, the ends I'm trying to accomplish removes the former value from the stack and leaves the exchanged value on the stack with Y, Z, and (if possible) the T registers intact.

All I'm trying to do is leave the exchanged value in the X register without the forner register content in the Y register.

Perhaps I shoud have been clearer to the point of exact in my original post. Sorry.

Dieter is correct, the best way to do this is to understand the algorithm and recode it. RPN programs should almost always be shorter than AOS ones.

Since you want some code, this sequence will swap X and register 1 using register 0 and preserving the rest of the stack:

Code:

`01 X<>Y`

02 STO 0

03 CLx

04 RCL 1

05 X<>Y

06 STO 1

07 CLx

08 RCL 0

09 X<>Y

To avoid using the register, Last X can be used instead but this requires the arithmetic operation in step 2 to be undone in step 8 without loss (multiplication and division would also work as a pair in the same manner). This code swaps X with register 0 and leaves the rest of the stack intact:

Code:

`01 X<>Y`

02 +

03 RCL 0

04 X<>Y

05 STO 0

06 CLx

07 LAST X

08 STO- 0

09 X<>Y

Both are for the HP-25. Using 20% of the program memory to swap X with a register seems a little wasteful.

Pauli

First, let me apologise for my frustration. I'm trying too hard to fit an advanced technique (67/97/34) into a basic 25/33 (forgive me) programming language.

Second, I do appreciate your straughtforward four-to-multiple step variations. I shouldn't try so hard to make the most direct method into an elaborate one. Besides, I need to adapt to what a calculator does best by its own merits. For example, I can't expect the 25 or 33 to handle the memory register gymnastics for a Moving Averages program. If I want to code for something that complex, I should use the right tool for the task, a 67/97, 34C, or later. Besides, as capable as the 65 is, a Moving Averages program, for example, requiring indirect addressing isn't that feasable.

Once again apologies and thanks.

(06-14-2017 03:04 PM)Matt Agajanian Wrote: [ -> ]First, let me apologise for my frustration. I'm trying too hard to fit an advanced technique (67/97/34) into a basic 25/33 (forgive me) programming language.

Well, of course most of the HP67/97 and maybe also 34C programs are so complex that they simply won't fit the 25 or 33. After all it is 224 steps plus 26 registers vs. 49 steps and 8 registers... plus a less comprehensive command set. So at least a more or less direct program transfer must fail. That said, many clever programs for the 25 exist that prove what can be done even with its limited ressources.

(06-14-2017 03:04 PM)Matt Agajanian Wrote: [ -> ]Second, I do appreciate your straughtforward four-to-multiple step variations. I shouldn't try so hard to make the most direct method into an elaborate one. Besides, I need to adapt to what a calculator does best by its own merits. For example, I can't expect the 25 or 33 to handle the memory register gymnastics for a Moving Averages program.

While we're at it: I just looked at the HP67/97 moving average program that came with the Standard Pac. At one point the oldest value is removed from the curent sum while the newest one is added and stored. This can be done with an EXC command, if available, but the 67/97 does it this way:

Code:

`... ...`

037 RCL i

038 ST- 0

039 x<>y

040 STO i

041 ST+ 0

042 R↓

... ...

Compare this with the suggestion in my first post. ;-)

(06-14-2017 03:04 PM)Matt Agajanian Wrote: [ -> ]If I want to code for something that complex, I should use the right tool for the task, a 67/97, 34C, or later. Besides, as capable as the 65 is, a Moving Averages program, for example, requiring indirect addressing isn't that feasable.

OK. But there are other programs that

can be done on the 25. I recommend looking at the HP-25 Library by Jim Davidson, a list of programs that have been published in PPC Journal between 1976 and 1978 (this index can be found in PPC V5 P6). I think it was Gene who posted the whole package as a PDF about half a year ago.

But... I am still waiting for an SR56 program with the infamous EXC instruction that is waiting for a translation to HP25/33 code. ;-)

Dieter

(06-14-2017 10:19 AM)Matt Agajanian Wrote: [ -> ]I've been trying to figure this out and I'm getting confused and forgetting the stack at the exchange steps. So, please help me. Maybe you've already responded with the answer. But, the ends I'm trying to accomplish removes the former value from the stack and leaves the exchanged value on the stack with Y, Z, and (if possible) the T registers intact.

This – leaving the whole stack or most of it unchanged – usually is

not required at all. At least after some slight recoding usually you do not have to hold three intermediate values on the stack.

Example: Calculate R1 + R2*R3^R4 while pushing pi into R4

Code:

`AOS RPN`

--------------

RCL RCL 3

01 RCL 4

+ Pi

RCL STO 4

02 R↓

* y^x

RCL RCL 2

03 *

y^x RCL 1

Pi +

EXC

04

=

RPN is different. You can do most calculations without having to keep track of lots of intermediate results – you always work with just two numbers. ;-)

(06-14-2017 10:19 AM)Matt Agajanian Wrote: [ -> ]All I'm trying to do is leave the exchanged value in the X register without the forner register content in the Y register.

?!? After the exchange the former register content is in X of course.

That's what the EXC command does. As well as the four-step-code in my first post. Y and Z are preserved.

Dieter

(06-14-2017 06:39 PM)Dieter Wrote: [ -> ] (06-14-2017 10:19 AM)Matt Agajanian Wrote: [ -> ]I've been trying to figure this out and I'm getting confused and forgetting the stack at the exchange steps. So, please help me. Maybe you've already responded with the answer. But, the ends I'm trying to accomplish removes the former value from the stack and leaves the exchanged value on the stack with Y, Z, and (if possible) the T registers intact.

This – leaving the whole stack or most of it unchanged – usually is not required at all. At least after some slight recoding usually you do not have to hold three intermediate values on the stack.

Example: Calculate R1 + R2*R3^R4 while pushing pi into R4

Code:

`AOS RPN`

--------------

RCL RCL 3

01 RCL 4

+ Pi

RCL STO 4

02 R↓

* y^x

RCL RCL 2

03 *

y^x RCL 1

Pi +

EXC

04

=

RPN is different. You can do most calculations without having to keep track of lots of intermediate results – you always work with just two numbers. ;-)

(06-14-2017 10:19 AM)Matt Agajanian Wrote: [ -> ]All I'm trying to do is leave the exchanged value in the X register without the forner register content in the Y register.

?!? After the exchange the former register content is in X of course.

That's what the EXC command does. As well as the four-step-code in my first post. Y and Z are preserved.

Dieter

Dieter, again, sorry for my mixup. Yes, your methods accomplish what I need. For some reason, a mental block on my part is gettiing in the way of imagining/picturing the stack. Perhaps, I should create an Excel or Word six-row table to help me physically visualise these.

Thanks

(06-14-2017 07:38 PM)Matt Agajanian Wrote: [ -> ]For some reason, a mental block on my part is gettiing in the way of imagining/picturing the stack. Perhaps, I should create an Excel or Word six-row table to help me physically visualise these.

Here we go:

Code:

`T Z Z Z X`

Z Y Y Y Z

Y X R1 R1 Y

X R1 X X R1 <= at the end X and R1

R1 R1 R1 X X <= have swapped their contents

-------------------------------------------

Start RCL 1 X<>Y STO 1 R↓

-------------------------------------------

You see that X and R1 are swapped, Y and Z are preserved, only T is lost.

Dieter

(06-14-2017 08:46 PM)Dieter Wrote: [ -> ] (06-14-2017 07:38 PM)Matt Agajanian Wrote: [ -> ]For some reason, a mental block on my part is gettiing in the way of imagining/picturing the stack. Perhaps, I should create an Excel or Word six-row table to help me physically visualise these.

Here we go:

Code:

`T Z Z Z X`

Z Y Y Y Z

Y X R1 R1 Y

X R1 X X R1 <= at the end X and R1

R1 R1 R1 X X <= have swapped their contents

-------------------------------------------

Start RCL 1 X<>Y STO 1 R↓

-------------------------------------------

You see that X and R1 are swapped, Y and Z are preserved, only T is lost.

Dieter

Thanks for that extra effort doing what I should have. Much appreciated and quite helpful.