I'm trying to sort an array of registers into two new odd and even registers being stored at separate locations accordingly.
I'm giving inputs manually using the memory window tab in the Keil uVision's debugger.
- d:20H stores the length of the register array
- d:30H is the starting address of the register array that's taken as input
- x:2000H should be the starting address of the new odd array being created
- x:3000H should be the starting address of the new even array being created
I've been able to figure out if a value is even or odd using the LSB. However, I've been facing trouble trying to move a register into my desired location using indirect addressing (got to do so for storing at consecutive locations). It kind of works, but right now, only the last odd/even value is being stored at x:2001H and x:3001H respectively.
Here's my attempt:
/*
program to filter an array of registers into even and odd arrays of registers
d:20 -> length of array
d:30H -> initial input array
x:2000H -> ODD array (external memory)
x:3000H -> EVEN array (external memory)
*/
ORG 0000H
MOV R0, 20H ;where length of input reg array is stored
MOV R1, #30H ;R1 will be the pointer for looping through the input array starting at d:30H
MOV R2, #00H ;counter for incrementing DPTR for required even array index
MOV R3, #00H ;counter for incrementing DPTR for required odd array index
LOOP:
MOV A, @R1
RRC A ;dividing by 2 (right shift) and moving LSB to carry
/* alternatively:
ANL A, #01H ;indexed element is bitwise ANDed with #01H so that only the LSB remains
;if LSB is 1 -> odd
;if LSB is 0-> even
and then CJNE #00H */
MOV A, @R1 ;gotta do this cause you cant MOV @DPTR, @R1 directly
INC R1 ;current R1 is no longer required and moving to next index for next loop
JC ODD ;if carry is generated -> ODD -> go to ODD level
MOV DPTR, #2000H ;starting address of even array
JMP INCLOOP1
INCLOOP1:
INC DPTR
DJNZ R3, INCLOOP1 ;using this loop to increment dptr so that even values are stored in consecutive addresses
;after the first even value is stored at 2000H
MOVX @DPTR, A ;even value is moved to @DPTR(even array index)
INC R3 ;incrementing R3 after a value is stored so that the 'ith' time an even value is found
;dptr is increased 'i' times
ODD:
MOV DPTR, #3000H ;starting address of odd array
JMP INCLOOP2
INCLOOP2:
INC DPTR
DJNZ R2, INCLOOP2 ;using this loop to increment dptr so that odd values are stored in consecutive addresses
;after the first odd value is stored at 3000H
MOVX @DPTR, A ;even value is moved to @DPTR(odd array index)
INC R2
DJNZ R0, LOOP ;loop for going through all elements of the array
END
Ideally, DPTR should have been incremented to point to the next address every time a value is stored in the odd/even array.
Here's my inputs:

And here's the outputs I get after running my program:

Your code has several errors and quirks:
DPTRdecrementR2andR3, respectively, until zero.INCsets the value to 1, for each value to sort. This is the reason why you see only the last value in the sorted arrays.R2andR3, respectively, are zero as initialized. SinceDJNZchecks for zero after the decrement, these loops run 256 rounds, incrementingDPTRto 2100H and 3100H, respectively. You might want to check those XDATA locations to see if I'm right.DPTRis the other way around than your prose requires. I used the prose for my solution.This is my suggested solution, please compare it to yours.
R2/R3andR4/R5) as save storage of the output array addresses. Some 8051 derivatives have two data pointers, but the standard core has just one.INC DPTR, because this is shorter than other ways to increment the register pair. However, if you are perfectly sure that there will be no carry into the upper byte, you can replace that and the followingMOVes by a singleINC R2(INC R4).