ed: add 'd' cmd
This commit is contained in:
parent
50d0dc982c
commit
8af1cf468c
@ -46,6 +46,17 @@ bufAddLine:
|
|||||||
pop de
|
pop de
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
; transform line index HL into its corresponding memory address in BUF_LINES
|
||||||
|
; array.
|
||||||
|
bufLineAddr:
|
||||||
|
push de
|
||||||
|
ex de, hl
|
||||||
|
ld hl, BUF_LINES
|
||||||
|
add hl, de
|
||||||
|
add hl, de ; twice, because two bytes per line
|
||||||
|
pop de
|
||||||
|
ret
|
||||||
|
|
||||||
; Read line number specified in HL and loads the I/O buffer with it.
|
; Read line number specified in HL and loads the I/O buffer with it.
|
||||||
; Like ioGetLine, sets HL to line buffer pointer.
|
; Like ioGetLine, sets HL to line buffer pointer.
|
||||||
; Sets Z on success, unset if out of bounds.
|
; Sets Z on success, unset if out of bounds.
|
||||||
@ -54,10 +65,7 @@ bufGetLine:
|
|||||||
ld de, (BUF_LINECNT)
|
ld de, (BUF_LINECNT)
|
||||||
call cpHLDE
|
call cpHLDE
|
||||||
jr nc, .outOfBounds ; HL > (BUF_LINECNT)
|
jr nc, .outOfBounds ; HL > (BUF_LINECNT)
|
||||||
ex de, hl
|
call bufLineAddr
|
||||||
ld hl, BUF_LINES
|
|
||||||
add hl, de
|
|
||||||
add hl, de ; twice, because two bytes per line
|
|
||||||
; HL now points to seek offset in memory
|
; HL now points to seek offset in memory
|
||||||
ld e, (hl)
|
ld e, (hl)
|
||||||
inc hl
|
inc hl
|
||||||
@ -71,3 +79,43 @@ bufGetLine:
|
|||||||
.outOfBounds:
|
.outOfBounds:
|
||||||
pop de
|
pop de
|
||||||
jp unsetZ
|
jp unsetZ
|
||||||
|
|
||||||
|
; Given line indexes in HL and DE where HL < DE < CNT, move all lines between
|
||||||
|
; DE and CNT by an offset of DE-HL. Also, adjust BUF_LINECNT by DE-HL.
|
||||||
|
; WARNING: no bounds check. The only consumer of this routine already does
|
||||||
|
; bounds check.
|
||||||
|
bufDelLines:
|
||||||
|
ex de, hl
|
||||||
|
push hl ; --> lvl 1
|
||||||
|
scf \ ccf
|
||||||
|
sbc hl, de ; HL now has delcount -1
|
||||||
|
inc hl ; adjust for actual delcount
|
||||||
|
; We have the number of lines to delete in HL. We're going to move this
|
||||||
|
; to BC for a LDIR, but before we do, there's two things we need to do:
|
||||||
|
; adjust buffer line count and multiply by 2 (we move words, not bytes).
|
||||||
|
push de ; --> lvl 2
|
||||||
|
ex de, hl ; del cnt now in DE
|
||||||
|
ld hl, (BUF_LINECNT)
|
||||||
|
scf \ ccf
|
||||||
|
sbc hl, de ; HL now has adjusted line cnt
|
||||||
|
ld (BUF_LINECNT), hl
|
||||||
|
; Good! one less thing to think about. Now, let's prepare moving DE
|
||||||
|
; (delcnt) to BC. But first, we'll multiply by 2.
|
||||||
|
sla e \ rl d
|
||||||
|
push hl \ pop bc ; BC: delcount * 2
|
||||||
|
pop de ; <-- lvl 2
|
||||||
|
pop hl ; <-- lvl 1
|
||||||
|
; At this point we have higher index in HL, lower index in DE and number
|
||||||
|
; of bytes to delete in BC. It's convenient because it's rather close
|
||||||
|
; to LDIR's signature! The only thing we need to do now is to translate
|
||||||
|
; those HL and DE indexes in memory addresses, that is, multiply by 2
|
||||||
|
; and add BUF_LINES
|
||||||
|
push hl ; --> lvl 1
|
||||||
|
ex de, hl
|
||||||
|
call bufLineAddr
|
||||||
|
ex de, hl
|
||||||
|
pop hl ; <-- lvl 1
|
||||||
|
call bufLineAddr
|
||||||
|
; Both HL and DE are translated. Go!
|
||||||
|
ldir
|
||||||
|
ret
|
||||||
|
@ -53,6 +53,8 @@ cmdParse:
|
|||||||
jr z, .nullCmd
|
jr z, .nullCmd
|
||||||
cp 'p'
|
cp 'p'
|
||||||
jr z, .okCmd
|
jr z, .okCmd
|
||||||
|
cp 'd'
|
||||||
|
jr z, .okCmd
|
||||||
; unsupported cmd
|
; unsupported cmd
|
||||||
ret ; Z unset
|
ret ; Z unset
|
||||||
.nullCmd:
|
.nullCmd:
|
||||||
|
@ -91,11 +91,21 @@ edMain:
|
|||||||
ld a, (CMD_TYPE)
|
ld a, (CMD_TYPE)
|
||||||
cp 'q'
|
cp 'q'
|
||||||
jr z, .doQuit
|
jr z, .doQuit
|
||||||
|
cp 'd'
|
||||||
|
jr z, .doDel
|
||||||
jr .doPrint
|
jr .doPrint
|
||||||
|
|
||||||
.doQuit:
|
.doQuit:
|
||||||
xor a
|
xor a
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
.doDel:
|
||||||
|
call edReadAddrs
|
||||||
|
jr nz, .error
|
||||||
|
; bufDelLines expects an exclusive upper bound, which is why we inc DE.
|
||||||
|
inc de
|
||||||
|
call bufDelLines
|
||||||
|
jr .mainLoop
|
||||||
.doPrint:
|
.doPrint:
|
||||||
call edReadAddrs
|
call edReadAddrs
|
||||||
jr nz, .error
|
jr nz, .error
|
||||||
|
@ -35,4 +35,40 @@ Thus, code that glue parts together could look like:
|
|||||||
MOD2_RAMSTART .equ MOD1_RAMEND
|
MOD2_RAMSTART .equ MOD1_RAMEND
|
||||||
#include "mod2.asm"
|
#include "mod2.asm"
|
||||||
|
|
||||||
|
## Stack management
|
||||||
|
|
||||||
|
Keeping the stack "balanced" is a big challenge when writing assembler code.
|
||||||
|
Those push and pop need to correspond, otherwise we end up with completely
|
||||||
|
broken code.
|
||||||
|
|
||||||
|
The usual "push/pop" at the beginning and end of a routine is rather easy to
|
||||||
|
manage, nothing special about them.
|
||||||
|
|
||||||
|
The problem is for the "inner" push and pop, which are often necessary in
|
||||||
|
routines handling more data at once. In those cases, we walk on eggshells.
|
||||||
|
|
||||||
|
A naive approach could be to indent the code between those push/pop, but indent
|
||||||
|
level would quickly become too big to fit in 80 chars.
|
||||||
|
|
||||||
|
I've tried ASCII art in some places, where comments next to push/pop have "|"
|
||||||
|
indicating the scope of the push/pop. It's nice, but it makes code complicated
|
||||||
|
to edit, especially when dense comments are involved. The pipes have to go
|
||||||
|
through them.
|
||||||
|
|
||||||
|
Of course, one could add descriptions next to each push/pop describing what is
|
||||||
|
being pushed, and I do it in some places, but it doesn't help much in easily
|
||||||
|
tracking down stack levels.
|
||||||
|
|
||||||
|
So, what I've started doing is to accompany each "non-routine" (at the
|
||||||
|
beginning and end of a routine) push/pop with "--> lvl X" and "<-- lvl X"
|
||||||
|
comments. Example:
|
||||||
|
|
||||||
|
push af ; --> lvl 1
|
||||||
|
inc a
|
||||||
|
push af ; --> lvl 2
|
||||||
|
inc a
|
||||||
|
pop af ; <-- lvl 2
|
||||||
|
pop af ; <-- lvl 1
|
||||||
|
|
||||||
|
I think that this should do the trick, so I'll do this consistently from now on.
|
||||||
[zasm]: ../apps/zasm/README.md
|
[zasm]: ../apps/zasm/README.md
|
||||||
|
Loading…
Reference in New Issue
Block a user