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.
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:
DPTR
decrement R2
and R3
, respectively, until zero.INC
sets the value to 1, for each value to sort. This is the reason why you see only the last value in the sorted arrays.R2
and R3
, respectively, are zero as initialized. Since DJNZ
checks for zero after the decrement, these loops run 256 rounds, incrementing DPTR
to 2100H and 3100H, respectively. You might want to check those XDATA locations to see if I'm right.DPTR
is 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
/R3
and R4
/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 following MOV
es by a single INC R2
(INC R4
). 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, #LOW 3000H
MOV R3, #HIGH 3000H ;address for output even array
MOV R4, #LOW 2000H
MOV R5, #HIGH 2000H ;address for output odd array
LOOP:
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
JB ACC.0,ODD ;if LSBit is set -> ODD -> go to ODD level
MOV DPL, R2
MOV DPH, R3 ;current address in even array
MOVX @DPTR, A ;even value is copied to even array
INC DPTR
MOV R2, DPL
MOV R3, DPH ;increment and save address
JMP LOOPEND
ODD:
MOV DPL, R4
MOV DPH, R5 ;current address in odd array
MOVX @DPTR, A ;odd value is copied to odd array
INC DPTR
MOV R4, DPL
MOV R5, DPH ;increment and save address
LOOPEND:
DJNZ R0, LOOP ;loop for going through all elements of the array
END