How can ADD be a 1 byte instruction?

I am learning 8051 coding. I came across the instructions of these forms ADD R7 and ADD A, R5. Now, since ADD is a mathematical operation, which should always take place in the accumulator, isn't the ADD A, R5 command redundant?

And secondly, how can these be a 1 byte instruction? I mean, there should be 2 bytes, one for the opcode which says that it is an add operation, and the second byte will have the byte value that is to be added to the accumulator. How can both be squeezed into one byte?

• you may wish to consider accepting one of the answers. It's an important part of the process. Jan 8 '14 at 16:24
• Sorry mate, forgot. Done now.. Jan 9 '14 at 20:25

You are correct that ADD A, R5 is redundant. This is probably done for clarity in the code, to make it slightly more human-readable.

ADD is either a one-byte or a two-byte instruction, depending on what's getting added to what. If you're adding a constant, or the value at an arbitrary address, then ADD is a two-byte instruction. It's only a one-byte instruction if there are enough bits in the opcode besides those indicating ADD to indicate something else useful. In this case, there are two variations: add one of eight registers, or add what's found at a particular address (with that address stored in one of two registers).

• Yeah, I did find that ADD A, #5f is a 2 byte instruction, then why isn't ADD A, R5 a 2 byte instruction as well? Sep 11 '13 at 21:22
• @Cupidvogel Because only five bits are necessary to indicate "ADD", not an entire byte. "5" (indicating register five) can be represented by the remaining three bits in the byte. This does mean there are limits on what registers can be used for what purposes; R12 couldn't be used, because 12 can't be represented in three bits. Sep 11 '13 at 21:23
• Umm, why? What is the opcode for ADD? And where is 5 coming from in this question? Sep 11 '13 at 21:25
• @Cupidvogel The opcode for ADD A, Rn is 00101, as shown in the link. That's only five bits. 5 comes from your example ADD A, R5. Sep 11 '13 at 21:27
• Okay, so basically it is 101, and 5 bits remain. Since there are 8 registers, numbered 0 to 7, there are specified by the corresponding BCD, which takes up at most 3 bits. Remaining 5 digits are covered by ADD (padded by 0s to make up 5), right? Sep 11 '13 at 21:32

The 8x51 instruction set has 16 instructions of the form "do something with Rn" where n=[0..7]; every combination of operation and register number is assigned a different opcode; a total of 128 opcodes are used for such purposes. Some of the operations operate only on Rn, and some only on Rn and the accumulator. In either case, the opcode specifies everything that needs to be said about the instruction. Some other operations require more information (e.g. "load Rn with some constant", "load Rn with data from some directly-specified address", "decrement Rn and branch forward or backward some distance if not zero", or "compare Rn with data at some specified address and branch forward or backward some distance if not equal"). In those cases, one or two additional bytes will be required following the opcode.

• So when a single byte code is generated, how will the system know which part is the opcode and which part is the operand (in this case, the number 5, the serial number of the register whose value is to be added to A)? I mean, if there are two single byte instructions, the one like here: [7..3][2..0], where the first 5 bits are the opcode, and the last 3 are the operand. Let's imagine another one: [7..4][3..0]. Both are single byte instructions, how will the system know in which case the opcode is 4 bits and in which case opcode is 5 bits? Sep 11 '13 at 22:19
• All opcodes whose MSB is set are of the form 1nnn oooo (where nnn identifies one of eight registers, and oooo one of 16 operations). Sep 11 '13 at 22:36
• So whenever the machine find an instruction of the type 1nnn oooo, it will do a prescribed operation based on the value of oooo, with the value stored in the register specified by nnn, right? And among those 16 operations, one is add the value of the said register with A and store it there? Sep 11 '13 at 22:41
• @Cupidvogel: Bingo, except I described the exact bit ordering wrong [oops]. See keil.com/support/man/docs/is51/is51_opcodes.htm for a list of opcodes. Sep 11 '13 at 22:47

If you check the op-codes for ADD on an 8051 here

You will see that ADD R5 has opcode 0x2D.

It adds the value in R5 to the Accumulator and stores the result in the Accumulator. Only one byte is needed to code this

Whereas ADD #xx where xx is immediate data has opcodes 0x24 xx needing two bytes.

See Atmel's 8051 family hardware manual at http://www.atmel.ca/Images/doc4316.pdf . It includes a detailed listing of the bit patterns for all 8051 instructions.

ADD A, R5 is not an instruction; it is a fragment of assembly language. Assembly language is not machine language. It contains syntax that does not correspond to anything in machine language directly, such as pseudo-operations, alternative register names and such.

Even if some instruction always uses a fixed register as a source or destination operand, or both, those can still appear explicitly in the assembly language syntax.

As for "how can something be a one-byte operation"? You can use as little as one bit to encode a symbol. Take a look at a compression method called Huffman Coding. Huffman coding lets us take an alphabet (or, more generally, a dictionary of some symbols, which are bit strings, or whatever) and assign them to table of variable-length codes, the shortest of which is just one bit!

Not that Huffman coding would commonly be used for instruction sets, but the principle is there: there are ways to use variable bit lengths in order to encode important symbols in less space, at the cost of lengthening the codes for others.

For instance, if you have an 8 byte opcode field, you could reserve, say two bits of it to classify opcodes into four categories. The remaining 6 bits are then category specific. Three of the categories (say) could use the remaining 6 bits to encode various instruction kinds so that, for instance, anything which starts with 00, 01, or 10 is some kind of regular opcode. But one of the four categories, say 11, could just stand for "add immediate to accumulator". The remaining six bits (and their 64 possibilities) would encode the value to be added, between 0 and 63. The value 0 (add 0 to accumulator) could serve as a no-op instruction, so that in the assembly language ADD #0, A and NOOP could be two spellings for exactly the same bit pattern (bringing us back to earlier points). Or the value 0 could be taken to designate 65, extending the addition range (and so NOOP would be something else, and ADD #0, A would be rejected by the assembler as out of range).

Effectively, you could regard this situation as having 64 different "add immediate to accumulator" instruction flavors, with one opcode for each value to be added, or you can regard that as a special two-bit opcode within the opcode byte, with an immediate field.

• So essentially, in my case, a part of the opcode denotes the BCD of the register whose value needs to be added to A, while the remaining 5 bits take up the opcode itself, right? Sep 11 '13 at 22:31
• Your first paragraph is rubbish. ADD A, R5 is an instruction too. And there's a 1-on-1 correspondence between assembly language and machine code. Sep 12 '13 at 10:51
• I guess he meant that the system does not interpret it in that manner, it is first converted into a machine-readbale opcode. Sep 12 '13 at 17:19
• The text ADD A, R5 is not a machine language instruction, but a source-level assembly representation of one. The claim that assembly is 1:1 with machine code is easily refuted. There are pseudo-ops and macros in assembly languages that do not correspond to an instruction, and there can be instruction sequences generated by one line of assembly. Assemblers can also analyze code and reorganize it, and do things like automatically fill branch delay slots (specific to a CPU model) and so on.
– Kaz
Sep 12 '13 at 18:19
• Another important way in which assembly is not 1:1 to machine language is the use of symbols for addresses and such. We can refer to a data or code address as FOO. When this is assembled, FOO changes to a concrete number. But that number will change as we reorganize the program's data and code over time. So FOO potentially maps to many numbers (not 1:1). Symbolic assembly languages, even rudimentary ones, are considerably higher level than machine code.
– Kaz
Sep 12 '13 at 19:27