Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

HELP Assembly 8051 language

caramelwilly

New Member
Hi all.
I have a work to do with 8051 microcontroller and I need help because I coded something and I don't know what is wrong. I just started to learn this language and this is very hard.
I put in green what I've done. I know my "MOVX" is wrong and I was thinking about a "MOVC". And I know that R6 should be used but I don't know how.
Thank for your help!

Task description:
; Search for the smallest element in a number sequence (array) stored in the internal memory.
; Every element is an 8 bit unsigned integer.
; Inputs: Start address of the array (pointer), number of elements
; Output: Smallest element value in a register
; -------------------------------------------------------------------


; Definitions
; -------------------------------------------------------------------

; Address symbols for creating pointers

ARRAY_LEN EQU 16
ARRAY_ADDR_IRAM EQU 0x40

; Test data for input parameters
; (Try also other values while testing your code.)

; Store numbers (bytes) in the code memory as an array

ORG 0x0070 ; Move if more code memory is required for the program code
ARRAY_ADDR_CODE:
DB 0x42, 0x1A, 0x7F, 0x80, 0x55, 0xAA, 0xA0, 0xCC, 0x12, 0x13, 0x11, 0x10, 0x05, 0xAA, 0x42, 0x34

; Interrupt jump table
ORG 0x0000;
SJMP MAIN ; Reset vector



; Beginning of the user program, move it freely if needed
ORG 0x0010

; -------------------------------------------------------------------
; MAIN program
; -------------------------------------------------------------------
; Purpose: Prepare the inputs and call the subroutines
; -------------------------------------------------------------------

MAIN:

; Prepare input parameters for the subroutine
MOV DPTR,#ARRAY_ADDR_CODE
MOV R6,#ARRAY_ADDR_IRAM
MOV R7,#ARRAY_LEN
CALL CODE2IRAM ; Copy the array from code memory to internal memory

MOV R6, #ARRAY_ADDR_IRAM
MOV R7, #ARRAY_LEN
; Infinite loop: Call the subroutine repeatedly
LOOP:

CALL FIND_MIN_NUMBER ; Call Find min number subroutine

SJMP LOOP




; ===================================================================
; SUBROUTINE(S)
; ===================================================================


; -------------------------------------------------------------------
; CODE2IRAM
; -------------------------------------------------------------------
; Purpose: Copy the number array from code memory to internal memory
; -------------------------------------------------------------------
; INPUT(S):
; DPTR - Base address of the number array in code memory
; R6 - Base address of the number array in the internal memory
; R7 - Number array size (in bytes)
; OUTPUT(S):
; -
; MODIFIES:
; [TODO]
; -------------------------------------------------------------------

CODE2IRAM:

MOV A,R6

MOVC A,@A+DPTR ;A->ext destn
INC R6 ;Source increment
INC DPTR ;destination increment
DJNZ R7

RET


; -------------------------------------------------------------------
; FIND_MIN_NUMBER
; -------------------------------------------------------------------
; Purpose: Find the minimum number (byte) in the array
; -------------------------------------------------------------------
; INPUT(S):
; R6 - Base address of the number array in the internal memory
; R7 - Array size (in bytes)
; OUTPUT(S):
; R4 - Minimum element value
; MODIFIES:
; [TODO]
; -------------------------------------------------------------------

FIND_MIN_NUMBER:

MOV DPTR, #2400 ;set DPTR as pointer array
MOVX A,@DPTR
MOV R0, A ; load the count value into a R0 register
DEC R0 ;it means that if we have 6 data, we have 5 comparisons to do (6-1) thats why we decrease by 1
INC DPTR ;we go to the first element of the array
MOVX A, @DPTR ;we load the first data into R7
MOV R4, A ;the first element is the smallest and we wave it into R4
AGAIN :
INC DPTR ;make DPTR to point next element of array
MOVX A, @DPTR ;get next element of array in A
MOV R2, A ;save in R2
CLR C ;clear carry flag
SUBB A, R4 ;Subtract current smallest from A
JNC AHEAD ;check for carry, if carry is set
MOV A, R2 ;save content of R2 as current smallest
MOV R4, A ;copy the smallest value into R4
AHEAD:
DJNZ R0, AGAIN ;Decrement count and go again if count is not zero
;otherwise go to next instruction
MOV DPTR, #2500h ;load the adress of result in DPTR
MOV A, R4 ; move the smallest data to A
MOVX @DPTR, A ;save in external memory
HALT:
SJMP HALT ;remain Idle in infinity loop

RET


; [TODO: You can also create other subroutines if needed.]



; End of the source file
END
 

throbscottle

Well-Known Member
I'll start by saying I know nothing about 8051 assembly but this caught my attention because I've thought about trying to learn it in the past, so this is a learning opportunity for both of us.

So, it looks like you are comparing each value in the array to a variable and producing an output based on the result of that.

So if that's the case, where are you adjusting the variable? It looks as though you are comparing your array values to an address counter. (But I am ignorant and may have read this completely wrong).

The way I would do it is, start a variable that increments from zero, and for each value of that variable, subtract each array element from it in turn. First zero result you get, the element which produced that is the one you want. Save writing some code by copying the variable value to the output rather than looking up the array element.
 

Dan Soze

Member
This is one possible solution for your homework:
Code:
; Search for the smallest element in a number sequence (array) stored in the internal memory.
; Every element is an 8 bit unsigned integer.
; Inputs: Start address of the array (pointer),number of elements
; Output: Smallest element value in a register
; -------------------------------------------------------------------


; Definitions
; -------------------------------------------------------------------

; Address symbols for creating pointers

ARRAY_LEN       EQU     16
ARRAY_ADDR_IRAM EQU     0x40

; Test data for input parameters
; (Try also other values while testing your code.)

; Store numbers (bytes) in the code memory as an array

    ORG     0x0070          ; Move if more code memory is required for the program code
ARRAY_ADDR_CODE:
    DB      0x42,0x1A,0x7F,0x80,0x55,0xAA,0xA0,0xCC,0x12,0x13,0x11,0x10,0x05,0xAA,0x42,0x34

; Interrupt jump table
    ORG     0x0000;
    SJMP    MAIN            ; Reset vector

; Beginning of the user program,move it freely if needed
    ORG     0x0010
; -------------------------------------------------------------------
; MAIN program
; -------------------------------------------------------------------
; Purpose: Prepare the inputs and call the subroutines
; -------------------------------------------------------------------

MAIN:

; Prepare input parameters for the subroutine
    MOV     DPTR,#ARRAY_ADDR_CODE
    MOV     R6,#ARRAY_ADDR_IRAM
    MOV     R7,#ARRAY_LEN
    CALL    CODE2IRAM       ; Copy the array from code memory to internal memory

; Infinite loop: Call the subroutine repeatedly
LOOP:
    MOV     R6,#ARRAY_ADDR_IRAM
    MOV     R7,#ARRAY_LEN
    CALL    FIND_MIN_NUMBER ; Call Find min number subroutine
    SJMP    LOOP

; ===================================================================
; SUBROUTINE(S)
; ===================================================================


; -------------------------------------------------------------------
; CODE2IRAM
; -------------------------------------------------------------------
; Purpose: Copy the number array from code memory to internal memory
; -------------------------------------------------------------------
; INPUT(S):
;   DPTR  - Base address of the number array in code memory
;   R6    - Base address of the number array in the internal memory
;   R7    - Number array size (in bytes)
; OUTPUT(S):
;         -
; MODIFIES:
;   [TODO]
; -------------------------------------------------------------------

CODE2IRAM:
    MOV     R0,R6
COPYLOOP:
    CLR     A
    MOVC    A,@A+DPTR   ; A = byte read from code
    MOV     @R0,A       ; Write RAM from A
    INC     DPTR        ; Source increment
    INC     R0          ; Destination increment
    DJNZ    R7,COPYLOOP ; decrement count and loop until zero
    RET

; -------------------------------------------------------------------
; FIND_MIN_NUMBER
; -------------------------------------------------------------------
; Purpose: Find the minimum number (byte) in the array
; -------------------------------------------------------------------
; INPUT(S):
;   R6 - Base address of the number array in the internal memory
;   R7 - Array size (in bytes)
; OUTPUT(S):
;   R4 - Minimum element value
; MODIFIES:
;   [TODO]
; -------------------------------------------------------------------

FIND_MIN_NUMBER:

    MOV     R4,#255             ; Start with maximum value
    MOV     R0,R6               ; R0 points to array in RAM
FIND_MIN_LOOP:
    MOV     A,@R0
    CJNE    A,R4,NX             ; Check Array element against current minimum
NX: JNC     FIND_MIN_GTE
    MOV     R4,A                ; Remember new minimum
FIND_MIN_GTE:
    INC     R0                  ; Point to next element
    DJNZ    R7,FIND_MIN_LOOP    ; Loop until we have checked all elements
    RET
   
HALT:
    SJMP    HALT                ; remain Idle in infinity loop

; [TODO: You can also create other subroutines if needed.]


; End of the source file
    END
Note: I have not actually tried to build this so it may have bugs.
 

caramelwilly

New Member
Hey I'm coming back because I have few mistakes again.
When I'm running my code on EdSim51DI, it's saying "Invalid Operand - R6 cannot be used here" for the line "MOV R0, R6" and Idk why? (in code2iram)
Can you please help me again?
 

Ian Rogers

User Extraordinaire
Forum Supporter
Most Helpful Member
With that code?? There is no instruction to "MOV R0,R6" You will need an accumulator
Change both to

MOV B,R6
MOV R0,B

(There is two of them )

Also... CJNE cannot use an R register as a compare You can substitute R4 with an IRAM variable.. But you'll need to load it ( I tried with TEMP )

MOV R4, #0FFh
MOV TEMP, R4

Then..

CJNE A,TEMP,NX .. But this need checking as it goes there (NX) in both scenario's.. I think it needs to jump elsewhere.. I think it should jump out..
 

caramelwilly

New Member
I tried to code what you just said.
It seems to work but the simulation doest not reckognize "TEMP" (Unknow Label - TEMP) should I declare it before ?
 

atferrari

Well-Known Member
Most Helpful Member
Instead of starting by code, why not struggling to get a flow diagram that you are sure (of course, subject to later verification) is suitable for the problem to solve?

When that stage is done, writing code becomes a simple clerical work.

I do it all the time.
 

caramelwilly

New Member
Hi again.
First, I've done a flow diagram but it's not helping me to code because this is the first time I'm coding in this language but it's true that it helps a little bit!
Then, I have this code now :

Code:

; Search for the smallest element in a number sequence (array) stored in the internal memory.
; Every element is an 8 bit unsigned integer.
; Inputs: Start address of the array (pointer),number of elements
; Output: Smallest element value in a register
; -------------------------------------------------------------------


; Definitions
; -------------------------------------------------------------------

; Address symbols for creating pointers

ARRAY_LEN EQU 16
ARRAY_ADDR_IRAM EQU 0x40

; Test data for input parameters
; (Try also other values while testing your code.)

; Store numbers (bytes) in the code memory as an array

ORG 0x0070 ; Move if more code memory is required for the program code
ARRAY_ADDR_CODE:
DB 0x42,0x1A,0x7F,0x80,0x55,0xAA,0xA0,0xCC,0x12,0x13,0x11,0x10,0x05,0xAA,0x42,0x34

; Interrupt jump table
ORG 0x0000;
SJMP MAIN ; Reset vector

; Beginning of the user program,move it freely if needed
ORG 0x0010
; -------------------------------------------------------------------
; MAIN program
; -------------------------------------------------------------------
; Purpose: Prepare the inputs and call the subroutines
; -------------------------------------------------------------------

MAIN:

; Prepare input parameters for the subroutine
MOV DPTR,#ARRAY_ADDR_CODE
MOV R6,#ARRAY_ADDR_IRAM
MOV R7,#ARRAY_LEN
CALL CODE2IRAM ; Copy the array from code memory to internal memory

; Infinite loop: Call the subroutine repeatedly
LOOP:
MOV R6,#ARRAY_ADDR_IRAM
MOV R7,#ARRAY_LEN
CALL FIND_MIN_NUMBER ; Call Find min number subroutine
SJMP LOOP

; ===================================================================
; SUBROUTINE(S)
; ===================================================================


; -------------------------------------------------------------------
; CODE2IRAM
; -------------------------------------------------------------------
; Purpose: Copy the number array from code memory to internal memory
; -------------------------------------------------------------------
; INPUT(S):
; DPTR - Base address of the number array in code memory
; R6 - Base address of the number array in the internal memory
; R7 - Number array size (in bytes)
; OUTPUT(S):
; -
; MODIFIES:
; [TODO]
; -------------------------------------------------------------------

CODE2IRAM:
MOV B,R6
MOV R0,B
COPYLOOP:
CLR A
MOVC A,@A+DPTR ; A = byte read from code
MOV @R0,A ; Write RAM from A
INC DPTR ; Source increment
INC R0 ; Destination increment
DJNZ R7,COPYLOOP ; decrement count and loop until zero
RET

; -------------------------------------------------------------------
; FIND_MIN_NUMBER
; -------------------------------------------------------------------
; Purpose: Find the minimum number (byte) in the array
; -------------------------------------------------------------------
; INPUT(S):
; R6 - Base address of the number array in the internal memory
; R7 - Array size (in bytes)
; OUTPUT(S):
; R4 - Minimum element value
; MODIFIES:
; [TODO]
; -------------------------------------------------------------------

FIND_MIN_NUMBER:

MOV R4,#255 ; Start with maximum value
MOV B,R6
MOV R0,B ; R0 points to array in RAM
FIND_MIN_LOOP:
TEMP EQU 0xE
MOV A,@R0
MOV R4, #0FFh
MOV TEMP, R4
CJNE A,TEMP,NX ; Check Array element against current minimum
NX: JNC FIND_MIN_GTE
MOV R4,A ; Remember new minimum
FIND_MIN_GTE:
INC R0 ; Point to next element
DJNZ R7,FIND_MIN_LOOP ; Loop until we have checked all elements
RET

HALT:
SJMP HALT ; remain Idle in infinity loop

; [TODO: You can also create other subroutines if needed.]


; End of the source file
END

But It always returns the last element of the array, not the smallest, and I think that the "MODIFIES" sections of the subroutine headers has to be filled but I don't now how to fill it for the user know that I'm using registers and memory variable in IRAM.
If you could again help me with that,thank you again!!
 

rjenkinsgb

Well-Known Member
Most Helpful Member
FIND_MIN_LOOP:
TEMP EQU 0xE
MOV A,@R0
MOV R4, #0FFh
MOV TEMP, R4
CJNE A,TEMP,NX ; Check Array element against current minimum
NX: JNC FIND_MIN_GTE

Look at the middle line - you are overwriting the saved "minimum" value in R4 every pass through the loop.
 

Ian Rogers

User Extraordinaire
Forum Supporter
Most Helpful Member
Here is the subroutine I used

Code:
FIND_MIN_NUMBER:

    MOV     R4,#0FFh             ; Start with maximum value
    MOV        TEMP,R4
    MOV     B,R6               ; R0 points to array in RAM
    MOV     R0,B
FIND_MIN_LOOP:
    MOV     A,@R0
    CJNE    A,TEMP,NX             ; Check Array element against current minimum <<< HERE>>>
NX:   JNC     FIND_MIN_GTE
    MOV     TEMP,A                ; Remember new minimum    I think this is right!!!
FIND_MIN_GTE:
    INC     R0                  ; Point to next element
    DJNZ    R7,FIND_MIN_LOOP    ; Loop until we have checked all elements
    RET
 
HALT:
    SJMP    HALT                ; remain Idle in infinity loop

Notice the R0 R6 swap... and R4 init is OUTSIDE the loop..

BUT... That jump is not correct.... CJNE ... NX.. well it will do that regardless of condition...

I have moved the NX to where I think it goes...
 
Last edited:

atferrari

Well-Known Member
Most Helpful Member
Hi again.
First, I've done a flow diagram but it's not helping me to code because this is the first time I'm coding in this language but it's true that it helps a little bit!
Then, I have this code now :

Code:

; Search for the smallest element in a number sequence (array) stored in the internal memory.
; Every element is an 8 bit unsigned integer.
; Inputs: Start address of the array (pointer),number of elements
; Output: Smallest element value in a register
; -------------------------------------------------------------------


; Definitions
; -------------------------------------------------------------------

; Address symbols for creating pointers

ARRAY_LEN EQU 16
ARRAY_ADDR_IRAM EQU 0x40

; Test data for input parameters
; (Try also other values while testing your code.)

; Store numbers (bytes) in the code memory as an array

ORG 0x0070 ; Move if more code memory is required for the program code
ARRAY_ADDR_CODE:
DB 0x42,0x1A,0x7F,0x80,0x55,0xAA,0xA0,0xCC,0x12,0x13,0x11,0x10,0x05,0xAA,0x42,0x34

; Interrupt jump table
ORG 0x0000;
SJMP MAIN ; Reset vector

; Beginning of the user program,move it freely if needed
ORG 0x0010
; -------------------------------------------------------------------
; MAIN program
; -------------------------------------------------------------------
; Purpose: Prepare the inputs and call the subroutines
; -------------------------------------------------------------------

MAIN:

; Prepare input parameters for the subroutine
MOV DPTR,#ARRAY_ADDR_CODE
MOV R6,#ARRAY_ADDR_IRAM
MOV R7,#ARRAY_LEN
CALL CODE2IRAM ; Copy the array from code memory to internal memory

; Infinite loop: Call the subroutine repeatedly
LOOP:
MOV R6,#ARRAY_ADDR_IRAM
MOV R7,#ARRAY_LEN
CALL FIND_MIN_NUMBER ; Call Find min number subroutine
SJMP LOOP

; ===================================================================
; SUBROUTINE(S)
; ===================================================================


; -------------------------------------------------------------------
; CODE2IRAM
; -------------------------------------------------------------------
; Purpose: Copy the number array from code memory to internal memory
; -------------------------------------------------------------------
; INPUT(S):
; DPTR - Base address of the number array in code memory
; R6 - Base address of the number array in the internal memory
; R7 - Number array size (in bytes)
; OUTPUT(S):
; -
; MODIFIES:
; [TODO]
; -------------------------------------------------------------------

CODE2IRAM:
MOV B,R6
MOV R0,B
COPYLOOP:
CLR A
MOVC A,@A+DPTR ; A = byte read from code
MOV @R0,A ; Write RAM from A
INC DPTR ; Source increment
INC R0 ; Destination increment
DJNZ R7,COPYLOOP ; decrement count and loop until zero
RET

; -------------------------------------------------------------------
; FIND_MIN_NUMBER
; -------------------------------------------------------------------
; Purpose: Find the minimum number (byte) in the array
; -------------------------------------------------------------------
; INPUT(S):
; R6 - Base address of the number array in the internal memory
; R7 - Array size (in bytes)
; OUTPUT(S):
; R4 - Minimum element value
; MODIFIES:
; [TODO]
; -------------------------------------------------------------------

FIND_MIN_NUMBER:

MOV R4,#255 ; Start with maximum value
MOV B,R6
MOV R0,B ; R0 points to array in RAM
FIND_MIN_LOOP:
TEMP EQU 0xE
MOV A,@R0
MOV R4, #0FFh
MOV TEMP, R4
CJNE A,TEMP,NX ; Check Array element against current minimum
NX: JNC FIND_MIN_GTE
MOV R4,A ; Remember new minimum
FIND_MIN_GTE:
INC R0 ; Point to next element
DJNZ R7,FIND_MIN_LOOP ; Loop until we have checked all elements
RET

HALT:
SJMP HALT ; remain Idle in infinity loop

; [TODO: You can also create other subroutines if needed.]


; End of the source file
END

But It always returns the last element of the array, not the smallest, and I think that the "MODIFIES" sections of the subroutine headers has to be filled but I don't now how to fill it for the user know that I'm using registers and memory variable in IRAM.
If you could again help me with that,thank you again!!
Could you show that diagram which, prior to start writing code, should work to implement the algorithm that solves the problem you face at the moment?
 

Latest threads

Top