Bladeren bron

shell: add call command

pull/10/head
Virgil Dupras 5 jaren geleden
bovenliggende
commit
83f63c7146
2 gewijzigde bestanden met toevoegingen van 142 en 20 verwijderingen
  1. +53
    -7
      parts/core.asm
  2. +89
    -13
      parts/shell.asm

+ 53
- 7
parts/core.asm Bestand weergeven

@@ -18,6 +18,12 @@ addDE:
ld e, a
ret

; jump to the location pointed to by IX. This allows us to call IX instead of
; just jumping it. We use IX because we never use this for arguments.
callIX:
jp (ix)
ret

; Increase HL until the memory address it points to is null for a maximum of
; 0xff bytes. Returns the new HL value as well as the number of bytes iterated
; in A.
@@ -71,12 +77,6 @@ fmtHexPair:
pop af
ret

; jump to the location pointed to by HL. This allows us to call HL instead of
; just jumping it.
jumpHL:
jp hl
ret

; Parse the hex char at A and extract it's 0-15 numerical value. Put the result
; in A.
;
@@ -141,6 +141,30 @@ parseHexPair:
pop bc
ret

; Parse a series of A hex pairs from (HL) and put the result in (DE)
parseHexChain:
push af
push bc
push de
push hl

ld b, a
.loop:
call parseHexPair
jr c, .end ; error?
ld (de), a
inc hl
inc hl
inc de
djnz .loop

.end:
pop hl
pop de
pop bc
pop af
ret

; print null-terminated string pointed to by HL
printstr:
push af
@@ -187,10 +211,17 @@ strncmp:
.loop:
ld a, (de)
cp (hl)
jr nz, .end ; not equal? break early
jr nz, .end ; not equal? break early. NZ is carried out
; to the called
cp 0 ; If our chars are null, stop the cmp
jr z, .end ; The positive result will be carried to the
; caller
inc hl
inc de
djnz .loop
; We went through all chars with success, but our current Z flag is
; unset because of the cp 0. Let's do a dummy CP to set the Z flag.
cp a

.end:
pop de
@@ -201,6 +232,21 @@ strncmp:
; early, set otherwise)
ret

; Swap the two bytes at (HL)
swapBytes:
push af
ld a, (hl)
ex af, af'
inc hl
ld a, (hl)
ex af, af'
ld (hl), a
dec hl
ex af, af'
ld (hl), a
pop af
ret

; Transforms the character in A, if it's in the a-z range, into its upcase
; version.
upcase:


+ 89
- 13
parts/shell.asm Bestand weergeven

@@ -21,7 +21,7 @@
; *** CONSTS ***

; number of entries in shellCmdTbl
SHELL_CMD_COUNT .equ 3
SHELL_CMD_COUNT .equ 4

; The command that was type isn't known to the shell
SHELL_ERR_UNKNOWN_CMD .equ 0x01
@@ -122,6 +122,7 @@ shellParse:
push bc
push de
push hl
push ix

ld de, shellCmdTbl
ld a, SHELL_CMD_COUNT
@@ -145,8 +146,10 @@ shellParse:
; point to the cmd jump line.
ld a, 4
call addDE
; Now, let's swap HL and DE because, welll because that's how we're set.
ex hl, de ; HL = jump line, DE = cmd str pointer
ld ixh, d
ld ixl, e
; Now, let's swap HL and DE because, well because that's how we're set.
ex hl, de ; DE = cmd str pointer

; Before we call our command, we want to set up the pointer to the arg
; list. Normally, it's DE+5 (DE+4 is the space) unless DE+4 is null,
@@ -158,10 +161,11 @@ shellParse:
jr z, .noarg ; char is null? we have no arg
inc de
.noarg:
; DE points to args, HL points to jump line. Ready to roll!
call jumpHL
; DE points to args, IX points to jump line. Ready to roll!
call callIX

.end:
pop ix
pop hl
pop de
pop bc
@@ -202,16 +206,14 @@ shellSeek:
push hl

ex de, hl
call parseHexPair
ld de, SHELL_MEM_PTR
ld a, 2
call parseHexChain
jr c, .error
; z80 is little endian. in a "ld hl, (nn)" op, L is loaded from the
; first byte, H is loaded from the second
ld (SHELL_MEM_PTR+1), a
inc hl
inc hl
call parseHexPair
jr c, .error
ld (SHELL_MEM_PTR), a
; first byte, H is loaded from the second. We have to swap our result.
ld hl, SHELL_MEM_PTR
call swapBytes
jr .success

.error:
@@ -322,6 +324,78 @@ shellLoad:
pop af
ret

; Calls the routine where the memory pointer currently points. This can take two
; parameters, A and HL. The first one is a byte, the second, a word. These are
; the values that A and HL are going to be set to just before calling.
; Example: run 42 cafe
shellCall:
push af
push de
push hl

ld a, (de)
cp 0
jr z, .defA ; no arg? don't try to parse
call parseHex
jr c, .error
; We have a proper A arg, in A. We push it for later use, just before
; the actual call.
push af

; Let's try DE parsing now
inc de
inc de
ld a, (de)
cp 0
jr z, .defDE ; no arg? don't try to parse
inc de ; we're on a space (maybe...) we parse the
; next char
ex hl, de ; we need HL to point to our hex str for
; parseHexChain
; We need a tmp 2 bytes space for our result. Let's use SHELL_HEX_FMT.
ld de, SHELL_HEX_FMT
ld a, 2
call parseHexChain
jr c, .error
ex hl, de ; result is in DE, we need it in HL
call swapBytes
; Alright, we have a proper address in (SHELL_HEX_FMT), let's push it
; to the stack
ld hl, (SHELL_HEX_FMT)
push hl
jr .success

.error:
ld a, SHELL_ERR_BAD_ARGS
call shellPrintErr
jr .end

.defA:
xor a
push af
.defDE:
ld hl, 0
push hl
.success:
; Let's recap here. At this point, we have:
; 1. The address we want to execute in (SHELL_MEM_PTR)
; 2. our HL arg on top of the stack
; 3. our A arg underneath.
; Ready, set, go!
ld a, (SHELL_MEM_PTR)
ld ixl, a
ld a, (SHELL_MEM_PTR+1)
ld ixh, a
pop hl
pop af
call callIX

.end:
pop hl
pop de
pop af
ret

; Format: 4 bytes name followed by 3 bytes jump. fill names with zeroes
shellCmdTbl:
.db "seek"
@@ -330,4 +404,6 @@ shellCmdTbl:
jp shellPeek
.db "load"
jp shellLoad
.db "call"
jp shellCall


Laden…
Annuleren
Opslaan