The following text is an assembler listing generated with AS V1.41 from Alfred Arnold. AS is an easily customizable cross assembler for many systems to which I have added a code generator for the PALM processor.

This program should be a small demonstration of the machine. Several obstacles (walls) are created on the screen. A ball bounces within the screen boundaries and reflects either at one of the screen borders or at a wall. Each collision will be accompanied with a short sound. This program is loaded like any other machine program with LINK or )LINK. The load address is fixed to $0B00. The program is held as simple as possible so it's not using sophisticated algorithms.
Source code and binary in downloadable form will be found on these pages later.

       1/       0 :                     ; ***********************************************************
       2/       0 :                     ;
       3/       0 :                     ; Moves a "ball" within the screen boundaries. In addition
       4/       0 :                     ; some walls as obstacles are added.
       5/       0 :                     ;
       6/       0 :                     ; ***********************************************************
       7/       0 :
       8/       0 :                             cpu IBM5110
       9/       0 :
      10/       0 :                             include "ebcdic.inc"
      11/       0 :
      12/     B00 :                             org $0B00
      13/     B00 :
      14/     B00 :                     Start:
      15/     B00 :                             ; Set processor state
      16/     B00 : 2152                        MOVE R1, $A4
      17/     B02 : DF01 0CCE                   LWI R15, #Status_Save
      18/     B06 : 51F8                        MOVE (R15), R1
      19/     B08 :
      20/     B08 : 021C                        MHL R2, R1
      21/     B0A : 9204                        CLR R2, #$04
      22/     B0C : B201                        SET R2, #$01
      23/     B0E : 012D                        MLH R1, R2
      24/     B10 : 3152                        MOVE $A4, R1
      25/     B12 :
      26/     B12 : 1077                        CTRL $0, #$77        ; turn screen on
      27/     B14 :
      28/     B14 :                     Main:
      29/     B14 :
      30/     B14 : =$400               SCREENSIZE equ 16*64
      31/     B14 :
      32/     B14 : 0203 D021 0B66              CALL ClrScr, R2
      33/     B1A : 0203 D021 0B7E              CALL BuildWalls, R2
      34/     B20 :
      35/     B20 : 2150                        MOVE R1, $A0
      36/     B22 : D201 0CC8                   LWI R2, #XPos
      37/     B26 : 8111                        LBI R1, #17
      38/     B28 : 5121                        MOVE (R2)+, R1        ; XPos
      39/     B2A : 8103                        LBI R1, #3
      40/     B2C : 5121                        MOVE (R2)+, R1        ; YPos
      41/     B2E : 8111                        LBI R1, #$11
      42/     B30 : 5128                        MOVE (R2), R1        ; direction
      43/     B32 :
      44/     B32 :                     Loop:
      45/     B32 : D701 0200                   LWI R7, #$0200
      46/     B36 :
      47/     B36 :                             ; Calculate a screen address from line and column
      48/     B36 : D401 0CCA                   LWI R4, #YPos
      49/     B3A : D345                        MOVE R3, (R4)-
      50/     B3C : C30B                        SNZ R3
      51/     B3E : A007                        BRA l2
      52/     B40 : A73F                l1:     ADD R7, #64
      53/     B42 : 0331                        DEC R3, R3
      54/     B44 : C303                        SZ R3
      55/     B46 : F007                        BRA l1
      56/     B48 :
      57/     B48 : D347                l2:     MOVE R3, (R4)--
      58/     B4A : 0738                        ADD R7, R3
      59/     B4C :
      60/     B4C : D341                        MOVE R3, (R4)+
      61/     B4E :
      62/     B4E : 6678                        MOVB R6, (R7)        ; save contents of prev. location
      63/     B50 : 7378                        MOVB (R7), R3        ; writes "ball" into location
      64/     B52 :
      65/     B52 : 0203 D021 0BD6              CALL Delay, R2
      66/     B58 : 0203 D021 0BE6              CALL CalcNewPos, R2
      67/     B5E :
      68/     B5E :                     ;
      69/     B5E :                     ;
      70/     B5E : 7678                        MOVB (R7), R6        ; restore prev. location
      71/     B60 :
      72/     B60 : F02F                        BRA Loop
      73/     B62 :
      74/     B62 : D001 0CAA                   JMP Ende
      75/     B66 :
      76/     B66 :                     ; ********

As the name suggests this routine clears the screen. This is done by writing blanks into locations $0200 to $05FF.

      77/     B66 :
      78/     B66 :                     ClrScr:
      79/     B66 : D501 0200                   LWI R5, #$0200
      80/     B6A : D601 0400                   LWI R6, #SCREENSIZE
      81/     B6E : 8740                        LBI R7, #' '
      82/     B70 : 7750                cs_1:   MOVB (R5)+, R7
      83/     B72 : 0661                        DEC R6, R6
      84/     B74 : 086C                        MHL R8, R6
      85/     B76 : 0866                        OR R8, R6
      86/     B78 : C803                        SZ R8
      87/     B7A : F00B                        BRA cs_1
      88/     B7C : 0024                        RET R2
      89/     B7E :
      90/     B7E :                     ; ********

The routine BuildWalls creates some "walls". Position and size are hard coded, the character $FF is taken as brick element (filled character).

      91/     B7E :
      92/     B7E :                     BuildWalls:
      93/     B7E : D501 04CA                   LWI R5, #$0200+(11*64)+10
      94/     B82 : 8605                        LBI R6, #5
      95/     B84 : D701 FFFF                   LWI R7, #$FFFF
      96/     B88 :
      97/     B88 : 5758                bw_1:   MOVE (R5), R7
      98/     B8A : F600                        SUB R6, #1
      99/     B8C : C60B                        SNZ R6
     100/     B8E : A003                        BRA bw_2
     101/     B90 : A53F                        ADD R5, #64
     102/     B92 : F00B                        BRA bw_1
     103/     B94 :
     104/     B94 : D501 02B2           bw_2:   LWI R5, #$0200+(2*64)+50
     105/     B98 : 8603                        LBI R6, #3
     106/     B9A : 5758                bw_4:   MOVE (R5), R7
     107/     B9C : F600                        SUB R6, #1
     108/     B9E : C60B                        SNZ R6
     109/     BA0 : A003                        BRA bw_5
     110/     BA2 : A53F                        ADD R5, #64
     111/     BA4 : F00B                        BRA bw_4
     112/     BA6 :
     113/     BA6 : D501 031E           bw_5:   LWI R5, #$0200+(4*64)+30
     114/     BAA : 8608                        LBI R6, #8
     115/     BAC : 5758                bw_6:   MOVE (R5), R7
     116/     BAE : F600                        SUB R6, #1
     117/     BB0 : C60B                        SNZ R6
     118/     BB2 : A003                        BRA bw_7
     119/     BB4 : A53F                        ADD R5, #64
     120/     BB6 : F00B                        BRA bw_6
     121/     BB8 :
     122/     BB8 : D501 0526           bw_7:   LWI R5, #$0200+(12*64)+38
     123/     BBC : 8604                        LBI R6, #4
     124/     BBE : 5751                bw_8:   MOVE (R5)+, R7
     125/     BC0 : F600                        SUB R6, #1
     126/     BC2 : C603                        SZ R6
     127/     BC4 : F007                        BRA bw_8
     128/     BC6 :
     129/     BC6 : D501 0414           bw_9:   LWI R5, #$0200+(8*64)+20
     130/     BCA : 8603                        LBI R6, #3
     131/     BCC : 5751                bw_10:  MOVE (R5)+, R7
     132/     BCE : F600                        SUB R6, #1
     133/     BD0 : C603                        SZ R6
     134/     BD2 : F007                        BRA bw_10
     135/     BD4 :
     136/     BD4 : 0024                bw_99:  RET R2
     137/     BD6 :
     138/     BD6 :                     ; ********

Delay is called after each new ball position to prevent the ball from moving too fast over the screen. The delay value has been determined manually.

     139/     BD6 :
     140/     BD6 :                     Delay:
     141/     BD6 : DF01 0BB8                   LWI R15, #3000
     142/     BDA : FF00                del_1:  SUB R15, #1
     143/     BDC : 0EFC                        MHL R14, R15
     144/     BDE : 0EF6                        OR R14, R15
     145/     BE0 : CE03                        SZ R14
     146/     BE2 : F009                        BRA del_1
     147/     BE4 : 0024                        RET R2
     148/     BE6 :
     149/     BE6 :                     ; ********

CalcNewPos calculates the next position of the ball. Along with the current moving direction (var. "Richt") a collision either with a screen border or with a wall is taken into account. In case of a collision the "Sound" routine will be called. Several collision may occur e.g. when the ball flies into a corner.

     150/     BE6 :
     151/     BE6 :                     CalcNewPos:
     152/     BE6 : D501 0CCC                   LWI R5, #Richt
     153/     BEA : DF58                        MOVE R15, (R5)
     154/     BEC :
     155/     BEC :                             ; X-Position
     156/     BEC :
     157/     BEC : D501 0CC8                   LWI R5, #XPos
     158/     BF0 : DA58                        MOVE R10, (R5)
     159/     BF2 : 0DA4                        MOVE R13, R10                ; store old X-pos.
     160/     BF4 : 8310                        LBI R3, #$10
     161/     BF6 : CF3D                        SNBS R15, R3
     162/     BF8 : A011                        BRA cnp1
     163/     BFA :
     164/     BFA : AA00                        ADD R10, #1
     165/     BFC : 8C3F                        LBI R12, #63
     166/     BFE : CAC9                        SGE R10, R12
     167/     C00 : A017                        BRA cnp2
     168/     C02 : BF10                        SET R15, #$10
     169/     C04 : 0803 D081 0C9C              CALL Sound, R8
     170/     C0A : A00D                        BRA cnp2
     171/     C0C :
     172/     C0C : FA00                cnp1:   SUB R10, #1
     173/     C0E : CA03                        SZ R10
     174/     C10 : A007                        BRA cnp2
     175/     C12 : 9F10                        CLR R15, #$10
     176/     C14 : 0803 D081 0C9C              CALL Sound, R8
     177/     C1A :
     178/     C1A :                     cnp2:
     179/     C1A :                             ; Check if ball touched the side of a wall
     180/     C1A : CAD8                        SGT R10, R13
     181/     C1C : A003                        BRA cnp2_1
     182/     C1E : 0E72                        INC R14, R7
     183/     C20 : A001                        BRA cnp2_2
     184/     C22 : 0E71                cnp2_1: DEC R14, R7
     185/     C24 :                     cnp2_2:
     186/     C24 : 68E8                        MOVB R8, (R14)
     187/     C26 : 89FF                        LBI R9, #$FF
     188/     C28 : C892                        SE R8, R9
     189/     C2A : A00D                        BRA cnp2_3
     190/     C2C :
     191/     C2C :                             ; Collision with wall
     192/     C2C : 0AD4                        MOVE R10, R13        ; return to old X-pos.
     193/     C2E : 8910                        LBI R9, #$10
     194/     C30 : 0F97                        XOR R15, R9          ; reverse X direction
     195/     C32 : 0803 D081 0C9C              CALL Sound, R8
     196/     C38 : A059                        BRA cnp5             ; keep Y-pos.
     197/     C3A :
     198/     C3A : 5A58                cnp2_3: MOVE (R5), R10
     199/     C3C :
     200/     C3C :
     201/     C3C :
     202/     C3C :                             ; Y-Position
     203/     C3C :
     204/     C3C : D501 0CCA                   LWI R5, #YPos
     205/     C40 : DA58                        MOVE R10, (R5)
     206/     C42 : 8301                        LBI R3, #$01
     207/     C44 : CF3D                        SNBS R15, R3
     208/     C46 : A011                        BRA cnp3
     209/     C48 :
     210/     C48 : AA00                        ADD R10, #1
     211/     C4A : 8C0F                        LBI R12, #15
     212/     C4C : CAC9                        SGE R10, R12
     213/     C4E : A017                        BRA cnp4
     214/     C50 : BF01                        SET R15, #$01
     215/     C52 : 0803 D081 0C9C              CALL Sound, R8
     216/     C58 : A00D                        BRA cnp4
     217/     C5A :
     218/     C5A : FA00                cnp3:   SUB R10, #1
     219/     C5C : CA03                        SZ R10
     220/     C5E : A007                        BRA cnp4
     221/     C60 : 9F01                        CLR R15, #$01
     222/     C62 : 0803 D081 0C9C              CALL Sound, R8
     223/     C68 :
     224/     C68 :                     cnp4:
     225/     C68 :                             ; Check if ball touched the top or bottom of a wall
     226/     C68 : DB58                        MOVE R11, (R5)        ; store old Y-pos.
     227/     C6A : CAB8                        SGT R10, R11
     228/     C6C : A003                        BRA cnp4_1
     229/     C6E : AE3F                        ADD R14, #64
     230/     C70 : A001                        BRA cnp4_2
     231/     C72 : FE3F                cnp4_1: SUB R14, #64
     232/     C74 :                     cnp4_2:
     233/     C74 : 68E8                        MOVB R8, (R14)
     234/     C76 : 89FF                        LBI R9, #$FF
     235/     C78 : C892                        SE R8, R9
     236/     C7A : A015                        BRA cnp4_3
     237/     C7C :
     238/     C7C :                             ; Collision with wall
     239/     C7C : D501 0CC8                   LWI R5, #XPos
     240/     C80 : 5D58                        MOVE (R5), R13        ; return to old X-pos.
     241/     C82 : D501 0CCA                   LWI R5, #YPos
     242/     C86 : 0AB4                        MOVE R10, R11         ; return to old Y-pos.
     243/     C88 : 8901                        LBI R9, #$01
     244/     C8A : 0F97                        XOR R15, R9           ; reverse Y direction
     245/     C8C : 0803 D081 0C9C              CALL Sound, R8
     246/     C92 :
     247/     C92 : 5A58                cnp4_3: MOVE (R5), R10
     248/     C94 :
     249/     C94 :
     250/     C94 : D501 0CCC           cnp5:   LWI R5, #Richt
     251/     C98 : 5F58                        MOVE (R5), R15
     252/     C9A :
     253/     C9A : 0024                        RET R2
     254/     C9C :
     255/     C9C :                     ; ********

As the IBM 5110 has only a piezo beeper the only way of effectfully varying the tone is changing its duration. The 255 loop iterations used here just make a short "plick" sound (don't know how to call it). I haven't been successful in varying the frequency of the sound.

     256/     C9C :
     257/     C9C :                     Sound:
     258/     C9C : 89FF                        LBI R9, #255
     259/     C9E : 107E                        CTRL $0, #$7E
     260/     CA0 : F900                snd1:   SUB R9, #1
     261/     CA2 : C903                        SZ R9
     262/     CA4 : F005                        BRA snd1
     263/     CA6 : 107D                        CTRL $0, #$7D
     264/     CA8 :
     265/     CA8 : 0084                        RET R8
     266/     CAA :
     267/     CAA :                     ; ********

This point of the program will never be reached but it shows how a machine program can return to the interpreter.

     268/     CAA :
     269/     CAA :                     Ende:
     270/     CAA :                             ; restore processor status
     271/     CAA : DF01 0CCE                   LWI R15, #Status_Save
     272/     CAE : D1F8                        MOVE R1, (R15)
     273/     CB0 : 3152                        MOVE $A4, R1
     274/     CB2 :
     275/     CB2 :                             ; select APL- or BASIC-ROS
     276/     CB2 : 28FC                        MOVE R8, $1F8
     277/     CB4 : 8220                        LBI R2, #$20
     278/     CB6 : C82E                        SNBC R8, R2
     279/     CB8 : 1104                        CTRL $1, #$04        ; select APL-ROS
     280/     CBA :
     281/     CBA : 28E7                        MOVE R8, $1CE
     282/     CBC : 3868                        MOVE $D0, R8
     283/     CBE :
     284/     CBE :                             ; jump back to the interpreter
     285/     CBE : 2867                        MOVE R8, $CE
     286/     CC0 : 0880                        DEC2 R8, R8
     287/     CC2 : 2056                        JMP ($AC)

This is the data area. "XPos" and "YPos" give the starting location of the ball in screen coordinates. "Ball" contains the screen character of the ball. "Richt" stores the current direction of the ball movement.

     288/     CC4 :
     289/     CC4 : 00 FD               Ball:   dw $FD
     290/     CC6 : 00 40               Blank:  dw ' '
     291/     CC8 : 00 0A               XPos:   dw 10
     292/     CCA : 00 0A               YPos:   dw 10
     293/     CCC : 00 11               Richt:  dw $11
     294/     CCE :
     295/     CCE :
     296/     CCE : 00 00               Status_Save:        dw 0
     297/     CD0 :
     298/     CD0 :                             end