1
\$\begingroup\$

I understand how a CPU works fairly well, but there is this one thing which I've never really gotten the hang of.

Say we have an Intel 8086 CPU (16 bits wide registers) which is about to fetch its next instruction from RAM (also with a 16 bit data width). As the CPU fetches the instruction, say at 0x44AB, what exactly does RAM return? Is it an 8 bit op-code and an 8-bit operand? Does it return a 16 bit op-code, and then the operand is stored in 0x44AC?

In the first case, operands cannot have a value greater than 0xFF (255), but then why would you have 16-bit registers? In the second case, the program counter must be incremented by two between each instruction, and you use twice as much memory.

So how does this work? The question might seem a bit vague, but all I'm asking is really what the CPU does with the data returned from an address in RAM.

EDIT: Made the question more specific so that it's easier to give a good answer.

\$\endgroup\$
6
  • 1
    \$\begingroup\$ The RAM returns the 16 individual ones and zeros stores at the specified address. Depending on the CPU, that could be 1/2 of an opcode, 1 opcode or two opcodes. \$\endgroup\$ Jan 30, 2021 at 16:38
  • \$\begingroup\$ CPUs work differently depending on architecture. Do you mean "the most popular Intel CPUs" or something else? \$\endgroup\$
    – Reinderien
    Jan 30, 2021 at 16:49
  • \$\begingroup\$ This all depends on the ISA (Instruction Set Architecture) of that CPU. They are all different. Even within an ISA you usually find several different instruction formats. \$\endgroup\$
    – user16324
    Jan 30, 2021 at 17:50
  • 2
    \$\begingroup\$ all I'm asking is really what the CPU does with the data returned from an address in RAM. does not match How are programs stored in RAM? \$\endgroup\$
    – jsotola
    Jan 30, 2021 at 21:04
  • \$\begingroup\$ You can read the wikipedia article on 8086: en.wikipedia.org/wiki/Intel_8086. I hope you understood that the instruction is fetched from the instruction queue and not the RAM. If you are interested in this field you can learn for free from Saylor academy: learn.saylor.org They have a free online course on Computer Architecture \$\endgroup\$ Jan 31, 2021 at 17:23

2 Answers 2

8
\$\begingroup\$

Neither, as for the 8086 CPU, program code is just bytes of data in memory, and the bitness of registers have almost nothing to do with opcode length, as you can move bytes or 16-bit words, and also far jump to a 32-bit address (defined by segment and offset).

As the 8086 is a CPU with a 16-bit bus and the opcodes can be 1 to 6 bytes long, the opcodes may or may not be aligned in any way to the memory. However a typical optimization (manually or by compiler) is to place 16-bit variables and targets for code jumps at even addresses in the memory.

That is because the bus is 16 bits wide, so it must have 16-bit memory at each even memory address, and all odd memory addresses are simply the high 8-bit part of the 16-bit bus.

So, if there is a command which tells the CPU to go execute code at 0x44AB, which is an odd address, the CPU Bus Interface Unit (BIU) will first read one 8-bit byte from that address into the prefetch queue, and continue fetching 16-bit words at a time from address 0x44AC onwards into the prefetch queue.

The CPU Execution Unit (EU) will simply take bytes from the prefetch queue, or wait for bytes to appear if it is empty, and then decode the opcodes and takes any amount of bytes necessary from the queue to fully decode the opcodes.

If you do want to access read or write 16-bit word on odd addresses, the BIU has to do two 8-bit accesses. It needs to access a byte at the high part of 16 bits of a memory location, and the other byte at the low part of 16 bits of the next memory location.

\$\endgroup\$
2
\$\begingroup\$

When running the program, the CPU first reads in the opcode, and then decodes it to decide how many more bytes, if any, it needs to fetch in successive cycles to fulfill the instruction.

The thing that ‘decides’ is the CPU microcode, an internal program / finite state machine that controls the cycle-by-cycle operation of the CPU. The microcode also decodes the instruction to perform the data movements called out by the instruction.

The x86 architecture has variable-length instructions and variable-sized operands. The x86 microcode figures all this out as it decodes the opcode. Other machines, notably RISC, may use fixed-length opcodes but still will handle different-sized operands. This simplifies instruction decoding and increases speed, but trades off instruction density.

RISC or CISC (e.g., x86), the compiler / assembler / linker puts together an executable program, so that the byte sequences are arranged with exact knowledge of how the CPU fetches opcodes and operands.

The CPU running the compiled program thus assumes that what it is reading is in the right order and in the right format; and so long as the program was built correctly, this will be the case. The ‘right order’ is defined by the instruction set, with the format and length of each instruction determined by the initial opcode.

Otherwise, there’s no way for a running CPU to explicitly know from the data itself whether what is being read in is opcode, opcode extension, operand, or random garbage. Only the CPU microcode knows that.

\$\endgroup\$
1
  • \$\begingroup\$ This may be more detail than anyone wants, but the 8086 is more complicated than that. The decision of 1 byte vs 2 bytes is made by the Group Decode ROM, which is outside of the microcode. Simple 1-byte instructions or prefixes don't use the microcode at all. The microcode then gets additional bytes from the prefetch buffer as needed. See the patent for details: patents.google.com/patent/US4449184A \$\endgroup\$ Dec 21, 2022 at 3:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.