0
long vframe(long n, long idx, long *q){
    long i;
    long *p[n];
    p[0] = &i;
    for(i=1; i<n; i++)
        p[i]=q;
    return *p[idx];
}

I have the vframe function and generated the assembly code like this

1: vframe:
2:    pushq    %rbp
3:    movq     %rsp, %rbp
4:    subq     $16, %rsp
5:    leaq     22(, %rdi, 8), %rax      # I think the number 22 is vary from machine and OS
6:    andq     $-16, %rax       
7:    subq     %rax, %rsp
8:    leaq     7(%rsp), %rax
9:    shrq     $3, %rax
10:   leaq     0(, %rax, 8), %r8
11:   movq     %r8, %rcx
................................
12: L3:
13:   movq     %rdx, (%rcx, %rax, 8)
14:   addq     $1, %rax
15:   movq     %rax, -8(%rbp)
16: L2:
17:   movq     -8(%rbp), %rax
18:   cmpq     %rdi, %rax
19:   jl       L3
20:   leave
21:   ret

If we see lines from 8 to 11, we didn't push address of p on stack but assembly has already assumed &p[0] is in %rsp since leaq 0(, %rax, 8), %r8 means the instruction set %r8 to &p[0] (Actually I check variable i is moved to stack by checking my own compiler like movq $0x1,-0x8(%rbp) but I couldn't find about &p[0])

If we want some argument not to be corrupted, we push some register and move callee saved register to the pushed register. But ,in this case, it seems not. Is there any other conventions about local variable like i and &p[0] in this code? I mean why &p[0] is in %rsp even though we didn't push &p[0] on stack?

cp3
  • 1
  • 2
  • 7

1 Answers1

2

The compiler internally keeps track of the offsets of each local variable, including p. It doesn't need to store the addresses of the local variables on the stack. In this case, it knows that p is at (%rsp).

This code doesn't use any call-preserved registers other than rbp, so that is the only one it saves.

prl
  • 11,716
  • 2
  • 13
  • 31
  • Then how we know that offset of local variable? Is there any other convention? I can find some assembly codes like allocating space for local variable i and array p(subq $16, %rsp in line 4 and subq %rax, $rsp in line 7) but I can't quess where it is – cp3 Nov 11 '18 at 07:03
  • There’s no convention; the compiler can lay out the stack frame however it likes. To find out what the compiler has done, you can look at the debugging information. Some compilers put comments in the assembly language output with the offsets. Or you can look at the assembly code to detect what the compiler stores where. – prl Nov 11 '18 at 07:22
  • For example, by examining the assembly code in the question, I can tell that n is in rdi and i is in -8(rbp) – prl Nov 11 '18 at 07:24
  • (The third way is the only way I use, so I cannot offer any advice on the first two.) – prl Nov 11 '18 at 07:31