Introduction to 8051 Assembly Language Programming
ROM: ROM is Read Only Memory. Essentially it is a piece of permanently written information stored as memory. Nowadays there is a version of this memory that can be ‘rewritten’ and it is called EEPROM (Electrically Erasable Programmable Read Only Memory).
The RAM of a microcontroller (8051) is 128bytes or more (depending upon the company of microcontroller). The RAM consists of registers that can be of one or two bytes (generally).

Registers:
In CPU registers are used to store information temporarily. That information can be in the form of bytes of data to be processed or some address pointing to a data to be fetched. In 8051 there is only one data type: 8 bits. With an 8 bit data registers, any data more than 8 bit should be divided into 8 bit chunks before being processed.

The most widely used registers of 8051 are A (accumulator), R0, R1, R2, R3, R4, R5, R6, R7, DPTR (data pointer), PC (program counter). A register is used for all the arithmetic and logic operations.
These registers are divided into two groups:
- General purpose registers
- Special purpose registers
I will introduce you to all the registers as and when required.

For better understanding of microcontroller I will use assembly language. You may not enjoy this language as it is quite lengthy and tedious to write programs, so in the end I will also discuss the C platform for writing programs easily and much faster.
8051 instruction sets:
STRUCTURE OF ASSEMBELY LANGUAGE:
Let’s see an example (Below is a statement taken from an assembly code)
- USER: It is label (this field is not necessary)
- MOV: mnemonic (easy to remember). Others mnemonic are SUBC, MUB, DIV, etc
- A is an operand, (this field is not necessary)
- ; load 25hex in accumulator register - This is a comment. Though this field is not necessary you should always use it to understand program better)
MOV instruction
It is used to load a register with some value like:
|
Assembly |
Code |
www.botskool.com |
|
MOV MOV MOV |
A,#51H R1,#0FFH R2,#3BH |
; load A= 51 hex ; load R1= FF hex ; load R2= 3B hex |
1. This instruction can be used to load any register with a hex value.
2. ‘#’ signifies that it is a number (and not a byte address).
3. ‘H’ symbolizes that it is hexadecimal number. Similarly if we write a binary number it should end with ‘B’ like 1111B & a decimal number can be written as it is or followed by D, 17 or 17D.
4. In the second line of the above code we used 0FFH. The ‘0’ symbolizes that ‘F’ is a hex number and not letter. This is always necessary if we are writing any hexadecimal number. It should always start with a 0 like ‘0ABH’ or ‘0CFH’
5. All the register should be assumed to be of 1 byte. Unless otherwise mentioned. So if we load A= FFFH > 255D (a byte can hold), it is illegal.
Now suppose I wish to transfer contents of R1 into R6. I can do so by writing the following code:
|
Assembly |
Code |
www.botskool.com |
|
MOV |
R6,R1 |
; copy contents of R1, R6 |
Here R6 is a destination operand whereas R1 is a source operand. We always write a destination operand first.
Now let’s apply the above knowledge to understand a code in assembly.
|
Assembly |
Code |
|
www.botskool.com |
|
HERE: |
ORG MOV MOV MOV MOV SJMP END |
0H R1,#31H R2, 20H R3,R2 R4,R3 HERE |
; start at location 0 (origin) ; load 31 hex in R1 ; load 20 hex in R2 ; copy contents of R2 into R3 ; copy contents of R3 into R4 ; copy contents of R3 into R4 |
1. ORG and END are the directives of assembly language. The origin directs the CPU to start at ROM location 0H (this is discussed in detail later on).
2. HERE: - this label tells 8051 to stay in the loop. If your system has a monitor program you do not need this line and it should be deleted from your code.
ADD instruction
|
Assembly |
Code |
www.botskool.com |
|
ADD |
A,source |
;add the value in A & source register |
- This instruion is used to add two numbers
- When you do an operation between two registers then the first one is called the destination and second is the source.
- The result of an operation is always stored in destination.
- The operation ADD should always have register A as its destination.
|
Assembly |
Code |
www.botskool.com |
|
ADD |
A, R1 |
; add contents of A and R1 ; A is the destination & R1 the source ;A=A+R1 |
For e.g. we can write -
An example –
|
Assembly |
Code |
|
www.botskool.com |
|
HERE: |
ORG MOV ADD MOV ADD MOV SJMP END |
0H A,#30H A,#2BH R1, #20H A,R1 R2,#2CH HERE |
; start at 0 (origin) ; A= 30 hex ; A= A+ 2B hex ; add 2B to Accumulator ; R1= 20 hex ; Add contents of R1 & A ; R2 = 2C hex ; stay in the loop |
All the addition and subtraction should have A as their destination; otherwise the statement will be illegal. For example
|
Assembly |
Code |
|
www.botskool.com |
|
|
ADD ADD |
R2,A R2,#12H |
; an illegal statement ; an illegal statement |
Now suppose I wish to add contents of two register to R1.
|
Assembly |
Code |
|
www.botskool.com |
|
HERE: |
ORG MOV MOV MOV ADD MOV ADD ADD MOV SJMP END |
0H A,#0H A,#2BH R1, #20H A,R2 R3,#2EH A,R2 A,R3 R1,A HERE |
; start at 0 (origin) ; A= 0 hex ; R1= 0 hex ; R2= 20 hex ; A= A + R2 ; R3 = 2E hex ; A = A + R2 ; A = A + R3 ; copy contents of A to R1 |
How are two decimal number added?

(You can see ‘1’ is carried from 4th bit to 5th bit)
As we know that register A is a single byte register, so what will happen if addition of two numbers exceed FF hex (255) and a carry is generated {the maximum value a byte can hold is 255 or FF hex}

1. Where will this 9th bit go?
The A register will hold all the bits except the first one. This highest significant bit will move to ‘Carry Flag’.
2. What is a carry flag?
All the microcontrollers have a register to indicate arithmetic conditions such as carry bit. The register for this operation in 8051 is called a PSW register or flag register.
PSW (program status word) register

PSW is an 8 bit register.
- CY (PSW.7): This is the carry flag. This flag is set (become high or CY=1) whenever there is a carry from D7 bit. You can set this flag equal to one like this SETB C, and clear it by this instruction - CLR C. You will see the application in coming sessions.
- AC (PSW.6): This is the auxiliary carry flag. This flag is set whenever there is carry from D3 to D4.
- P (PSW.0): This is parity flag. This flag is set whenever the number of 1’s in accumulator is odd otherwise it is zero.
- OV (PSW.2): Over flow flag, this will be explained later.
- RS1 (PSW.4) and RS0 (PSW.3) - These are used to switch register banks. (Explained in detail later).
- F0 (PSW.5) and -- (PSW.1) – They do not have any specific function and are user-definable bits.
Now suppose if I have these two instructions
|
Assembly |
Code |
|
www.botskool.com |
|
|
MOV ADD |
A, #55H A, #25H |
; load A with 55hex ; A= A+25hex |

SUBB instruction
|
Assembly |
Code |
|
www.botskool.com |
|
Subtraction: |
SUBB |
A,source |
; A= A- source-CY |
- This instruction is used for subtracting two numbers.
- Here also the destination is always register A.
- The result is stored in the register A.
Before we move to this instruction, let’s first discuss the subtraction of two decimal numbers.
1’s Complement
In a binary number take a complement, that is replace all 1’s by 0 & 0’s by 1
For e.g.: 1111 0000
1’s complement: 0000 1111
2’s Complement
Take 1’s complement and add 1H to it:
In the above example 2’s complement is:
How SUBB instruction works? There are three main steps involved:-
- Take 2’s complement of subtrahend (source operand)
- Add it to the A
- Invert the carry
- If CY= 0 after implementation (step three) then the result is positive.
- If the CY=0 the result is negative & the answer is 2’s complement of result
{The answer is 2’s complement of result only in this case}

|
Assembly |
Code |
|
www.botskool.com |
|
NEXT: |
CLR MOV SUBB JNC CPL INC MOV |
C A,# 24H A,# 6BH NEXT A A R1,A |
; clear the carry flag ; load A= 24 hex ; subtract 6B hex from A ; jump to next if CY=0 ; if CY=1 è take complement of result ; & Increment the final answer ; save the answer in R1 |
MUL instruction
|
Assembly |
Code |
|
www.botskool.com |
|
Multiply: |
MUL |
AB |
; Multiply the contents of A & B ; the result is stored in 16 bit ;the lower byte in A & higher in B |
- The numbers to be multiplied should be moved into registers A & B.
- The result is stored in 16 bit or 2 bytes in the same two registers A & B. The lowest significant bit is stored in the D0 (or the lowest bit of register A) and the highest in D7 of register B.
- We cannot multiply the value of two registers until we move their content to register A & B.
Example –
|
Assembly |
Code |
|
www.botskool.com |
|
|
MOV MOV MUL |
A,#B2H B,#D6H AB |
; load A= B6 hex ; load B= D8 hex ; B2* D6= 94 CC ; we get A= CC & B= 94 ; since 94 is higher byte & CC lower byte |
DIV instruction
|
Assembly |
Code |
|
www.botskool.com |
|
Divide: |
DIV |
AB |
; divides A by B ; A is the numerator ; & B is the denominator ; stores the quotient in A & reminder in B |
- This instruction divides the number stored in register A by the number stored in register B.
- A is the numerator and B is the denominator.
- The quotient is stored in register A.
- The reminder is stored in Register B.
Example –
|
Assembly |
Code |
|
www.botskool.com |
|
MOV MOV DIV |
A, # 82 B, # 5 AB |
; load A with 82 (decimal) ; load B with 5 ; divide A by B ; the result is A= 16 & B= 2 (in decimal) |
SIGNED/ UNSIGNED NUMBERS
Till now all the 8 bit was used to store the magnitude of number. We considered only positive numbers. But there are numerous occasions where we have to deal with negative & positive number both.
1. The highest bit carry the sign i.e. +/-. If the number is negative then highest bit set to1 or else in positive number it is zero.
2. All other bits carry the magnitude of the number.
If you don’t have any use of negative number then you surely can skip this topic.
How to convert a negative number in decimal to hex?
1. Write the number in binary form
2. Take 2’s complement of binary number
Let’s say we have a number -10
The binary form of 10: 0000 1010
2’s complement of binary number: 1111 0110
HEX number: F6
(The above discussion is in regard with an 8 bit data. But the 8051 only support 8bit so don’t worry. )
|
Assembly |
Code |
|
www.botskool.com |
|
MOV MOV ADD |
A, # +106 R1, # 108 A, R1 |
; learning signed & unsigned ; integers |

The bit encircled represent a sign, this should have be zero since we have added two positive numbers, so the result should be positive. {Since the highest bit represent the sign, which is 1 when the number is one}
This is called overflow. Therefore a flag called over flow flag or OV flag is set to one.
When is OV set to one?
1. When there is a carry from D6 to D7
2. When there is carry from D7 (to carry flag)
3. OV is zero when both or none of them happen.
Summary:
Let us recap what we have covered so far:
Types of memories
Types of registers: General and special
Assembly instruction set like MOV and arithmetic operations
The aim of this tutorial was to create a better understanding of registers and memories for a beginner and this series of tutorial will focus upon deep understanding of microcontrollers.




Comments
7 January 2011
1 year 18 weeks
sir, i wanna ask if in 8051 assembly can passing parameter like C# ???
21 October 2010
1 year 30 weeks
this tutorial is very helpful
22 May 2010
1 year 51 weeks
Thanks for the reply. Regarding instruction MOV R6,R1 or in that case between any two Rn registers, check the addressing modes of 8051. also check the instruction set of 8051, you will not find any isntruction where dis kind of instruction can be written. I have read( i think in Mazidi) that to overcome this proble , we have to use register addressing mode.
Please correctc me if I am wrong!
21 February 2009
2 years 9 weeks
Hi ritula.thakur,
The statement MOV R6, R1 is correct. If you have to transfer the content of R1 register into R6 you will use the above mentioned statement to do so.
Regarding the second mistake that you have mentioned, the # sign was missed and it should be very much there.
Thank you for bringing this to our attention. The tutorial has been updated!
Cheers
22 May 2010
1 year 51 weeks
First of all, i must say that it is a very well written tutorial. Please correct me if I am wrong. but I couldnt help myself when i found sum mistakes in the above tutorial.I have written them as follows:
1. Firstly you have given an example: mov R6,R1. however, this is wrong.In ace we want to transfer data between any two rn registers, we have to use direct addressing modes, specifying their address. for ex in this case, it should be : mov 6,1
2. In another statement while giving example of ADD instruction, you have written MOV A, 55H
MOV A,25H
then moved data in A. however, there should be a # befor 55 and 25 H if you wan2 show them in data format. otherwise these are memory location.
Kindly check!
15 February 2010
2 years 13 weeks
"using timer 1 as time base for 1s during which timer 0 is used as counter with ip pulse fed at pin 3.4....and to store the counted values at TL0 n TH0....
18 February 2009
3 days 16 hours
Hi mixanologos,
Have you gone through the above tutorial?
29 January 2010
2 years 15 weeks
HI THERE!!
I REALLY NEED YOUR HELP. I AM DUE WITH AN ASSIGMENT, WE JUST STARTED MICROPROCESSORS WITH 8051 BUT OUT LECTURER IS AWFUL, AND WE HAVE A PROJECT TO BUILD UP, AND I AM EVEN STRUGGLING WITH THE MOST EASY TASKS. DONT KNOW WHAT TO DO! HERE ARE THE TASKS I AM HAVING PROBLEBS WITH, IF SOMEBODY KNOWS HOW TO WRITE THEM - PLS HIT ME BCK ASAP. THANK YOU SOOO MUCH.
1. Add up the numbers which are in the four internal RAM locations 32h to 35h, leaving the result in Port P2.
2. Send a repeating square wave to Port 1 bit 7. One complete cycle should take 100μs instructions.
3. SetP1.0to1,ifbit0onport0(P0.0)is1orbit1onport0(P0.1)is0,otherwise clearing P1.0. Check the inputs and adjust the output in a loop. Test by changing port values in the simulator.
2 November 2009
9 weeks 2 days
now u can publish your comment directly from botskool to facebook.. yepee..
this is a really nice tutorial..
21 February 2009
2 years 9 weeks
You are welcome
Enjoy!