assembly8051

Is there a better method to store values in consecutive registers using indirect addressing?


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:

d:20H d:30H

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

x:2000H x:3000H


Solution

  • Your code has several errors and quirks:

    This is my suggested solution, please compare it to yours.

        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