He arreglado el problema de las escrituras en variables, estos son los cambios:
array.asm
Código: Seleccionar todo
; Simple array Index routine
; Number of total indexes dimensions - 1 at beginning of memory
; HL = Start of array memory (First two bytes contains N-1 dimensions)
; Dimension values on the stack, (top of the stack, highest dimension)
; E.g. A(2, 4) -> PUSH <4>; PUSH <2>
; For any array of N dimension A(aN-1, ..., a1, a0)
; and dimensions D[bN-1, ..., b1, b0], the offset is calculated as
; O = [a0 + b0 * (a1 + b1 * (a2 + ... bN-2(aN-1)))]
; What I will do here is to calculate the following sequence:
; ((aN-1 * bN-2) + aN-2) * bN-3 + ...
#include once <mul16.asm>
#ifdef __CHECK_ARRAY_BOUNDARY__
#include once <error.asm>
#endif
__ARRAY:
PROC
LOCAL LOOP
LOCAL ARRAY_END
pop de ; Return address
ld (RET_ADDRESS+1), de ; Stores it for later
push hl ; Indexes pointer goes to H'L'
exx
pop hl ; Will use H'L' as the pointer
ld c, (hl) ; Loads Number of dimensions from (hl)
inc hl
ld b, (hl)
inc hl ; Ready
exx
ld hl, 0 ; BC = Offset "accumulator"
#ifdef __CHECK_ARRAY_BOUNDARY__
pop de
#endif
LOOP:
pop bc ; Get next index (Ai) from the stack
#ifdef __CHECK_ARRAY_BOUNDARY__
ex de, hl
or a
sbc hl, bc
ld a, ERROR_SubscriptWrong
jp c, __ERROR
ex de, hl
#endif
add hl, bc ; Adds current index
exx ; Checks if B'C' = 0
ld a, b ; Which means we must exit (last element is not multiplied by anything)
or c
jr z, ARRAY_END ; if B'Ci == 0 we are done
ld e, (hl) ; Loads next dimension into D'E'
inc hl
ld d, (hl)
inc hl
push de
dec bc ; Decrements loop counter
exx
pop de ; DE = Max bound Number (i-th dimension)
#ifdef __CHECK_ARRAY_BOUNDARY__
push de
#endif
;call __MUL16_FAST ; HL *= DE
call __FNMUL
#ifdef __CHECK_ARRAY_BOUNDARY__
pop de
dec de
#endif
jp LOOP
ARRAY_END:
ld e, (hl)
inc hl
ld d, c ; C = 0 => DE = E = Element size
push hl
push de
exx
#ifdef __BIG_ARRAY__
pop de
call __FNMUL
#else
LOCAL ARRAY_SIZE_LOOP
ex de, hl
ld hl, 0
pop bc
ld b, c
ARRAY_SIZE_LOOP:
add hl, de
djnz ARRAY_SIZE_LOOP
;; Even faster
;pop bc
;ld d, h
;ld e, l
;dec c
;jp z, __ARRAY_FIN
;add hl, hl
;dec c
;jp z, __ARRAY_FIN
;add hl, hl
;dec c
;dec c
;jp z, __ARRAY_FIN
;add hl, de
;__ARRAY_FIN:
#endif
pop de
add hl, de ; Adds element start
RET_ADDRESS:
ld de, 0
push de
ret ; HL = (Start of Elements + Offset)
;; Performs a faster multiply for little 16bit numbs
LOCAL __FNMUL, __FNMUL2
__FNMUL:
xor a
or d
jp nz, __MUL16_FAST
or e
ex de, hl
ret z
cp 33
jp nc, __MUL16_FAST
ld b, l
ld l, h ; HL = 0
__FNMUL2:
add hl, de
djnz __FNMUL2
ret
ENDP
alloc.asm
Código: Seleccionar todo
; vim: ts=4:et:sw=4:
; Copyleft (K) by Jose M. Rodriguez de la Rosa
; (a.k.a. Boriel)
; http://www.boriel.com
;
; This ASM library is licensed under the BSD license
; you can use it for any purpose (even for commercial
; closed source programs).
;
; Please read the BSD license on the internet
; ----- IMPLEMENTATION NOTES ------
; The heap is implemented as a linked list of free blocks.
; Each free block contains this info:
;
; +----------------+ <-- HEAP START
; | Size (2 bytes) |
; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK
; +----------------+
; | Next (2 bytes) |---+
; +----------------+ <-+
; | Size (2 bytes) |
; +----------------+
; | Next (2 bytes) |---+
; +----------------+ |
; | <free bytes...>| | <-- If Size > 4, then this contains (size - 4) bytes
; | (0 if Size = 4)| |
; +----------------+ <-+
; | Size (2 bytes) |
; +----------------+
; | Next (2 bytes) |---+
; +----------------+ |
; | <free bytes...>| |
; | (0 if Size = 4)| |
; +----------------+ |
; <Allocated> | <-- This zone is in use (Already allocated)
; +----------------+ <-+
; | Size (2 bytes) |
; +----------------+
; | Next (2 bytes) |---+
; +----------------+ |
; | <free bytes...>| |
; | (0 if Size = 4)| |
; +----------------+ <-+
; | Next (2 bytes) |--> NULL => END OF LIST
; | 0 = NULL |
; +----------------+
; | <free bytes...>|
; | (0 if Size = 4)|
; +----------------+
; When a block is FREED, the previous and next pointers are examined to see
; if we can defragment the heap. If the block to be freed is just next to the
; previous, or to the next (or both) they will be converted into a single
; block (so defragmented).
; MEMORY MANAGER
;
; This library must be initialized calling __MEM_INIT with
; HL = BLOCK Start & DE = Length.
; An init directive is useful for initialization routines.
; They will be added automatically if needed.
#include once <error.asm>
#include once <heapinit.asm>
; ---------------------------------------------------------------------
; MEM_ALLOC
; Allocates a block of memory in the heap.
;
; Parameters
; BC = Length of requested memory block
;
; Returns:
; HL = Pointer to the allocated block in memory. Returns 0 (NULL)
; if the block could not be allocated (out of memory)
; ---------------------------------------------------------------------
MEM_ALLOC:
__MEM_ALLOC: ; Returns the 1st free block found of the given length (in BC)
PROC
LOCAL __MEM_LOOP
LOCAL __MEM_DONE
LOCAL __MEM_SUBTRACT
LOCAL __MEM_START
ld hl, 0
ld (TEMP+1), hl
__MEM_START:
ld hl, ZXBASIC_MEM_HEAP ; This label point to the heap start
inc bc
inc bc ; BC = BC + 2 ; block size needs 2 extra bytes for hidden pointer
__MEM_LOOP: ; Loads lengh at (HL, HL+). If Lenght >= BC, jump to __MEM_DONE
ld a, h ; HL = NULL (No memory available?)
or l
#ifdef __MEMORY_CHECK__
ld a, ERROR_OutOfMemory
jp z, __ERROR
#else
ret z ; NULL
#endif
; HL = Pointer to Free block
ld e, (hl)
inc hl
ld d, (hl)
inc hl ; DE = Block Length
push hl ; HL = *pointer to -> next block
ex de, hl
or a ; CF = 0
sbc hl, bc ; FREE >= BC (Length) (HL = BlockLength - Length)
jp nc, __MEM_DONE
pop hl
ld (TEMP+1), hl
ex de, hl
ld e, (hl)
inc hl
ld d, (hl)
ex de, hl
jp __MEM_LOOP
__MEM_DONE: ; A free block has been found.
; Check if at least 4 bytes remains free (HL >= 4)
push hl
exx ; exx to preserve bc
pop hl
ld bc, 4
or a
sbc hl, bc
exx
jp nc, __MEM_SUBTRACT
; At this point...
; less than 4 bytes remains free. So we return this block entirely
; We must link the previous block with the next to this one
; (DE) => Pointer to next block
; (TEMP) => &(previous->next)
pop hl ; Discard current block pointer
push de
ex de, hl ; DE = Previous block pointer; (HL) = Next block pointer
ld a, (hl)
inc hl
ld h, (hl)
ld l, a ; HL = (HL)
ex de, hl ; HL = Previous block pointer; DE = Next block pointer
TEMP: ld hl, 0 ; Pre-previous block pointer
ld (hl), e
inc hl
ld (hl), d ; LINKED
pop hl ; Returning block.
ret
__MEM_SUBTRACT:
; At this point we have to store HL value (Length - BC) into (DE - 2)
ex de, hl
dec hl
ld (hl), d
dec hl
ld (hl), e ; Store new block length
add hl, de ; New length + DE => free-block start
pop de ; Remove previous HL off the stack
ld (hl), c ; Store length on its 1st word
inc hl
ld (hl), b
inc hl ; Return hl
ret
ENDP