Here's a strange bug that I fixed, but can't understand what is truly happening.
The following is a subroutine that takes a string entered by the user, looks for spaces, and separates the string into a command and arguments. It just scans the string (in COM1_RXBUF), and every time it sees a space, it converts it to a NULL, and creates an index to the next character in a array so that the argument can be located by the parser later. It does this until it finds a NULL, meaning the end of the string.
Long story short, it turns a long string of words into a buffer of null terminated command and arguments.
It works perfectly, except...
If I try to save any of my registers on the stack, and there are ANY arguments, the computer crashes when I RTS. If I enter a command with no arguments, it returns just fine. Using an LED as an indicator (poor man's debugger), all seems well until I RTS.
In the below code, I have the stack calls commented out. Un-commmenting any single push or pull pair (or all of them) causes the bug. The actual contents of those registers are not really needing to be saved when this sub routine is called, and I save them just out of habit and "just in case". Things work great with out saving them.
So I'm basically just trying to see what the heck is happening?
My reset routine sets the stack at $FF. I should have TONS of room still on the stack when this routine is called. I can't see that any of my memory writes go anywhere NEAR the stack. Actually, can you even do that (use $100 page like regular memory accidentally?). I can't see that I'm doing that anywhere. My first RAM allocations start at $200, and I really don't use much at all.
Here's the subtroutine:
Code:
;*****************************************************************************
;Process commandline subroutine. *
;puts indices to individual arguments into memory location labled ARG_INDEX *
;*****************************************************************************
process_cmdln:; PHA
; PHX
; PHY
STZ CMDLN_ERROR ;clear command line error byte
STZ ARG_CNT ;reset argument count
LDX #$00 ;clear X register
LDY #$00 ;clear Y register
find_spaces: LDA COM1_RXBUF,X ;get current character
CMP #$00 ;is it a NULL?
BEQ cmdln_exit ;if its a NULL, we are at the end of the string. Return from subroutine
CMP #$20 ;is it a space?
BEQ add_arg ;if its a space, branch to add argument
INX ;increment to next character
JMP find_spaces ;keep looking
add_arg: STZ COM1_RXBUF,X ;convert SPACE into NULL.
INX ;increment character index. Will be at first char of argument now
STX ARG_INDEX,Y ;store index into string buffer to current argument
INY ;increment argument count index.
CPY #$04 ;check if we are above max number of arguments
BCS cmdln_err ;if too many args, error and rts
STY ARG_CNT ;store number of arguments.
JMP find_spaces ;go back to searching string for aruments
cmdln_err: LDA #$FF
STA CMDLN_ERROR ;put $FF in error flag byte
STZ ARG_CNT ;reset argument count
cmdln_exit:
;PLY
;PHX
;PHA
RTS