Assembly (x86-64, AArch64, RISC-V) Module 18 – 8-bit assembly: the 8051 microcontroller and the 8085
8051 lab programs and viva practice
Write and run the standard 8051 lab programs, keep a record of aim, algorithm, program and result, and answer viva questions from what each run printed.
What you will learn
- Identify the family of an 8051 lab program and the instructions it rests on
- Write a lab record of aim, algorithm, program and result from a recorded run
- Program a bubble sort of 16 bytes in 8051 internal RAM and calculate its machine cycles
- Compare one sort on the 8051, 8085, 8086 and RISC-V by size and instruction count, and the 8051 and 8085 runs by time
- Answer viva questions on the 8051 with evidence from a run
Before you start
What you’ll learn · Before you start
What you will learn
- Identify the family of an 8051 lab program and the instructions it rests on
- Write a lab record of aim, algorithm, program and result from a recorded run
- Program a bubble sort of 16 bytes in 8051 internal RAM and calculate its machine cycles
- Compare one sort on the 8051, 8085, 8086 and RISC-V by size and instruction count, and the 8051 and 8085 runs by time
- Answer viva questions on the 8051 with evidence from a run
Before you start
On this page
An 8051 lab sheet can list a dozen short programs, and each one ends in a written record and a few viva questions about why its lines are there. Most 8051 lab programs belong to four families, data transfer, arithmetic, logical and branch, and every record has the same four parts: aim, algorithm, program and result.
The record below is for a ten-byte block move that ran in uCsim in 756 clock periods, and the viva answers after it quote that run. Viva practice works best that way: a dump settles what a remembered rule only argues.
Four families of programs cover most 8051 lab lists
The table sorts the 8051 lab programs of most lists by what they practise, and each family rests on a few instructions:
| Family | Typical programs | Instructions they rest on |
|---|---|---|
| Data transfer | copy, exchange or fill a block; read a code table | MOV, MOVX, MOVC, XCH, PUSH, POP |
| Arithmetic | sums, differences, products, quotients, BCD | ADD, ADDC, SUBB, MUL AB, DIV AB, DA A |
| Logical | masks, single bits, rotations, counting 1 bits | ANL, ORL, XRL, CPL, RL, RLC, SETB, CLR |
| Branch | largest or smallest byte, searches, sorts | DJNZ, CJNE, JZ, JNC, JNB, SJMP |
Port, timer and serial programs add the setup of an special function register: One of the 8051's own registers mapped into the internal data addresses 80H to FFH, such as the accumulator, B, PSW, SP, the port latches and the timer and serial controls. Only a direct address reaches an SFR. More in “The 8051: memory map, registers and SFRs” to these four, as timers, the serial port and interrupts shows; 8051 assembly covers the addressing modes and loops of every family.
The four families in Indian lab syllabi
Checkpoint
Check: The four families of lab programs
A lab record has four parts: aim, algorithm, program, result
A record lets someone who never saw your screen repeat the run and check it: what the program must do, in which steps, in which bytes, and what came out. Step through the block move’s record:
The drawing shows the whole scene; its 6 steps are listed below.
Every step as text
- The aim names the addresses. Copy the ten bytes at 30H-39H of internal RAM to 40H-49H. One sentence with the addresses in it, so the result can be held against it later.
- The algorithm in five steps. 1. Point R0 at 30H and R1 at 40H, and put 10 in R2. 2. Copy the byte R0 points at to the address in R1, through A. 3. Add 1 to R0 and to R1. 4. Subtract 1 from R2 and go back to step 2 until R2 is 0. 5. Stop.
- The program is the listing. The assembler listing gives each line its address and bytes: 14 bytes from 0000H to 000DH, with DONE, the jump to itself, at 000CH.
- The run, set up by hand. In uCsim: set memory writes the ten bytes at 30H, a dump shows 30H-4FH, break 0x000c sets the stop, run starts it, and a second dump and state follow at DONE.
- The result is read, not assumed. 40H-49H held power-on bytes before the run and the ten bytes of 30H-39H after it; 4AH-4FH did not change. 756 clock periods are 63 machine cycles, 68.36 µs at 11.0592 MHz.
- The result answers the aim. The aim promised ten bytes at 40H-49H, and the dump shows exactly those ten and nothing past them. A result that disagreed would send the record back to its algorithm.
The program part is the assembler’s listing, not the bare source, because the
assembler listing: A text file the assembler writes beside the object that pairs each source line with its offset and the bytes it produced, including the lines each macro use expanded to. nasm -l writes one. gives every line its address and bytes: block_move.asm assembled to 14
bytes at 0000H-000DH. The run loads ten bytes with set memory, stops at a breakpoint: An address, usually of an instruction, where a debugger stops the program just before that instruction runs. A breakpoint can be set by a function's name, which the debugger looks up in the symbol table, or by the address itself. More in “GDB and LLDB for assembly” on
DONE and dumps 30H-4FH before and after:
; Block move: copy the ten bytes at 30H-39H of internal RAM to 40H-49H.
CPU 8051
ORG 0000H
START: MOV R0,#30H ; R0 -> the next source byte
MOV R1,#40H ; R1 -> the next destination byte
MOV R2,#10 ; ten bytes to copy
COPY: MOV A,@R0 ; A = the byte R0 points at
MOV @R1,A ; store it where R1 points
INC R0
INC R1
DJNZ R2,COPY ; R2 = R2 - 1, back to COPY until it is 0
DONE: SJMP DONE ; stop here: nothing to return to
END """Assemble the block move, put ten bytes at 30H, run it to DONE and read both blocks."""
import pathlib
import sys
sys.path.insert(0, str(pathlib.Path(__file__).parent / "sessions"))
import eightbit
hexfile = eightbit.asm51("8051/block_move.asm") # AS, then p2hex: block_move.hex
eightbit.listing("block_move.lst") # line, address, bytes and source
eightbit.s51(hexfile, """
set memory iram 0x30 0x41 0x0c 0x5e 0x27 0x83 0x5e 0x96 0x3a 0xb2 0x70
dump /h iram 0x30 0x4f
break 0x000c
run
dump /h iram 0x30 0x4f
state
""") Output
$ asl -q -cpu 8051 -L -olist block_move.lst -o block_move.p 8051/block_move.asm
$ p2hex -q block_move.p block_move.hex
# block_move.lst: line/address, bytes, source
1/ 0 : ; Block move: copy the ten bytes at 30H-39H of internal RAM to 40H-49H.
2/ 0 : CPU 8051
3/ 0 : ORG 0000H
4/ 0 : 78 30 START: MOV R0,#30H ; R0 -> the next source byte
5/ 2 : 79 40 MOV R1,#40H ; R1 -> the next destination byte
6/ 4 : 7A 0A MOV R2,#10 ; ten bytes to copy
7/ 6 : E6 COPY: MOV A,@R0 ; A = the byte R0 points at
8/ 7 : F7 MOV @R1,A ; store it where R1 points
9/ 8 : 08 INC R0
10/ 9 : 09 INC R1
11/ A : DA FA DJNZ R2,COPY ; R2 = R2 - 1, back to COPY until it is 0
12/ C : 80 FE DONE: SJMP DONE ; stop here: nothing to return to
13/ E : END
$ s51 -t 8051 -R 1 block_move.hex < block_move.s51
set memory iram 0x30 0x41 0x0c 0x5e 0x27 0x83 0x5e 0x96 0x3a 0xb2 0x70
dump /h iram 0x30 0x4f
break 0x000c
run
dump /h iram 0x30 0x4f
state
quit
0x30 41 0c 5e 27 83 5e 96 3a A.^'.^.:
0x38 b2 70 .p
0x30 41 0c 5e 27 83 5e 96 3a A.^'.^.:
0x38 b2 70 0c f7 19 6a c9 d7 .p...j..
0x40 c0 76 dd 4f 50 e3 79 96 .v.OP.y.
0x48 28 d3 35 16 85 93 7c 42 (.5...|B
Breakpoint 1 at 0x00000c (cond="")
0x000c F 80 fe SJMP 0x000c
Simulation started, PC=0x000000
14 words read from block_move.hex
Stop at 0x00000c: (104) Breakpoint
R0 R1 R2 R3 R4 R5 R6 R7
3a 4a 00 27 e9 1a d9 27
@R0 0c . ACC= 0x70 112 p B= 0x00
@R1 35 5 PSW= 0x01 CY=0 AC=0 OV=0 P=1
SP 0x07 -> 27 d9 1a e9 27 00 4a 3a
DPTR= 0x00000000 @DPTR= 0xe1 225 .
0x000c F 80 fe SJMP 0x000c
F 0x00000c
Simulated 756 ticks (6.836e-05 sec)
0x30 41 0c 5e 27 83 5e 96 3a A.^'.^.:
0x38 b2 70 0c f7 19 6a c9 d7 .p...j..
0x40 41 0c 5e 27 83 5e 96 3a A.^'.^.:
0x48 b2 70 35 16 85 93 7c 42 .p5...|B
CPU state= OK PC= 0x00000c frequency= 11059200 HZ
Operation since last reset= 86 vclks
Inst= 54 Fetch= 66 Read= 10 Write= 10
Total time since last reset= 0.000068359375000 sec (756 clks)
Time in isr = 0.000000000000000 sec (0 clks) 0.00%
Time in idle= 0.000000000000000 sec (0 clks) 0.00%
Most value of stack pointer= 0x000007
Simulation: stopped
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 block_move_session.py
The result comes from the dumps, not from the code. Before the run, 40H-49H held c0 76 dd 4f 50 e3 79 96 28 d3, power-on state: The values registers and memory hold the moment a chip powers up, before any program runs. Intel's manuals say that the 8051's internal RAM, R0 to R7 included, is indeterminate at power-up and kept through a reset, and that a reset does not set the 8085's registers A to L or its flags. More in “8-bit toolchains: assemblers, HEX and simulators” bytes from uCsim’s seed; after it they equal 30H-39H, and 4AH-4FH still read 35 16 85 93 7c 42, so the loop wrote ten bytes and no more. uCsim counted 756 clock periods, 63 machine cycle: The unit in which 8051 instructions are timed: 12 periods of the oscillator, so its length depends on the crystal a board uses. More in “The 8051: memory map, registers and SFRs”: 3 to set up and 6 for each byte, 68.36 µs at 11.0592 MHz.
A result that repeats the aim
“The block was copied” is the aim in the past tense. Write down the bytes: 40H-49H before and after the run, and the bytes just past the block, which show that the copy stopped at 49H.
Checkpoint
Check: Aim, algorithm, program and result
Viva answers that point at the run
Each answer below names something the run printed.
Why do R0 and R1 hold the addresses, and not R2? Of R0 to R7, only R0 and R1 can be pointers: MOV A,@R0 and
MOV @R1,A are register-indirect addressing: An addressing mode in which a register holds the address of the operand, so the same instruction reaches a different byte whenever the register changes. The 8051 writes it with @, as in MOV A,@R0, where R0 or R1 holds an internal RAM address. More in “8051 assembly: addressing modes and lab programs” moves, and the 8051 has no @R2
form. R2 then serves as the count.
Why does the loop run exactly ten times? DJNZ R2,COPY subtracts 1 from R2 and jumps back while the result is
not 0, so a count of 10 gives ten passes. The run ended with R2 = 00H and 4AH untouched.
Why does the program end with SJMP DONE? Nothing waits for it to return: the processor fetches whatever byte
comes next, so the program parks on a jump to itself, and the breakpoint there stops the simulator.
Why does PSW read 01H? The last byte loaded into A was 70H, which has three 1 bits, and P, bit 0 of PSW, is 1 whenever A holds an odd number of 1 bits.
The run’s evidence, answer by answer:
| Answer | Evidence |
|---|---|
| Pointers | MOV A,@R0, MOV @R1,A |
| Ten turns | R2 = 00H; 4AH still 35H |
| The end | Stop at 0x00000c |
| Parity | ACC= 0x70, P=1 |
Questions like these make good viva practice because the evidence is on the page: a register, a byte or a count. Three parts follow. The first sorts 16 bytes with a bubble sort: A sorting method that walks through a list again and again, comparing each pair of neighbouring items and swapping any pair that is out of order, until the whole list is in order., which compares neighbouring bytes and swaps each pair that is out of order, and counts its cycles. The second runs the sort on the 8085, beside 8086 and RISC-V versions that are assembled, not run. The third reproduces a slip in it and sets nine viva questions.
Checkpoint
Check: Viva answers that cite the run
Practise
Change a copy of block_move.asm and write down the dump you expect before each run (8-bit toolchains covers AS and uCsim):
- Copy 16 bytes with
MOV R2,#16: what lands at 4AH-4FH? - Point R1 at 38H instead of 40H: which bytes end at 40H and 41H?
- How many machine cycles does each change take?
The self-check below starts where your answers are weakest.
Practice that adapts to you
Practise this lesson
11 questions about 6 ideas of this lesson. Each answer is explained at once, and what you get right is kept in this browser.
A bubble sort of 16 bytes, with its machine cycles counted Pro: opens with a Pro, Premium or Ultimate pass
The sort below uses three of the four families at once: data transfer for the swap, arithmetic for the compare and branch instructions for its two loops. Its run sorts 16 bytes at 30H-3FH in 1,200 machine cycles, and a model with four counts accounts for every one of them.
In this part:
- Two pointers and one SUBB per pair sort the 16 bytes
- 1,200 machine cycles, from a model checked against three runs
- Count the passes, comparisons and swaps of the 8051 sort
- Results of the sample tests
1 diagram · 3 runnable examples (ASM, Python) · 1 exercise with sample tests · about 10 minutes
Opening this part with your pass…
This part opens with any MySmartCoPilot pass.
- Pro pass · 1 week₹79$2.99
- 30 days₹179$5.99
- 1 year₹1,699$45
One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.
Passes can’t be bought right now, so this part can’t be opened at the moment. The free part above stands on its own. If you have a pass, enter your licence key.
It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).
The same sort on the 8085, the 8086 and RISC-V, compared Pro: opens with a Pro, Premium or Ultimate pass
An accumulator machine, a machine with memory operands and a load-store machine spend their bytes and instructions in different places. The 8085 version runs below in two simulators; the 8086 and RISC-V versions are assembled and listed, so their numbers are sizes and counts, not times.
In this part:
- The 8085 version: 953 instructions and 6,653 T-states in two simulators
- RISC-V and the 8086, assembled: 17 instructions in 68, 44 or 33 bytes
5 runnable examples (ASM, Python, bubble16.s, bubble86.asm) · about 7 minutes
Opening this part with your pass…
This part opens with any MySmartCoPilot pass.
- Pro pass · 1 week₹79$2.99
- 30 days₹179$5.99
- 1 year₹1,699$45
One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.
Passes can’t be bought right now, so this part can’t be opened at the moment. The free part above stands on its own. If you have a pass, enter your licence key.
It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).
A slip reproduced, a viva set and a rubric for the answers Pro: opens with a Pro, Premium or Ultimate pass
One wrong count in the sort gives a result that looks right on one board and wrong on the next. The runs below reproduce it under two power-on seeds, and a viva set then checks the module question by question, with a rubric for what each level of answer covers.
In this part:
- One count too many: 16 comparisons pull in the byte at 40H
- A viva set: nine questions, each with the evidence that settles it
- What a viva answer covers at each level
2 runnable examples (ASM, Python) · about 12 minutes
Opening this part with your pass…
This part opens with any MySmartCoPilot pass.
- Pro pass · 1 week₹79$2.99
- 30 days₹179$5.99
- 1 year₹1,699$45
One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.
Passes can’t be bought right now, so this part can’t be opened at the moment. The free part above stands on its own. If you have a pass, enter your licence key.
It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).
Interview questions
Four questions take the sort further: a stray byte, a time limit, the four versions weighed and an interrupt that breaks it.
-
Fresher to mid
An 8051 bubble sort of the 16 bytes at 30H-3FH is right on one board. On another, the same HEX file leaves a byte in the result that was never an input, and the largest input byte is missing. What is wrong, why does one board hide it, and how would you test for it on every board?
-
Fresher to senior
An 11.0592 MHz 8051 data logger stores one sample every 125 µs from a Timer 0 interrupt. The main program bubble-sorts each batch of 16 samples while the next batch fills. One test batch took well under 2 ms. Is the routine safe for every batch? What bound would you rely on, and how would you check it?
-
Mid to senior
You have one bubble sort written for the 8051, the 8085, the 8086 and 32-bit RISC-V, with each version's size and instruction counts; only the 8051 and 8085 versions were run. A colleague says the version with the fewest instructions per pair must be the fastest. What can the numbers tell you, and what would you measure next?
-
Mid to staff
An 8051 lab program bubble-sorts 16 bytes correctly. After a Timer 0 interrupt that counts ticks is added, most runs still end sorted, but now and then one pair is out of order, and once a byte that was never an input appeared. Explain the failure, how you would make it happen on every run, and the fix.
Flashcards · 4 cards
Recall it, then check
Say the answer to yourself before you look: recalling it is what makes it stick.
-
Into which families do most 8051 lab programs fall?
Data transfer, arithmetic, logical and branch programs, each resting on a few instructions.
-
What four parts does a lab record have?
The aim, the algorithm as numbered steps, the listing with every address and byte, and the result read from the run.
-
How is the 8051 block-move program shown to be right?
By its memory dump: after the run 40H to 49H equal 30H to 39H, 4AH to 4FH are unchanged, and the copy took 63 machine cycles.
-
What makes a viva answer strongest?
Pointing at a register, a byte or a count that the run printed, rather than a general description.
Key takeaways
- Most 8051 lab programs are data transfer, arithmetic, logical or branch programs, each resting on a few instructions.
- A lab record gives the aim, the algorithm as numbered steps, the listing with addresses and bytes, and the result read from the run.
- The block move’s result is its dump: 40H-49H equal 30H-39H after the run, 4AH-4FH are unchanged, and the copy took 63 machine cycles.
- A viva answer is strongest when it points at a register, a byte or a count the run printed.
Terms in this lesson
- bubble sort
- A sorting method that walks through a list again and again, comparing each pair of neighbouring items and swapping any pair that is out of order, until the whole list is in order.
- lab record
- The write-up of one lab program in four parts: the aim, the steps of the algorithm, the program as the assembler printed it with every address and byte, and the result as the run showed it, so that someone else can repeat the run and check it.
References
- MCS-51 Microcontroller Family User's Manual: instruction set, machine cycles, PSW and interrupt vectors (Intel Corporation)
- MCS-80/85 Family User's Manual: the 8085AH, its clock and its instruction set (Intel Corporation)
- Intel 64 and IA-32 Architectures Software Developer's Manuals: CMP, XCHG, JBE and LOOP (Intel Corporation)
- RISC-V Ratified Specifications: RV32I base integer instruction set (RISC-V International)
- RISC-V Ratified Specifications: the C extension for compressed instructions (RISC-V International)
- NASM documentation: assembler directives, BITS and CPU (The NASM Authors)
- llvm-mc: LLVM machine code playground (LLVM Project)
- uCsim: microcontroller simulator, with its MCS-51 and 8085 models (Daniel Drotos)
- Sim8085: an Intel 8085 simulator with assembler and debugger (Debjit Biswas)
- The Macroassembler AS: releases (Alfred Arnold)
- Microprocessor & Microcontroller (4341101): diploma course syllabus (Gujarat Technological University)
- B.Tech ECE third-year syllabus: BEC-502 and the BEC-552 laboratory (Dr. A.P.J. Abdul Kalam Technical University)
- GATE syllabus for Instrumentation Engineering (IN) (Indian Institute of Technology Madras)
Related tools
Report a problem with this lesson
Kept only in this browser. Your Learn progress