2

I'm given some C code and it's assembly counterpart, which I am to use to figure out the values of two constants that were declared by #define. My question is what does the line

leal 0(,%eax,8),%edx

do?

nrz
  • 10,435
  • 4
  • 39
  • 71
grim_v3.0
  • 387
  • 1
  • 4
  • 11
  • See http://stackoverflow.com/questions/4003894/leal-assembler-instruction – A.E. Drew Oct 17 '13 at 22:07
  • 1
    Get out of the broken GAS syntax and use Intel syntax instead, your sanity will thank you for it: `lea edx,[eax*8+0]` – Johan Oct 18 '13 at 11:57

2 Answers2

7

lea (and its size-suffixed variants) is the Load Effective Address instruction. Basically, it performs an address calculation: it takes an address description similar to what mov takes, but instead of accessing the memory at that address, it just loads the computed address value into a register. This can be used, for example, to obtain pointer values in C.

Because address descriptions are highly flexible (arbitrary starting base, offset from base, and flexible element size), and because lea is a fast instruction, lea is often called on to perform simple arithmetic. In this context, the use of lea has nothing to do with physical addresses, and is just being used to do math. Typically, this can be recognized when the registers involved are numeric values (as opposed to pointer values). In this case, the lea performs the operation %edx = %eax * 8. Since multiplying an address by 8 rarely results in a meaningful address, you can conclude that the lea instruction here is simply performing math.

nneonneo
  • 171,345
  • 36
  • 312
  • 383
  • +1, but you cannot categorically state that `lea is a fast instruction`. It depends on how lea gets translated into uops, which varies between CPU's. – Johan Oct 18 '13 at 12:01
  • The question is not whether it's fast, but whether the compiler thinks it is – Leeor Oct 18 '13 at 16:35
  • That [SHLD](http://www.felixcloutier.com/x86/SHLD.html) shifts 3 bits from the top of `%edx` into `%eax`. It's not the instruction you're looking for. LEA is the only way to copy-and-shift in one instruction, other than BMI2 [SHLX](http://www.felixcloutier.com/x86/SARX:SHLX:SHRX.html) and RORX. – Peter Cordes Dec 13 '16 at 01:30
  • @PeterCordes: Indeed, you're right. Not sure what I was thinking when I wrote that - nice catch! – nneonneo Dec 13 '16 at 02:46
4

This part:

0(,%eax,8)

is in the form:

base(offset, index, size)

and calculated as (offset & index need to be registers):

address = base + offset + (index × size)

in your case, eax is going to hold some address which will be multiplied by 8 and moved into edx (these operations are on the address not on the value). For example if eax = 0x11111111, the index, will be multiplied by 8 and edx will hold 0x88888888, that's all I can tell.

That doesn't look like a real work code. It's usually used with arrays as:

array_base_address( , index_of_element, sizeof_an_element)

for example:

.data
    # array of 3 elements 2 bytes each
    array: .short 0x0000, 0x1111, 0x2222
.text
    .global _main
_main:

    # address of 0x0000
    movl    $0, %eax
    leal    array( , %eax, 2), %ebx

    # address of 0x1111
    movl    $1, %eax
    leal    array( , %eax, 2), %ebx

    # address of 0x2222
    movl    $2, %eax
    leal    array( , %eax, 2), %ebx

it can also be used with structures as:

struct_base_address(offset_to_sub_element, index_of_element, sizeof_an_element)

for example:

.data
    struct:
        bytes: .byte  0, 1, 2, 3
        array: .int   0x00000000, 0x11111111, 0x22222222
.text
    .global _main
_main:

    # the offset to array
    movl    $4, %eax
    # the index of 0x22222222
    movl    $2, %ebx
    leal    struct(%eax, %ebx, 4), %edx