0

I'm going over some notes from Berkeley's CS61C here and there is a part that is talking about memory addresses.

On most current architectures, including the MIPS architecture, an int must have an address that's divisible by 4. So if you think of memory as being full of integers, it looks like this

enter image description here

but if you think of memory as full of characters, it looks like this:

enter image description here

Saying this another way, the rightmost two bits in any int address are zero.

The reason for this last statement is that the two rightmost bits represent 2^0 and 2^1 which are not divisible by four; the entire integer will be divisible by four if and only if those rightmost two bits are zero.

Question: why must the address be divisible by four?

This is my interpretation

  • addresses are 32 bits, so they go from 0 to 2^32-1
  • the smallest addressible unit of memory is a byte
  • so each of those addresses refers to one of these bytes
  • but an integer is 32 bits, so four bytes, ie it fits into four addresses
  • lets assume address number 4 points to a integer; this integer will be represented in memory positions 4, 5, 6, 7; therefore, the next available address for an integer is address 8
  • therefore, as long as the smallest address is divisible by four, all the others will be divisible by four necessarily.
  • if the first address of an int had been address 3, then this property that the rightmost two bits are zero wouldn't hold.
  • is this correct?
evianpring
  • 3,316
  • 1
  • 25
  • 54
  • 2
    You're probably going to find this Q&A (and the links it proffers) informative: [Purpose of memory alignment](https://stackoverflow.com/questions/381244/purpose-of-memory-alignment) – WhozCraig Dec 17 '19 at 10:40
  • 2
    There's no requirement in the Standard for a precise alignment... https://ideone.com/J0vBD4 – pmg Dec 17 '19 at 10:46
  • 2
    Your assumptions are all correct, although a bit clumsily worded. The 4th bullet I would reword as "each of the 4 bytes in a integer has a unique address". Also you leave out a few details, such as "the 4 bytes of an integer are contiguous; their addresses differ by 1". Things go slightly off-track at your 5th bullet. What if you allocate a single byte after the first integer, using address 8? The next available address is then 9. _But on MIPS, that address is unusable_. The hard rule is that the lowest bits must be 00. – MSalters Dec 17 '19 at 11:14
  • @pmg: Your code has UB when compiled for any normal ABI where `alignof(int) = sizeof(int) = 4`. The standard allows implementations with `alignof(int) = 1` but that is not the case on any mainstream x86 C implementation. The fact that it happens to work doesn't prove anything. Yes the target ISA supports unaligned loads, but [Why does unaligned access to mmap'ed memory sometimes segfault on AMD64?](//stackoverflow.com/q/47510783) demonstrates a case where autovectorization with a misaligned `uint16_t*` crashes because of an assumption the compiler is allowed to make. – Peter Cordes Dec 17 '19 at 15:08
  • @pmg: to do an unaligned load safely in ISO C, use `memcpy` (and hope it inlines like GCC will on targets that support unaligned loads). Or in GNU C, use `typedef int unaligned_int __attribute__((aligned(1), may_alias));` – Peter Cordes Dec 17 '19 at 15:10
  • mips and arm historically have this rule for performance as when these came about and part of their design is to use wider busses. when x86 came out the common memories were 8 bits wide, but internally the 8088 was an 8086 with an external bus that would sometimes do two transfers to get one thing done. down the road becoming 32 or 64 bit you can have unaligned transfers which have a penalty but because of cache and pipe and prefetch you cant see it, with mips and arm being more streamlined you can see the performance hit. – old_timer Dec 23 '19 at 06:14
  • no reason why you cant implement a mips and/or arm that supports unaligned transfers, arm always did but pre armv6 lets say it was not that desirable. at and after it has a performance hit but is supported most likely because programmers got used to x86 and simply cannot cope. Still see folks running into this and not understanding on this site on a regular basis. after a couple of decades of this being known. – old_timer Dec 23 '19 at 06:17
  • It has to do with addresses. As you have shown or perhaps understand the actual memory is forced to 32 bits wide, all accesses are 32 bits wide for performance reasons to read a 32 bit value (think int if you will) at address 0x1000 takes one bus cycle, but a 32 bit value at address 0x1002 takes two one at 0x1000 where two bytes are kept and one at 0x1004 where two bytes are kept, merged and sent to the processor core. Less efficient, put the work on the programmer and the toolchain to get that performance boost in a system design. – old_timer Dec 23 '19 at 06:20
  • And no most architectures do NOT require you to force alignment, you appear to be learning MIPS, think of MIPS at this point as a teaching instruction set, not the best, but because of how/when/etc it was developed it has been used as a teaching tool for a long time now. Understand that it has nuances that are isolated to it and now risc-v, most of the rest of the world does NOT do it the MIPS way. MIPS to some extent does not do it the MIPS way depending on what the topic is. Dont get mislead into thinking MIPS is the standard/norm. – old_timer Dec 23 '19 at 06:26
  • The alignment or not is tied to the bus near the processor which may be on die or not. Can go into a long discussion about busses and memory implementations and the glue between them. Dram has for a while often been made up of 8 bit wide parts, but from a system design cannot be accessed that way, depends on the system, because of how slow it usually has a cache in front which is internally fixed width and that helps make the dram transactions aligned, but that doesnt mean the processor to cache has to be. – old_timer Dec 23 '19 at 06:28
  • yeah reading at least near where you posted I would be careful with absolute statements like that. that is a compiler/target decision, while true the compilers are going to (hopefully) by default generate aligned addresses for variables be they 16, 32, 64, etc bits wide, but they are free to choose (which is why you should never use structs, etc across compile domains) the alignment at least with languages like C where there is a lot of implementation defined wiggle room. – old_timer Dec 23 '19 at 06:33
  • memorize and follow the absolutes and MIPS rules the world notions while in this class or college, but once that is behind you then you can learn reality. You wont pass to many classes trying to argue with the teacher that the teaching materials are wrong or misleading or incomplete even if they are. But understand that college is a stepping stone to the real world it is in no way shape or form is the real world. And that can be confusing with so much content out here on the internet that is a combination of reality and fantasy. – old_timer Dec 23 '19 at 06:37

0 Answers0