0
pub struct CIpv6Address {
    pub address: [u16; 8],
}

pub fn h() {
    let x = CIpv6Address {
        address: [1,2,3,4,5,6,7,8]
    };
}

generates

    sub     rsp, 32
    mov     word ptr [rsp + 16], 1
    mov     word ptr [rsp + 18], 2
    mov     word ptr [rsp + 20], 3
    mov     word ptr [rsp + 22], 4
    mov     word ptr [rsp + 24], 5
    mov     word ptr [rsp + 26], 6
    mov     word ptr [rsp + 28], 7
    mov     word ptr [rsp + 30], 8
    mov     rax, qword ptr [rsp + 16]
    mov     qword ptr [rsp], rax
    mov     rax, qword ptr [rsp + 24]
    mov     qword ptr [rsp + 8], rax
    add     rsp, 32
    ret

as can be seen here: https://godbolt.org/z/P4UHa_

I understood that it makes room in the stack pointer and fills with values. Why it starts at rsp + 16 though?

I can see then that if fills jumping by 4 bits. Why? My values are of 16 bits.

Finally, why it transfers the values from rsp +16 and rsp+24 to both rsp and rsp+8?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Guerlando OCs
  • 1,886
  • 9
  • 61
  • 150
  • 1
    *if fills jumping by 4 bits*. What? It's doing 8x 2-byte (word) stores. x86 is byte-oriented and doesn't do 4-bit operations easily. The last 4 `mov` qword copies are copying the whole 8x2 = 16-byte object because you disabled optimization. That explains reserving 2x 16 bytes on the stack. But if you enabled optimization, you'd get an empty function. – Peter Cordes Jun 02 '20 at 07:03
  • 2
    With [optimizations enabled](https://godbolt.org/z/Be3Psd), the code boils down to a single 128-bit copy using an XMM register. – IInspectable Jun 02 '20 at 07:09
  • Close to a duplicate of [Why does clang produce inefficient asm with -O0 (for this simple floating point sum)?](https://stackoverflow.com/q/53366394) for the general point about why compilers make such inefficient asm with optimization disabled. (Consistent debugging, and not even trying to optimize at all.) – Peter Cordes Jun 02 '20 at 07:12
  • @PeterCordes it moves the number `1` to the word (2 bytes) at address `rsp + 16` but then moves `2` to the word at address `rsp+20` which is just 4 bits more – Guerlando OCs Jun 02 '20 at 07:22
  • 1
    x86 is byte addressable, not bit. Those addresses are 4 *bytes* apart. (And actually it moves `2` to `[rsp+18]`, not 20, which starts just after the 2-byte word at `[rsp+16]`). So it's storing to 16 contiguous bytes, 2 bytes at a time, with increasing addresses. – Peter Cordes Jun 02 '20 at 07:23
  • ok so it fills `rsp+16`, which has 64 bits, with a 16 bits number, then jumps 1 entire 64 bits, just to place 2 as a 16 bits in the next 64 bits space? I know opmitization is off, but why leave 1 64 bits space blank? And the reason for not putting 16 bits next to another 16 bits next to another 16 bits is alignment, right? – Guerlando OCs Jun 02 '20 at 07:27
  • as always this kind of question should always be "why not" try to find why not if you find nothing you can conclude it a choice if you think something you can conclude is not a choice. Then you can start questioning this choice – Stargateur Jun 02 '20 at 07:28
  • 2
    @GuerlandoOCs no, again x86 is *byte*-addressable so `rsp+16` and `rsp+18` are *two bytes* apart. Which is 16 bits. It doesn't leave anything blank. – Masklinn Jun 02 '20 at 07:41
  • @Masklinn so each address in RAM stores only 8 bits? I thought it was 64 bits for each address – Guerlando OCs Jun 02 '20 at 08:05
  • 1
    @GuerlandoOCs in x86_64 yes, since the architecture is byte-addressable each address points to an 8-bit value. 64 bits is the address space (the number of addresses), as well as the width of general-purpose registries. Word-addressing has mostly fallen by the wayside. And even then, it was common for word-addressed architectures to have "bytewise" addresses and just ignore the bottom bits e.g. DEC Alpha had 32 bit words and was only word-addressable, but each address didn't point to a word, instead it'd just ignore the bottom 3 bits of the address. – Masklinn Jun 02 '20 at 09:02
  • 1
    @GuerlandoOCs: I think you're confusing the pointer width with the size of the pointed-to memory. There are several Q&As about that, including [How many bytes are there in one address?](https://stackoverflow.com/q/56717135). The fact that your Rust code compiled to this asm is also very good evidence that x86 is byte-addressable, as if any more evidence were needed when it's a very well documented fact. I forget if [What Every Programmer Should Know About Memory?](https://stackoverflow.com/q/8126311) covers that level of basics, or if it assumes that much. – Peter Cordes Jun 02 '20 at 09:40

0 Answers0