Post Reply 
(42S) CARDIAC
10-11-2014, 08:54 PM (This post was last modified: 07-31-2022 10:11 AM by Thomas Klemm.)
Post: #1
(42S) CARDIAC
Quote:The acronym CARDIAC stands for "CARDboard Interactive Aid to Computation." It was developed by David Hagelbarger at Bell Labs as a tool for teaching how computers work in a time when access to real computers was extremely limited. The CARDIAC kit consists of a folded cardboard "computer" and an instruction manual. In July 1969, the Bell Laboratories Record contained an article describing the system and the materials being made available to teachers for working with it.
-- Brian L. Stuart, A discription of the CARDIAC

This program is a CARDIAC-simulator. It allows to run programs written for CARDIAC on your HP-42S.
In order to work properly we need registers 00-99. Thus you have to set the size accordingly:

SIZE 100

The simulator allows to load a CARDIAC-program (deck of cards) into the memory of the HP-42S. These cards have to be stored in a matrix. This is an example of a program that counts to 10.

Program Listing:
Code:
04     009     n      DATA    009
05     000     cntr   DATA    000
                              
10     100            CLA     00      Initialize the counter
11     605            STO     cntr    
12     104     loop   CLA     n       If n < 0, exit
13     322            TAC     exit
14     505            OUT     cntr    Output a card
15     105            CLA     cntr    Increment the card
16     200            ADD     00
17     605            STO     cntr
18     104            CLA     n       Decrement n
19     700            SUB     00
20     605            STO     n
21     812            JMP     loop
22     900     exit   HRS     00

Create a 1×2 Matrix and set it to GROW:

1 ENTER 2
MATRIX.NEW
EDIT
GROW

Now enter all the numbers of the listing:
Code:
[
  2, 800,
 10, 100,
 11, 605,
 12, 104,
 13, 322,
 14, 505,
 15, 105,
 16, 200,
 17, 605,
 18, 104,
 19, 700,
 20, 604,
 21, 812,
 22, 900,
  4,   9,
  2, 810,
]

STO "COUNT"

The first row [2, 800] is just the boot-loader program.
At the end we write n = 9 into register 4 [4, 9] and then we jump to line 10 to start the program [2, 810].

This loads the program from the matrix into the memory and runs it:

RCL "COUNT"
XEQ "CARDIAC"

Make sure to set flag 21 when using Free42 or it will run too fast to notice anything.
Alternatively you may add a PSE in the implementation of OUT (LBL 05).

If everything is correct you should see:

R05=1
R05=2
R05=3
R05=4
R05=5
R05=6
R05=7
R05=8
R05=9
R05=10


The program is still loaded in the memory of the HP-42S. Let's assume we want to count to 100 instead:

99 STO 04
10 XEQ 99


R05=1
R05=2
R05=3
R05=4
(...)
R05=97
R05=98
R05=99
R05=100


Implementation details
The registers 00-99 are used as memory. The accumulator acc and the program-counter pc are kept on the stack.
The instruction register ir consists of two parts: the code and the address addr. Furthermore the address consists of the left and the right digit. They are used in the "shift accumulator" operator.

Here's an example:

ir = 835
code = 8
addr = 35
left = 3
right = 5


Links

Listing
Code:
;---------------------;------------------
{ 207-Byte Prgm }     ;
LBL "CARDIAC"         ;
;------- INIT --------;------------------
EDIT                  ; 1:1=2
←                     ; n:2=0
CF 00                 ;
CLRG                  ;
1                     ; 1
STO 00                ; 1
CLST                  ; 0 0
;---- MAIN LOOP ------;------------------
LBL 99                ; acc pc
RCL IND ST X          ; acc pc ir
X<>Y                  ; acc ir pc
1                     ; acc ir pc 1
+                     ; acc acc ir pc'
X<>Y                  ; acc acc pc' ir
1E2                   ; acc pc' ir 100
÷                     ; acc acc pc' code.addr
FP                    ; acc acc pc' .addr
XEQ IND ST L          ; acc acc pc' .addr
FC? 00                ; acc acc pc' .addr
GTO 99                ; acc acc pc' .addr
;---------------------;------------------
EXITALL               ;
CF 00                 ;
CLST                  ;
RTN                   ;
;------- INP ---------;------------------
LBL 00                ; acc pc .addr
1E2                   ; acc pc .addr 100
×                     ; acc acc pc addr
OLD                   ; acc pc addr card
→                     ; acc pc addr card'
STO IND ST Y          ; acc pc addr card'
RDN                   ; card' acc pc addr
RDN                   ; addr card' acc pc
RTN                   ; acc addr
;------- CLA ---------;------------------
LBL 01                ; acc pc .addr
1E2                   ; acc pc .addr 100
×                     ; acc acc pc addr
X<>Y                  ; acc acc addr pc
RCL IND ST Y          ; acc addr pc acc'
X<>Y                  ; acc addr acc' pc
RTN                   ; acc' pc
;------- ADD ---------;------------------
LBL 02                ; acc pc .addr
1E2                   ; acc pc .addr 100
×                     ; acc acc pc addr
X<> ST Z              ; acc addr pc acc
RCL+ IND ST Z         ; acc addr pc acc'
X<>Y                  ; acc addr acc' pc
RTN                   ; acc' pc
;------- TAC ---------;------------------
LBL 03                ; acc pc .addr
1E2                   ; acc pc .addr 100
×                     ; acc acc pc addr
R↑                    ; acc pc addr acc
X<0?                  ; acc pc addr acc
GTO 10                ; acc pc addr acc
RCL ST Z              ; pc addr acc pc
RTN                   ; acc pc
LBL 10                ; acc pc addr acc
X<>Y                  ; acc pc acc addr
RTN                   ; acc addr
;------- SFT ---------;------------------
LBL 04                ; acc pc .addr
10                    ; acc pc .addr 10
×                     ; acc acc pc left.right
ENTER                 ; acc pc left.right left.right
IP                    ; acc pc left.right left
10↑X                  ; acc pc left.right 10↑left
R↑                    ; pc left.right 10↑left acc
×                     ; pc pc left.right acc'
1E4                   ; pc left.right acc' 10000
÷                     ; pc pc left.right .acc'
LASTX                 ; pc left.right .acc' 10000
X<>Y                  ; pc left.right 1000 .acc'
FP                    ; pc left.right 1000 .acc'
×                     ; pc pc left.right acc"
X<>Y                  ; pc pc acc" left.right
FP                    ; pc pc acc" .right
10                    ; pc acc" .right 10
×                     ; pc pc acc" right
10↑X                  ; pc pc acc" 10↑right
÷                     ; pc pc pc acc~
IP                    ; pc pc pc acc`
X<>Y                  ; pc pc acc` pc
RTN                   ; acc` pc
;------- OUT ---------;------------------
LBL 05                ; acc pc .addr
1E2                   ; acc pc .addr 100
×                     ; acc acc pc addr
VIEW IND ST X         ; acc acc pc addr
RDN                   ; addr acc acc pc END 
RTN                   ; acc pc
;------- STO ---------;------------------
LBL 06                ; acc pc .addr
1E2                   ; acc pc .addr 100
×                     ; acc acc pc addr
X<> ST Z              ; acc addr pc acc
STO IND ST Z          ; acc addr pc acc
1E3                   ; addr pc acc 1000
÷                     ; addr addr pc .acc
LASTX                 ; addr pc .acc 1000
X<>Y                  ; addr pc 1000 .acc
FP                    ; addr pc 1000 .acc'
×                     ; addr addr pc acc'
X<> IND ST Z          ; addr addr pc acc
X<>Y                  ; addr addr acc pc
RTN                   ; addr pc
;------- SUB ---------;------------------
LBL 07                ; acc pc .addr
1E2                   ; acc pc .addr 100
×                     ; acc acc pc addr
X<> ST Z              ; acc addr pc acc
RCL- IND ST Z         ; acc addr pc acc'
X<>Y                  ; acc addr acc' pc
RTN                   ; acc' pc
;------- JMP ---------;------------------
LBL 08                ; acc pc .addr
1E2                   ; acc pc .addr 100
×                     ; acc acc pc addr
X<>Y                  ; acc acc addr pc
8E2                   ; acc addr pc 800
+                     ; acc acc addr pc'
STO 99                ; acc acc addr pc'
RDN                   ; pc' acc acc addr
RTN                   ; acc addr
;------- HRS ---------;------------------
LBL 09                ; acc pc .addr
1E2                   ; acc pc .addr 100
×                     ; acc acc pc addr
X<>Y                  ; acc acc addr pc
RDN                   ; pc acc acc addr
SF 00                 ; pc acc acc addr
END                   ; acc addr
;---------------------;------------------

Attachment
Code:
Archive:  cardiac.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
     5504  10-11-2014 22:42   cardiac.txt
      210  10-11-2014 22:42   cardiac.raw
     2206  10-11-2014 22:43   cardiac.py
---------                     -------
     7920                     3 files


Attached File(s)
.zip  cardiac.zip (Size: 2.06 KB / Downloads: 4)
Find all posts by this user
Quote this message in a reply
10-12-2014, 06:15 PM
Post: #2
RE: (HP-42S) CARDIAC
Greatest Common Divisor

Code:
05              a   DATA
06              b   DATA
07              c   DATA

10  005     load        INP     a
11  006                 INP     b
12  105     start       CLA     a
13  605     loop        STO     b
14  706                 SUB     b
15  317                 TAC     break
16  813                 JMP     loop
17  105     break       CLA     a
18  607                 STO     c
19  700                 SUB     1
20  326                 TAC     exit
21  106                 CLA     b
22  605                 STO     a
23  107                 CLA     c
24  606                 STO     b
25  812                 JMP     start
26  506                 OUT     b
27  910                 HRS     load

Example (after loading the program):

What is gcd(408, 360)?

408 STO 05
360 STO 06
12 XEQ 99

The result is:

R06=24

You can copy&paste this deck of cards into the simulator to run this example:

2
800
10
005
11
006
12
105
13
605
14
706
15
317
16
813
17
105
18
607
19
700
20
326
21
106
22
605
23
107
24
606
25
812
26
506
27
910
810
408
360
Find all posts by this user
Quote this message in a reply
10-13-2014, 07:30 PM
Post: #3
RE: (HP-42S) CARDIAC
Very cool. Kind of reminds me of the Manchester Small-Scale Experimental Machine emulator I wrote on my TI-92 back in high school. It was several orders of magnitude slower than the real thing; I imagine this CARDIAC simulator doesn't have the same problem. Smile
Visit this user's website Find all posts by this user
Quote this message in a reply
10-13-2014, 09:06 PM
Post: #4
RE: (HP-42S) CARDIAC
Loading and running the gcd-program above took ~42s while just running it took ~21s.
I used Christoph Giesselink's Emu42 but in my experience its speed is close to the original.

Could you write useful programs with your emulator? Have you been running one of the first programs?
Find all posts by this user
Quote this message in a reply
10-13-2014, 09:27 PM
Post: #5
RE: (HP-42S) CARDIAC
I don't recall programming anything terribly sophisticated with it. The original machine had only 7 instructions - one of them being stop - and no add instruction, just subtract and a combined load/negate. I was able to run various example programs on it, though, including one that would scroll a simple bitmap graphic across the "display" (very, very slowly, in the case of my emulator).

The TI-92 variety of Basic requires a lot of string handling for the type of indirection I was doing, so I wouldn't be surprised if the 42S could emulate it faster.
Visit this user's website Find all posts by this user
Quote this message in a reply
10-16-2014, 09:49 PM
Post: #6
RE: (HP-42S) CARDIAC
Factor

This is a very simple CARDIAC-program to find the factors of a number:
Code:
    03      0   ; DATA
    04      2   ; DATA    
    05      n   ; DATA
    06      p   ; DATA
    07      m   ; DATA
    08      q   ; DATA
                
    10  005     ; start           INP n
    11  104     ;                 CLA 2
    12  606     ;                 STO p
    13  105     ; trial           CLA n
    14  607     ;                 STO m
    15  103     ;                 CLA 0
    16  608     ;                 STO q
    17  107     ; division        CLA m
    18  706     ;                 SUB p
    19  607     ;                 STO m
    20  325     ;                 TAC break
    21  108     ;                 CLA q
    22  200     ;                 ADD 1
    23  608     ;                 STO q
    24  817     ;                 JMP division
    25  206     ; break           ADD p
    26  607     ;                 STO m
    27  700     ;                 SUB 1
    28  333     ;                 TAC factor
    29  106     ;                 CLA p
    30  200     ;                 ADD 1
    31  606     ;                 STO p
    32  813     ;                 JMP trial
    33  506     ; factor          OUT p
    34  108     ;                 CLA m
    35  605     ;                 STO n
    36  704     ;                 SUB 2
    37  339     ;                 TAC prime
    38  813     ;                 JMP trial
    39  910     ; prime           HRS start

As long as you don't use self-modifying code it can be translated 1:1 to the HP-42S:
Code:
LBL "FACTOR"    ; start           
STO 05          ;                 INP n
RCL 04          ;                 CLA 2
STO 06          ;                 STO p
LBL 00          ; trial           
RCL 05          ;                 CLA n
STO 07          ;                 STO m
RCL 03          ;                 CLA 0
STO 08          ;                 STO q
LBL 01          ; division        
RCL 07          ;                 CLA m
RCL- 06         ;                 SUB p
STO 07          ;                 STO m
X<0?            ;                 TAC
GTO 02          ;                     break
RCL 08          ;                 CLA q
RCL+ 00         ;                 ADD 1
STO 08          ;                 STO q
GTO 01          ;                 JMP division
LBL 02          ; break           
RCL+ 06         ;                 ADD p
STO 07          ;                 STO m
RCL- 00         ;                 SUB 1
X<0?            ;                 TAC
GTO 03          ;                     factor
RCL 06          ;                 CLA p
RCL+ 00         ;                 ADD 1
STO 06          ;                 STO p
GTO 00          ;                 JMP trial
LBL 03          ; factor                
VIEW 06         ;                 OUT p
RCL 08          ;                 CLA m
STO 05          ;                 STO n
RCL- 04         ;                 SUB 2
X<0?            ;                 TAC
GTO 04          ;                     prime
GTO 00          ;                 JMP trial
LBL 04          ; prime           
END             ;                 HRS start

Just make sure to initialize registers 00, 03 and 04 with 1, 0 and 2:
1 STO 00
0 STO 03
2 STO 04
Find all posts by this user
Quote this message in a reply
Post Reply 




User(s) browsing this thread: 1 Guest(s)