I've been reading about CPUs and how they are implemented, and some big complex architectures (looking at you x86) have instructions that load from memory during one clock cycle. Since one address points to a single byte, how is it possible that I can write:

mov eax, DWORD PTR ds:[esi]

where I'm loading a double word (4 bytes!) from memory and chucking it into eax. How does this work with only one clock cycle? Wouldn't it have to access 4 addresses? The DWORD starts from ds:[esi] and ends up at [ds:[esi] - 3] meaning it has to compute 4 effective address, but it does it in one cycle.



  • Possible duplicate of How Do Computers Work? – gnat Jan 3 '18 at 17:56
  • 1
    What makes you think that when you ask the CPU to load a single byte it actually requests and loads a single byte from memory (or that the memory bus is even capable of that), and not, say, load 64 bits or some other amount and then discard all the stuff it doesn't need? – Ordous Jan 3 '18 at 18:05
  • What about 8-bit processors (8086, Z80) that had 8-bit data busses? – DylanG Jan 3 '18 at 18:08
  • 8-bit processors, such as the 8080 or Z80, will make several memory fetches to load a double-word. Both the architecture and implementation affect how and when data is fetched. – BobDalgleish Jan 3 '18 at 18:32
  • @gnat this is a very specific question and not a duplicate of the very general question you're referring to. – Christophe Jan 3 '18 at 18:54

Because the width of the data bus and the size of the smallest addressable unit are two separate things.

Just because you can specify addresses at the byte level, does not mean you have to have an 8 bit data bus. Most (possibly all) modern x86 processors use a 64 bit data bus and every time they read from memory, they read 64 bits. If you only requested 8 bits, the excess is simply discarded.

If you request more than 64 bits (for example, if loading 128 bit SSE registers), then there will be multiple memory accesses.

Many processors also have a concept of alignment, which basically means that every memory access is on a address divisible by the data bus width. Most can still fetch unaligned memory, but if it crosses an alignment boundary (for example, requesting 32 bits at address 0xFC on a 64 bit aligned system), you'll get multiple memory accesses, even if it would otherwise fit in the data bus.

Here's a few other notes regarding some aspects of your question:

  • A single memory access takes longer than one cpu clock cycle. Much, MUCH longer if it's not in L1 cache. See this post for rough orders of magnitude, and keep in mind that 1 nanosecond = 1 clock cycle at 1 GHz. Many desktop and laptop CPUs these days can run upwards of 3 GHz, or less than 0.333... nanoseconds per cycle.
  • One clock cycle does not equal one instruction. Instructions (even those that stay entirely within the CPU, not accessing any memory or peripherals) can take multiple cycles to complete. Additionally, multiple instructions can be executing at the same time (and I'm not referring to multiple cores or hyperthreading here, I mean multiple instructions simultaneously executing on a single core, without hyperthreading).

As an example to illustrate the workings, let's first talk about a classic 32-bit processor like the good old 68020.

For various reasons (compatibility, usability for ASCII characters, ...), even 32-bit and 64-bit CPUs have names (called "addresses") for individual bytes. If the CPU needs to name a bigger chunk of memory, e.g. 4 bytes, it uses the name for the first byte, and implicitly the following bytes are the ones with the immediately following address numbers.

On the other hand, the bus can transfer 32 bits at once, because the CPU has 32 data lines D0...D32. So, of the 32 bit of an address, the lower 2 bits select a group of data lines (bits 00 select D0...D7, 01 selects D8...D15, 10 selects D16...D23, and 11 selects D24...D31). Only the higher 30 address bits exist as real address lines A2...A32. Instead of the lower 2 bits, the CPU has four distinct byte-select signals that it can use individually in different combinations.

Now, if the CPU wants to read 32 bits from address 0x1000, it can use all 32 data lines in parallel. It places the higher 30 bits on the address bus, and sets all four byte-select signals, so it transfers 4 bytes.

Let's get some overview:

  • read byte from 0x1000: Address bus = 0x1000, Byte-Select 0
  • read byte from 0x1001: Address bus = 0x1000, Byte-Select 1
  • read byte from 0x1002: Address bus = 0x1000, Byte-Select 2
  • read byte from 0x1003: Address bus = 0x1000, Byte-Select 3
  • read byte from 0x1004: Address bus = 0x1004, Byte-Select 0
  • read short from 0x1000: Address bus = 0x1000, Byte-Select 0+1
  • read short from 0x1002: Address bus = 0x1000, Byte-Select 2+3
  • read int from 0x1000: Address bus = 0x1000, Byte-Select 0+1+2+3
  • read (unaligned) int from 0x1002: (first cycle) Address bus = 0x1000, Byte-Select 2+3, then (second cycle) Address bus = 0x1004, Byte-Select 0+1

With current CPUs the principle stays the same, but with internal cache memory you can no longer observe the individual byte transfers of the CPU core from the outside. They happen between the CPU core and the cache (both on-chip). The memory only talks with the cache now, and that transfer is always done in bigger chunks than a byte.

  • All modern processors have byte-addressable memory. But back in the day when your 68020 was a hot new thing, byte-addressability was not a universal feature. E.g., PDP-10 computers, could only fetch 18 or 36 bits at a time. – Solomon Slow Jan 3 '18 at 19:55
  • @jameslarge Yes, there have even been machines (a Data General one, if I remeber correctly) where the byte-address of one memory location differed from the longword-address of the same location by a factor of 4. C programs had to make heavy use of pointer casting when using malloc()-style dynamic memory. – Ralf Kleberhoff Jan 4 '18 at 9:38

Your Answer

