0
votes
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?

1
It's unclear what you are asking.Jester

1 Answers

2
votes

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.