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