2

I have been studied assembly language based on gcc -S outputs, and i find some syntax i've not seen before. From C code:

#include <stdio.h>
void main() {
        printf("%d\n", sizeof(int));
}

I've got this:

        .file   "test.c"
        .def    __main; .scl    2;      .type   32;     .endef
        .section .rdata,"dr"
.LC0:
        .ascii "%d\12\0"
        .text
        .globl  main
        .def    main;   .scl    2;      .type   32;     .endef
        .seh_proc       main
main:
        pushq   %rbp
        .seh_pushreg    %rbp
        movq    %rsp, %rbp
        .seh_setframe   %rbp, 0
        subq    $32, %rsp
        .seh_stackalloc 32
        .seh_endprologue
        call    __main
        movl    $4, %edx
        leaq    .LC0(%rip), %rcx
        call    printf
        nop
        addq    $32, %rsp
        popq    %rbp
        ret
        .seh_endproc
        .ident  "GCC: (tdm64-1) 5.1.0"
        .def    printf; .scl    2;      .type   32;     .endef

And even if this code is very clear and understandable, that one line of it is completely strange for me. The line i am talking about is:

 leaq    .LC0(%rip), %rcx

And even if i know that leaq is instruction for loading effective address, that the operand syntax is unclear for me, i mean label of formatting string with instruction pointer as parameter? What does it do? Thanks in advance :)

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
wojcienty
  • 313
  • 1
  • 4
  • 14
  • 3
    That's RIP-relative addressing, it stores address relative to the instruction pointer. Read any x86-64 reference material for details. Or, you know, the [assembler manual](https://sourceware.org/binutils/docs/as/i386_002dMemory.html). – Jester Mar 22 '17 at 21:53
  • RIP relative addressing, loading a quad into RCX. – David Hoelzer Mar 22 '17 at 21:54
  • I'm very pleased by your comments, but there is one thing i don't understand yet. We have relative addressing, i understand that, but how its achived? I mean, by adding, subtracting? I have looked in IDA dump, and i what i saw was that this instruction address was 0x12 (Exactly what %rip should have + some memory address after loading) and the printf formatting address was 0x40. Please say more about it. – wojcienty Mar 22 '17 at 22:37
  • 2
    `cs:rip` points to next instruction to execute. At first it points at the first byte of `lea rcx,[rip+xyz]`, then the CPU will fetch it's opcode, decode it as `lea`, fetch correct number of remaining bytes of opcode, and update `rip` to point to next instruction (`call`). Then it will execute the `lea`, so the `rip+xyz` will evaluate already with the `call` instruction address, and resulting address is stored into `rcx`. (The compiler will calculate "xyz" in such way, that `next_instruction_address + xyz` == `.LC0`) – Ped7g Mar 23 '17 at 04:05
  • 1
    disassembly of `lea rcx,[rip+0]` (getting address of next instruction to `rcx`): `48 8d 0d 00 00 00 00 lea rcx,[rip+0x0]` => so `lea` in this case is 7B long, and displacement is sign-extended 32b value. – Ped7g Mar 23 '17 at 04:18

0 Answers0