I have just tried to write my first assembly program for 8051 and sadly it's all errors! It seems one can't copy value from one Rx register to some other Rx register. Is this correct? The book I use didn't mention this. I wonder why.
When I learned basic C++ I was able to enclose multi-line comment within /* comment */. Is there something like this in the assembly too?
Please help me with the queries above. Thank you.
Code:
;move some hex value, e.g. 89H to register A of CPU. Then from register A
;move it to all registers of RAM, i.e. R0 - R7.
ORG 0H ;start at memory location 0H
Mov A, #89H
Mov R0, A
Mov R1, R0
Mov R2, R1
Mov R3, R2
Mov R4, R3
Mov R5, R4
Mov R6, R5
Mov R7, R6
END ;program ends here
Errors
Code:
Compiling file: program1.asm
Initializing pre-processor ...
Syntax error at 9 in program1.asm: Invalid set of operands: mov R1,R0
Syntax error at 10 in program1.asm: Invalid set of operands: mov R2,R1
Syntax error at 11 in program1.asm: Invalid set of operands: mov R3,R2
Syntax error at 12 in program1.asm: Invalid set of operands: mov R4,R3
Syntax error at 13 in program1.asm: Invalid set of operands: mov R5,R4
Syntax error at 14 in program1.asm: Invalid set of operands: mov R6,R5
Syntax error at 15 in program1.asm: Invalid set of operands: mov R7,R6
Pre-processing FAILED !
Creating code listing file ... -> "program1.lst"
7 errors, 0 warnings
ORG 0H
MOV A, 80H
MOV R0, 81H
ORG 80H
DB 10
DB 12
END
Q1: There is some problem with the code because see the value "A" has taken on. The value for R0 is also wrong.
Q2: The value of PC goes up by 2 for every line. I have read that this instruction MOV A, 80H occupy two bytes instead of one and that's the reason PC goes up by '2' for every line of the code. But can't that instruction be saved on a single byte so that the PC goes up by only '1' byte?
This is a method of direct addressing and will load register R0 with the contents that reside in RAM location 0x22.
Code:
mov R0,#0x22
This loads register R0 with the immediate value of 0x22 (or literal constant 0x22).
Code:
mov R1,@R0
This is a method of indirect addressing and will load register R1 with the contents of the address value residing in R0. Since we loaded R0 with the value of 0x22, this will load register R1 with the contents of RAM location 0x22.
Code:
mov @R0,R1
This is a method of indirect addressing and will load the contents of register R1 into the RAM location address that resides in register R0. Since we loaded R0 with the value of 0x22, this will load the contents of register R1 into RAM location 0x22.
Can't it all, both instruction and data, fit one byte? Please let me know.
I'm sorry but I still don't find anything wrong with my code. First I defined RAM locations 80H and 81H with literals "10" and "12". Then I coped those literals residing in memory locations 80H and 81H into A and R0. I have even tried the code below where I have placed the 'DB section at top of ORG 0H. It still doesn't work. Besides this doesn't the code have to start at ORG 0H?
Code:
ORG 80H
DB 10
DB 12
ORG 0H
MOV A, 80H
MOV R0, 81H
END
Ian Rogers said:
MOV A, 80H ; This is moving 0xFF at location 0x80 into A
Well, you didn't tell us you were defining and initializing bytes and moving the contents, looked like you were trying to move an immediate into A and R0. And as a matter of fact, why not start with that? MOV A, #10H etc. This is a little simpler and could help isolate the problem.
Are you running a monitor program? If so, your executable code might need to be further down than ORG 0.
You can't put data and an instruction in one byte because the data takes up a byte, and you can't put a 'move direct' into one byte because the address for the direct needs its own byte.
MOV A, 80H ; Move contents of A to 0x80H
MOV R0, 81H ; Move contents of R0 to 0x80H
ORG 0x80 ; puts the values in CODE you will only be able to retrieve them with the code ptr.
Location 0x80 in the SFR's is P0 (port 0). The simulator has the value as 0xFF.
I see EXACTLY what is going wrong. You're storing the values in code memory, and code memory cannot be directly addressed by the code.
The only way to read data values that are stored in code memory (such as you have with the db statements) is via indirect addressing by using "MOVC" instruction to read them from code memory. This is how we do look up tables on the 8051 -
Code:
org 0x0080
Value movc A, @A+PC
ret
db 10
db 12
Then to call the table, you load the table line value into the accumulator, then call the subroutine -
Code:
mov A,0x01
acall Value
You can also use DPTR as the offset register for this as well -
Code:
org 0x0080
Value movc A, @DPTR+PC
ret
db 10
db 12
When it returns from the subroutine, the table line value will be stored in the accumulator.
In regards to your question regarding if instruction and data can fit in one byte. These are not PICs. They don't have a "long instruction word" like a PIC does. Instructions are 8 bit instructions and data is 8 bit data. 8051 uses what is called a "modified Harvard architecture". It's not a true Harvard processor like the PIC is.