Skip to content

Commit e569419

Browse files
committed
add test to check for array boundary checking
Note that both #pragma and #define must be used since the array checking requires such define that might not be declared at the beginning.
1 parent 7833016 commit e569419

2 files changed

Lines changed: 399 additions & 0 deletions

File tree

tests/functional/arrcheck.asm

Lines changed: 389 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,389 @@
1+
org 32768
2+
__START_PROGRAM:
3+
di
4+
push ix
5+
push iy
6+
exx
7+
push hl
8+
exx
9+
ld hl, 0
10+
add hl, sp
11+
ld (__CALL_BACK__), hl
12+
ei
13+
ld hl, (_b)
14+
push hl
15+
ld hl, 5
16+
push hl
17+
ld hl, (_b)
18+
push hl
19+
ld hl, 10
20+
push hl
21+
ld hl, _a
22+
call __ARRAY
23+
ld (hl), 7
24+
ld hl, (_b)
25+
push hl
26+
ld hl, 5
27+
push hl
28+
ld hl, (_b)
29+
ld de, 6
30+
add hl, de
31+
push hl
32+
ld hl, 10
33+
push hl
34+
ld hl, _a
35+
call __ARRAY
36+
ld a, (hl)
37+
ld (_c), a
38+
ld (_c), a
39+
ld hl, 0
40+
ld b, h
41+
ld c, l
42+
__END_PROGRAM:
43+
di
44+
ld hl, (__CALL_BACK__)
45+
ld sp, hl
46+
exx
47+
pop hl
48+
exx
49+
pop iy
50+
pop ix
51+
ei
52+
ret
53+
__CALL_BACK__:
54+
DEFW 0
55+
#line 1 "array.asm"
56+
57+
; vim: ts=4:et:sw=4:
58+
; Copyleft (K) by Jose M. Rodriguez de la Rosa
59+
; (a.k.a. Boriel)
60+
; http://www.boriel.com
61+
; -------------------------------------------------------------------
62+
; Simple array Index routine
63+
; Number of total indexes dimensions - 1 at beginning of memory
64+
; HL = Start of array memory (First two bytes contains N-1 dimensions)
65+
; Dimension values on the stack, (top of the stack, highest dimension)
66+
; E.g. A(2, 4) -> PUSH <4>; PUSH <2>
67+
68+
; For any array of N dimension A(aN-1, ..., a1, a0)
69+
; and dimensions D[bN-1, ..., b1, b0], the offset is calculated as
70+
; O = [a0 + b0 * (a1 + b1 * (a2 + ... bN-2(aN-1)))]
71+
; What I will do here is to calculate the following sequence:
72+
; ((aN-1 * bN-2) + aN-2) * bN-3 + ...
73+
74+
75+
#line 1 "mul16.asm"
76+
77+
__MUL16: ; Mutiplies HL with the last value stored into de stack
78+
; Works for both signed and unsigned
79+
80+
PROC
81+
82+
LOCAL __MUL16LOOP
83+
LOCAL __MUL16NOADD
84+
85+
ex de, hl
86+
pop hl ; Return address
87+
ex (sp), hl ; CALLEE caller convention
88+
89+
;;__MUL16_FAST: ; __FASTCALL ENTRY: HL = 1st operand, DE = 2nd Operand
90+
;; ld c, h
91+
;; ld a, l ; C,A => 1st Operand
92+
;;
93+
;; ld hl, 0 ; Accumulator
94+
;; ld b, 16
95+
;;
96+
;;__MUL16LOOP:
97+
;; sra c ; C,A >> 1 (Arithmetic)
98+
;; rra
99+
;;
100+
;; jr nc, __MUL16NOADD
101+
;; add hl, de
102+
;;
103+
;;__MUL16NOADD:
104+
;; sla e
105+
;; rl d
106+
;;
107+
;; djnz __MUL16LOOP
108+
109+
__MUL16_FAST:
110+
ld b, 16
111+
ld a, d
112+
ld c, e
113+
ex de, hl
114+
ld hl, 0
115+
116+
__MUL16LOOP:
117+
add hl, hl ; hl << 1
118+
sla c
119+
rla ; a,c << 1
120+
jp nc, __MUL16NOADD
121+
add hl, de
122+
123+
__MUL16NOADD:
124+
djnz __MUL16LOOP
125+
126+
ret ; Result in hl (16 lower bits)
127+
128+
ENDP
129+
130+
#line 20 "array.asm"
131+
132+
133+
#line 1 "error.asm"
134+
135+
; Simple error control routines
136+
; vim:ts=4:et:
137+
138+
ERR_NR EQU 23610 ; Error code system variable
139+
140+
141+
; Error code definitions (as in ZX spectrum manual)
142+
143+
; Set error code with:
144+
; ld a, ERROR_CODE
145+
; ld (ERR_NR), a
146+
147+
148+
ERROR_Ok EQU -1
149+
ERROR_SubscriptWrong EQU 2
150+
ERROR_OutOfMemory EQU 3
151+
ERROR_OutOfScreen EQU 4
152+
ERROR_NumberTooBig EQU 5
153+
ERROR_InvalidArg EQU 9
154+
ERROR_IntOutOfRange EQU 10
155+
ERROR_NonsenseInBasic EQU 11
156+
ERROR_InvalidFileName EQU 14
157+
ERROR_InvalidColour EQU 19
158+
ERROR_BreakIntoProgram EQU 20
159+
ERROR_TapeLoadingErr EQU 26
160+
161+
162+
; Raises error using RST #8
163+
__ERROR:
164+
ld (__ERROR_CODE), a
165+
rst 8
166+
__ERROR_CODE:
167+
nop
168+
ret
169+
170+
; Sets the error system variable, but keeps running.
171+
; Usually this instruction if followed by the END intermediate instruction.
172+
__STOP:
173+
ld (ERR_NR), a
174+
ret
175+
#line 23 "array.asm"
176+
#line 24 "/Users/boriel/Documents/src/zxbasic/zxbasic/library-asm/array.asm"
177+
178+
__ARRAY:
179+
PROC
180+
181+
LOCAL LOOP
182+
LOCAL ARRAY_END
183+
LOCAL RET_ADDRESS ; Stores return address
184+
185+
ex (sp), hl ; Return address in HL, array address in the stack
186+
ld (RET_ADDRESS + 1), hl ; Stores it for later
187+
188+
exx
189+
pop hl ; Will use H'L' as the pointer
190+
ld c, (hl) ; Loads Number of dimensions from (hl)
191+
inc hl
192+
ld b, (hl)
193+
inc hl ; Ready
194+
exx
195+
196+
ld hl, 0 ; BC = Offset "accumulator"
197+
198+
LOOP:
199+
200+
pop de
201+
#line 49 "/Users/boriel/Documents/src/zxbasic/zxbasic/library-asm/array.asm"
202+
pop bc ; Get next index (Ai) from the stack
203+
204+
205+
ex de, hl
206+
or a
207+
sbc hl, bc
208+
ld a, ERROR_SubscriptWrong
209+
jp c, __ERROR
210+
ex de, hl
211+
#line 59 "/Users/boriel/Documents/src/zxbasic/zxbasic/library-asm/array.asm"
212+
213+
add hl, bc ; Adds current index
214+
215+
exx ; Checks if B'C' = 0
216+
ld a, b ; Which means we must exit (last element is not multiplied by anything)
217+
or c
218+
jr z, ARRAY_END ; if B'Ci == 0 we are done
219+
220+
ld e, (hl) ; Loads next dimension into D'E'
221+
inc hl
222+
ld d, (hl)
223+
inc hl
224+
push de
225+
dec bc ; Decrements loop counter
226+
exx
227+
pop de ; DE = Max bound Number (i-th dimension)
228+
229+
;call __MUL16_FAST ; HL *= DE
230+
call __FNMUL
231+
jp LOOP
232+
233+
ARRAY_END:
234+
ld e, (hl)
235+
inc hl
236+
ld d, c ; C = 0 => DE = E = Element size
237+
push hl
238+
push de
239+
exx
240+
241+
#line 92 "/Users/boriel/Documents/src/zxbasic/zxbasic/library-asm/array.asm"
242+
LOCAL ARRAY_SIZE_LOOP
243+
244+
ex de, hl
245+
ld hl, 0
246+
pop bc
247+
ld b, c
248+
ARRAY_SIZE_LOOP:
249+
add hl, de
250+
djnz ARRAY_SIZE_LOOP
251+
252+
;; Even faster
253+
;pop bc
254+
255+
;ld d, h
256+
;ld e, l
257+
258+
;dec c
259+
;jp z, __ARRAY_FIN
260+
261+
;add hl, hl
262+
;dec c
263+
;jp z, __ARRAY_FIN
264+
265+
;add hl, hl
266+
;dec c
267+
;dec c
268+
;jp z, __ARRAY_FIN
269+
270+
;add hl, de
271+
;__ARRAY_FIN:
272+
#line 123 "/Users/boriel/Documents/src/zxbasic/zxbasic/library-asm/array.asm"
273+
274+
pop de
275+
add hl, de ; Adds element start
276+
277+
RET_ADDRESS:
278+
ld de, 0
279+
push de
280+
ret ; HL = (Start of Elements + Offset)
281+
282+
;; Performs a faster multiply for little 16bit numbs
283+
LOCAL __FNMUL, __FNMUL2
284+
285+
__FNMUL:
286+
xor a
287+
or d
288+
jp nz, __MUL16_FAST
289+
290+
or e
291+
ex de, hl
292+
ret z
293+
294+
cp 33
295+
jp nc, __MUL16_FAST
296+
297+
ld b, l
298+
ld l, h ; HL = 0
299+
300+
__FNMUL2:
301+
add hl, de
302+
djnz __FNMUL2
303+
ret
304+
305+
ENDP
306+
307+
#line 44 "arrcheck.bas"
308+
309+
ZXBASIC_USER_DATA:
310+
_c:
311+
DEFB 00
312+
_b:
313+
DEFB 05h
314+
DEFB 00h
315+
_a:
316+
DEFW 0001h
317+
DEFW 0006h
318+
DEFB 01h
319+
DEFB 00h
320+
DEFB 00h
321+
DEFB 00h
322+
DEFB 00h
323+
DEFB 00h
324+
DEFB 00h
325+
DEFB 00h
326+
DEFB 00h
327+
DEFB 00h
328+
DEFB 00h
329+
DEFB 00h
330+
DEFB 00h
331+
DEFB 00h
332+
DEFB 00h
333+
DEFB 00h
334+
DEFB 00h
335+
DEFB 00h
336+
DEFB 00h
337+
DEFB 00h
338+
DEFB 00h
339+
DEFB 00h
340+
DEFB 00h
341+
DEFB 00h
342+
DEFB 00h
343+
DEFB 00h
344+
DEFB 00h
345+
DEFB 00h
346+
DEFB 00h
347+
DEFB 00h
348+
DEFB 00h
349+
DEFB 00h
350+
DEFB 00h
351+
DEFB 00h
352+
DEFB 00h
353+
DEFB 00h
354+
DEFB 00h
355+
DEFB 00h
356+
DEFB 00h
357+
DEFB 00h
358+
DEFB 00h
359+
DEFB 00h
360+
DEFB 00h
361+
DEFB 00h
362+
DEFB 00h
363+
DEFB 00h
364+
DEFB 00h
365+
DEFB 00h
366+
DEFB 00h
367+
DEFB 00h
368+
DEFB 00h
369+
DEFB 00h
370+
DEFB 00h
371+
DEFB 00h
372+
DEFB 00h
373+
DEFB 00h
374+
DEFB 00h
375+
DEFB 00h
376+
DEFB 00h
377+
DEFB 00h
378+
DEFB 00h
379+
DEFB 00h
380+
DEFB 00h
381+
DEFB 00h
382+
DEFB 00h
383+
DEFB 00h
384+
DEFB 00h
385+
; Defines DATA END --> HEAP size is 0
386+
ZXBASIC_USER_DATA_END EQU ZXBASIC_MEM_HEAP
387+
; Defines USER DATA Length in bytes
388+
ZXBASIC_USER_DATA_LEN EQU ZXBASIC_USER_DATA_END - ZXBASIC_USER_DATA
389+
END

0 commit comments

Comments
 (0)