Der folgende Text ist ein Assembler-Listing, das vom AS V1.41 von Alfred Arnold generiert wurde. AS ist ein beliebig anpaßbarer Cross-Assembler, für den ich einen Codegenerator für den PALM-Prozessor implementiert habe.
Das Programm soll als kleine Demonstration der Maschine dienen. Es werden auf dem Schirm einige
Hindernisse in Form von Wänden dargestellt. Innerhalb des Schirms bewegt sich dann ein Ball, der
sowohl an den Wänden wie auch an den Schirmrändern abprallt. Bei jeder Kollision ertönt ein
durch die kurze Dauer gläsern wirkende Ton, der prima dazu paßt. Das Programm wird wie jedes
Maschinenspracheprogramm mit LINK oder )LINK geladen. Die Ladeadresse ist fest bei $0B00 vorgegeben.
Das Programm ist auf Einfachheit ausgelegt und nicht auf besonders geschickte oder optimierte
Programmierung.
Quelltext und Binärdatei in downloadbarer Form werde ich mit anderen Programmen
später noch in diese Seiten aufnehmen.
1/ 0 : ; *********************************************************** 2/ 0 : ; 3/ 0 : ; Bewegt einen "Ball" innerhalb der Begrenzungen des Schirms. 4/ 0 : ; Zusätzlich sind einige Wände als Hindernisse vorhanden. 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 : ; Setze Prozessorstatus 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 ; Schirm einschalten 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 ; Richtung 43/ B32 : 44/ B32 : Loop: 45/ B32 : D701 0200 LWI R7, #$0200 46/ B36 : 47/ B36 : ; Ermittle aus Zeile und Spalte die Bildschirmadresse 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) ; Merke Inhalt der alten Position 63/ B50 : 7378 MOVB (R7), R3 ; Schreibe Ball dorthin 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 ; Stelle alte Position wieder her 71/ B60 : 72/ B60 : F02F BRA Loop 73/ B62 : 74/ B62 : D001 0CAA JMP Ende 75/ B66 : 76/ B66 : ; ********
Wie der Name suggeriert, wird hier der Schirm gelöscht. Dies wird hier durch das Schreiben von Leerzeichen von $0200 bis $05FF erreicht.
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 : ; ********
In BuildWalls werden die paar "Wände" aufgebaut. Lage und Größe sind festkodiert; als Wandelement wird das Zeichen $FF (ausgefüllte Zeichenzelle) benutzt.
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 wird nach jeder neuen Ballposition aufgerufen, damit der Ball nicht mit Höchstgeschwindigkeit über den Schirm rast. Die Verzögerung ist empirisch ermittelt.
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 : ; ********
In CalcNewPos wird die nächste Position des Balls berechnet. Dabei wird neben der aktuellen Bewegungsrichtung (in "Richt") die Kollision mit den Schirmbegrenzungen oder mit einer Wand (Zeichen $FF) berücksichtigt. Falls eine Kollision auftritt, wird "Sound" aufgerufen. Es können durchauch mehrere Kollisionen hintereinander entdeckt werden; dies ist z.B. der Fall, wenn der Ball in eine Ecke fliegt.
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 ; Merke alte X-Position 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 : ; Überprüfe, ob Ball eine Wand seitlich getroffen hat 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 : ; Wand getroffen 192/ C2C : 0AD4 MOVE R10, R13 ; Gehe an alte X-Position zurück 193/ C2E : 8910 LBI R9, #$10 194/ C30 : 0F97 XOR R15, R9 ; Kehre X-Richtung um 195/ C32 : 0803 D081 0C9C CALL Sound, R8 196/ C38 : A059 BRA cnp5 ; Keine neue Y-Position 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 : ; Überprüfe, ob Ball eine Wand on oben oder unten getroffen hat 226/ C68 : DB58 MOVE R11, (R5) ; Alte Y-Position 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 : ; Wand getroffen 239/ C7C : D501 0CC8 LWI R5, #XPos 240/ C80 : 5D58 MOVE (R5), R13 ; Gehe an alte X-Position zurück 241/ C82 : D501 0CCA LWI R5, #YPos 242/ C86 : 0AB4 MOVE R10, R11 ; Gehe an alte Y-Position zurück 243/ C88 : 8901 LBI R9, #$01 244/ C8A : 0F97 XOR R15, R9 ; Kehre Y-Richtung um 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 : ; ********
Da die IBM 5110 einen Piezosummer hat, besteht die einzige effektvolle Variation des schrillen Tones in Änderung der Dauer. Die 255 Schleifendurchläufe ergeben gerade ein kurzes "Plick" (oder wie man das auch nennen möchte). Es ist mir bisher nicht gelungen, durch verschachtelte Schleifen an der wahrgenommenen Tonhöhe etwas zu verändern.
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 : ; ********
Diese Prozedur wird in diesem Programm zwar nie angesprungen. Sie zeigt aber, wie man aus einen Maschinenspracheprogramm wieder in den Interpreter zurückkehren kann.
268/ CAA : 269/ CAA : Ende: 270/ CAA : ; Prozessorstatus wiederherstellen 271/ CAA : DF01 0CCE LWI R15, #Status_Save 272/ CAE : D1F8 MOVE R1, (R15) 273/ CB0 : 3152 MOVE $A4, R1 274/ CB2 : 275/ CB2 : ; Auswahl APL- oder 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 ; Wähle APL-ROS aus 280/ CBA : 281/ CBA : 28E7 MOVE R8, $1CE 282/ CBC : 3868 MOVE $D0, R8 283/ CBE : 284/ CBE : ; Rücksprung in den Interpreter 285/ CBE : 2867 MOVE R8, $CE 286/ CC0 : 0880 DEC2 R8, R8 287/ CC2 : 2056 JMP ($AC)
Der Datenbereich. "XPos" und "YPos" ist die Startposition des Balls in Schirmkoordinaten. "Ball" enthält das Schirmzeichen, das für den Ball benutzt wird. In "Richt" wird die momentane Bewegungsrichtung des Balls festgehalten.
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