-1

I'm using this textbook Randal E. Bryant, David R. O’Hallaron - Computer Systems. A Programmer’s Perspective [3rd ed.] (2016, Pearson). For this problem 3.43 I am not sure why a few of the questions yields a assembly code as seen in the given answer.

question

Firstly, I am unsure as to why there is a addition of 10 for the case of &up->t1.w before the movw.

Secondly, I'm unsure about why the up->t2.a yields only a single line in assembly when the first 2 examples required us to do the following:

movq (%rdi), %rax
movq %rax, (%rsi)

What changed?

Thirdly, a similar confusion for the line up->t2.a[up->t1.u] being translated as such:

movq (%rdi), %rax
movl (%rdi,%rax,4), %eax
movl %eax, (%rsi)

Any and all help is appreciated, thank you!

answer

Megan Darcy
  • 530
  • 5
  • 15
  • 4
    **DO NOT post images of code, data, error messages, etc.** - copy or type the text into the question. [ask] – Rob Sep 23 '21 at 17:23
  • @Rob I would count these as illustrations. Maybe OP doesnt have the book digitally, copying all this is a waste – DownloadPizza Sep 23 '21 at 17:27
  • 2
    The addition of 10 is to get to the offset of the struct. Try `sizeof(long) + sizeof(short)` in a C program – DownloadPizza Sep 23 '21 at 17:30
  • @DownloadPizza To find out, remove the "illustrations" and see if the question is still answerable without them. – Rob Sep 23 '21 at 17:35
  • 1
    @DownloadPizza I expect OP to put in the work and copy the relevant parts of the book into his question. It would make the question easier to read, too. – fuz Sep 23 '21 at 19:27

1 Answers1

1

What changed?

a is only a pointer; rdi can be directly written to the address in rsi:

mov    QWORD PTR [rsi],rdi

u is a value, and it's in memory because it's a struct member. This requires a load and a store, which x86 can't do with a single mov; a register has to be involved. Here rax is a tmp variable:

mov    rax,QWORD PTR [rdi]
mov    QWORD PTR [rsi],rax

This is equivalent to a hypothetical:

mov    QWORD PTR [rsi], QWORD PTR [rdi]   !!! NOT encodeable into machine code

The more complicated addressing mode:

This is Base-Scale/Index-Displacement

movl (%rdi,%rax,4), ...

takes rdi as base plus 4*rax as offset, or in C syntax: int rdi[rax]. In Intel syntax asm it looks like this (because asm uses byte offsets, no implicit scaling by operand-size):

mov  ..., [rdi + rax*4]

Sadly, AT&T and Intel syntax look very different...I prefer the explicit xWORD PTR [], and right-to-left.

This is the get() for the int array:

void get_a(u_type *up, int **dest) {
    *dest = up->t2.a;
}

Really just forcing a copy of a (array-) pointer.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • 1
    *A normal CPU cannot move from address to address in one instruction* - x86 can't ([at least not two *explicit* addressing modes](https://stackoverflow.com/questions/52573554/what-x86-instructions-take-two-or-more-memory-operands)), m68k and VAX can. Most people consider m68k and VAX to be normal. (Not *common*, but in terms of design m68k is as normal as x86.) Actually, with dest, src args and the x86-64 SysV calling convention, things are perfectly set up for a `movsq` instruction to do `*rdi++ = *rsi++` in one instruction if you want. Compilers *don't* do that because it slower. – Peter Cordes Sep 23 '21 at 18:50
  • `movsq` is not a `mov` (data transfer), but a "string" operation to be REPeated. But my statement is not too precise, thanks for these details. Maybe what counts is not the instructions, but the micro-ops. And no CPU circuitry can make a byte in RAM move without that byte passing through the CPU. –  Sep 23 '21 at 19:38
  • Yeah, my comment was 100% a word-choice nitpick, not a disagreement with your overall point or the example of an invalid `mov` with two memory operands; I already upvoted. To avoid over-complicating things by bringing up `movsq` or efficiency, perhaps say "this requires a load and a store, so a compiler will use two `mov` instructions because it's not encodeable with two memory operands. Because that *is* true, and the fact that `movs` and `push/pop [mem]` exist isn't relevant if compilers (and this problem) don't use them. – Peter Cordes Sep 23 '21 at 19:53
  • (BTW, `movs` does work without a `rep` prefix, BTW, that's just one option for repeating "string" instructions. The other intended use is to put them in a loop that does other stuff as well during each iteration; more common with lods, stos, scas, and cmps than with movs, though. Stephen Morse, architect of the 8086 ISA, discussed that design intent in his book, free online these days, https://www.stevemorse.org/8086/index.html around page 72, as the reason for the `loop` and `jcxz` instructions existing and using the same CX as `rep`. Of course that's mostly obsolete for performance!). – Peter Cordes Sep 23 '21 at 19:58
  • Since you didn't correct your answer, I went ahead and edited for you. Now it's both technically correct and (I hope) still as useful / readable as before. – Peter Cordes Sep 23 '21 at 20:12