1

What is the proper way to access array elements in x86_64? For example, here is what I have going so far:

my_array:   .word 20,25,30,35
.globl _start
_start:

    movq $0, %rdi                  # should we use rdi for the offset?
    movz my_array(,%rdi,2), $r13   # how to move two bytes in r13 and zero-pad the rest?
    add $6, %rdi                   # move to next index position for my_array[3]
    movz my_array(,%rdi,2), $r14   # how to move two bytes in r14 and zero-pad the rest?

Basically what I'm trying to do is the following in pseudocode:

%r13 = my_array[0] # (20)
%r14 = my_array[3] # (35)

This is pretty sloppy and I'm sure the wrong way to do it (not to mention the movz is mis-sized and I'm having trouble figuring that out. What would be the correct way to do this then, using indexed-addressing mode?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
carl.hiass
  • 1,526
  • 1
  • 6
  • 26
  • 1
    Never use `movz` without a source operand size like `movzw`. Also, `$r14` is not a register name and will fail to assemble, I think you mean `%r14`. Also, the `add` instruction is unnecessary, use `my_array+6(,%rdi,2)` if you have a known constant offset. (Or better, just `my_array(%rip)` and `my_array+6(%rip)` for both known constant indexes). – Peter Cordes Aug 23 '20 at 04:29
  • If you want examples, compile a C function that takes an arg and uses it to index a global array, returning the value. Look at the asm output. [How to remove "noise" from GCC/clang assembly output?](https://stackoverflow.com/q/38552116) – Peter Cordes Aug 23 '20 at 04:30
  • @PeterCordes thanks for the feedback. I did that on godbolt but they're not using indexed addressing for the array, which I'm trying to learn: https://godbolt.org/z/jv5MoP. They just keep adding the array elements one at a time. – carl.hiass Aug 23 '20 at 04:36
  • @PeterCordes also, for the `movz`, what part of the command is optional and which part isn't, for example, I see results such as: `movzbw, movzbl, movzbq, movzwl, movzwq`. And wasn't sure if `movz` or `movzb` or `movzbw` is the right way to do it. – carl.hiass Aug 23 '20 at 04:38
  • 1
    Read my comment more carefully, and read the linked answer: a function *that takes an arg* and uses it to index the array. You just wrote a `main` where everything is a compile-time constant, so of course the compiler isn't going to put a `0` in a register and index with it. – Peter Cordes Aug 23 '20 at 04:48
  • @PeterCordes oh I see, thanks for pointing that out. Ok I got something that shows that now on godbolt: https://godbolt.org/z/KKbqr6. – carl.hiass Aug 23 '20 at 04:58
  • Way more readable if you use `-Og` to optimize *some*, but still without function inlining: https://godbolt.org/z/nrfr5x. You also don't need the `main` caller, you're not going to run it, just look at the asm output. (With no caller, you can crank up the optimization level to full `-O3` to see if anything changes. Or still look at the stand-alone definition which still exists because the function isn't `static` or `inline`.) – Peter Cordes Aug 23 '20 at 05:09
  • 1
    re: movzx in AT&T syntax: see [Moving a value of a lesser size into a register](https://stackoverflow.com/a/63389435). The accepted answer on that question uses `movzxb`; don't do that, that's a voodoo hybrid of AT&T and Intel mnemonics. See also [What does the MOVZBL instruction do in IA-32 AT&T syntax?](https://stackoverflow.com/a/31115069) which should have been the first hit if you googled for `site:stackoverflow.com movzbl` – Peter Cordes Aug 23 '20 at 05:13

0 Answers0