• Please review our updated Terms and Rules here

IBM PALM assembler now in Macro Assembler AS

voidstar78

Veteran Member
Joined
May 25, 2021
Messages
690
Location
Texas
On a request, Alfred Arnold had added PALM instruction set support to the Macro Assembler AS that is located here:


And in the coming months, we'll see if we can pair that up to a C compiler.

I saw also in another thread that the KINBAK-1 anniversary is this year - and I didn't realize this before, but the Macro Assembler AS will target to the KINBAK instruction set as well!!

Anyhow, the PALM additions are *freshly done* -- as in literally earlier today. I've verified that it perfectly compiles Christian Corti's original PALM examples, so that's an excellent first start. Mr. Arnold went so far as to support *both* IBM's "standard" assembly mnemonics and Corti's much-easier-to-follow update mnemonics.

So, if anyone has pages of old IBM PALM assembly, we're ready to dust that off :)

Meanwhile, we've got some ideas brewing..
- Breakout or Tetris (single screen stuff)
- Memory (something that might require using the L32/R32 to flip)
- Simple Terminal (exercise external IO to connect up a WiModem232)
- Bad Apple Demo, on a 5100? @Trixter (not disk load streaming, but whatever could fit in 64KB)

NOTE: Aside from keyboard scan code and display-character-code differences, the 5100 and 5110 (and probably 5120) can run all the same code. But for audio beeping, you'd have to use a 5110 (it can't be easily retrofitted to a 5100, since the audio buzzer was relayed through the Display card - as I understand it)


I've been working on consolidating some IBM 5100 related "knowledge-stuff" at a site. It's not quite ready for prime time -- I don't even have photos of my own 5100 up yet (been too much activity around to setup proper lighting -- but I do have notes up about the 5106 unit). However, I do want to share what will be my page on notes about this PALM assembler. That will be here:

https://voidstar.blog/ibm-5100-palm-assembler/

Cheers, and much kudos and thanks to Alfred Arnold for taking the time to do this ! Very honored.

@stepleton
 
Last edited:
Attached is a fairly extensive example of some PALM assembly in action, annotated to explain what is going on along the way. I put this together to help wring the AS assembler through its paces.


The program first runs through a boilerplate exercise of various PALM instructions.

After that, the program then has this main behavior:

It clears the screens (using two different approaches) and draws two strings at calculated positions (using CALLs).

Then it starts looping a 32-bit counter (using two 16-bit registers). During this loop, the program monitors for a key being pressed.

WASD keys will move the first string around on the screen (the position is updated in a small data structure and the screen position re-calculated by the CALLed function).

Q and E keys can be used to decrement/increment a "duration amount" that is stored in memory.

Any other key causes the speaker to BEEP for the currently set duration amount of time.

Any time a key is pressed, a separate counter is incremented in memory (effectively recording the number of times the "main loop" has been executed).


Here is an example of a couple of the functions:

Code:
; *************************    
; R5 = ComputeRowCol(R12)
; *************************    
; R12 is the address of the coordinates (HI=ROW, LO=COL) to be computed
; into a linear address (result stored in R5).
ComputeRowCol:
        MOVE  R13, (R12)    ; R13 = RWS[R12]
        MHL   R11, R13      ; LO(R11) = HI(R13)
        LWI   R5,  #$0200   ; CRT memory mapped output starts at address $0200
        LBI   R4,  #COL_PER_ROW
computeRowCol_again:
        SZ    R11
        BRA   nextRow
        BRA   nextStage_addCol
nextRow:
        DEC   R11
        ADD   R5, R4        ; add 64 (full row)
        BRA   computeRowCol_again
nextStage_addCol:
        ADD   R5, R13       ;
        RET   R2
; *************************


Code:
; *************************
; R11 = CheckKey(R8)
; *************************
; R8  OUT: Copy of the pressed key.
; R11 OUT: LO(R11) == 0 if no key pressed, else LO(R11) == 1 if key pressed
CheckKey:
        LWI   R11, ADDR_RWS_KEY_INPUT  ; R11 = value of ADDR_RWS_KEY_INPUT
        MOVE  R14, (R11)      ; R14 = RWS[R11]
                              ; (capture last reported key press)

        ; Make two copies of the current last key pressed...
        MOVE  R8,  R14        ; R8 = R14 (make copy)

        LWI   R13, (ADDR_LAST_KEY+2)   ; R13 = extra copy of last key
        MOVE  (R13), R14          ; RWS[R13] = R14 (store the copy)
        ; This is done because when a key press does end up detected,
        ;   ADDR_LAST_KEY will get reset.  In case the R8 register copy
        ;   gets overwritten, we still have an extra copy of the last
        ;   if it is needed.

        LWI   R13, ADDR_LAST_KEY  ; R13 = address of last key (copy)
        MOVE  R12, (R13)          ; R12 = RWS[R13]
     
        SUB   R14, R12       ; R14 = R14 - R12  (if same, result is 0)
        SZ    R14            ; does R11 == R12?      
        BRA   storeKey    ; <-- no, new key detected, go store it...
        LBI   R11, #$00   ; <-- yes, no new key, return R11 = 0
        RET   R2
     
storeKey:
        LBI   R10, #$00     ; We can't write directly to memory from an opcode
                            ; We have to go through a register that has the
                            ; value we want to write.

        MOVB  (R11), R10    ; RWS[R11] = R10 (0) (R11 is ADDR_RWS_KEY_INPUT)
        MOVE  (R13), R10    ; RWS[R13] = R10 (0) (R13 is ADDR_LAST_KEY)
        ; The above is done to zeroize the key reference. That is, to set a
        ;   "baseline" state that indicates that "relative to the last time
        ;   we checked, no new key has been pressed."  This is similar to
        ;   calling InitKey again, except that we're not setup to do
        ;   nested calls.
        ; NOTE: The key that was last pressed is preserved in R8 or
        ; in memory (the second "backup" copy at ADDR_LAST_KEY+2)

        LBI   R11,  #$01  ; Return R11 = 1 (flag indicating a key was pressed)
        RET   R2
; *************************


The resulting assembled machine code is around 830 bytes and runs great in the emulator.

I haven't typed it in yet on the IBM 5110. I may, but I'm also studying more about the GETB and PUTB instructions to try to define a Device Address and communicate across the external pins at the back of the system - and use that to digitally transfer the code (hopefully within under 100 bytes of a little loader software, which we can then use to start loading in much larger sample programs).

NOTE: All of this will work on the IBM 5100 as well, but different keyboard scan-codes and display-code are used.

NOTE: I'm sticking with the "Corti-style" mnemonics (they truly are more intuitive than IBM's original).
 

Attachments

  • palm_sample.asm.txt
    32.9 KB · Views: 3
Last edited:
Back
Top