сборка для кадра стека переменного размера (о стеке для локальной переменной) - PullRequest
0 голосов
/ 10 ноября 2018
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];
}

У меня есть функция vframe и я сгенерировал ассемблерный код следующим образом

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

Если мы видим строки от 8 до 11, мы не помещали адрес p в стек, но сборка уже предположила, что & p [0] находится в% rsp, так как leaq 0 (,% rax, 8),% r8 означает, что инструкция устанавливает% r8 в & p [0] (На самом деле я проверяю переменную I перемещается в стек, проверяя мой собственный компилятор как movq $ 0x1, -0x8 (% rbp), но я не смог найти информацию о & p [0])

Если мы хотим, чтобы какой-то аргумент не был искажен, мы помещаем некоторый регистр и перемещаем сохраненный регистр вызываемого абонента в регистр с принудительной отправкой. Но в этом случае, похоже, нет. Есть ли в этом коде другие соглашения о локальной переменной, такие как i и & p [0]? Я имею в виду , почему & p [0] находится в% rsp, хотя мы не помещали & p [0] в стек?

1 Ответ

0 голосов
/ 10 ноября 2018

Компилятор внутренне отслеживает смещения каждой локальной переменной, включая p.Для этого не нужно хранить адреса локальных переменных в стеке.В этом случае ему известно, что p равно (% rsp).

Этот код не использует регистры, сохраняющие вызовы, кроме rbp, поэтому он сохраняет только один.

...