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