可变大小堆栈框架的组装:这些堆栈对齐指令在分配VLA时似乎没用?

问题描述 投票:2回答:1

[我正在阅读《计算机系统:程序员的观点》第三版,3.10.5 Supporting Variable-Size Stack Frames, Figure 3.43中的程序集使我感到困惑。

本书的一部分试图解释如何生成可变大小的堆栈框架,并以C代码及其汇编版本为例。

这是C和汇编的代码(本书的图3.43:]:>

我不知道在程序集中使用第8-10行

是什么。为什么不只在第7行之后使用movq %rsp, %r8

((a)C代码

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];
}

((b)部分生成的汇编代码

vframe:
2:    pushq    %rbp
3:    movq     %rsp, %rbp  
4:    subq     $16, %rsp
5:    leaq     22(, %rdi, 8), %rax      
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

我想的是:

[在第7行之后,%rsp应该是16的倍数(由于堆栈帧对齐,在调用%rsp之前,vframe应该是16的倍数。当调用vframe时,减去%rsp用8保持调用者的返回地址,然后第2行中的pushq指令将另外8减去%rsp,并在第4行16中减去。因此,在第7行的开始处,%rsp是整数16的行,在%rsp中减去%rax。由于第6行使%rax为16的倍数,因此第7行的结果为%rsp的设置为16的倍数) %rsp的4位全为零。

然后,在第8行中,%rsp+7存储在%rax中,在第9行中,%rax在逻辑上右移3位,在第10行中,%rax*8存储在%r8中。第7行之后,%rsp的低4位全为零。在第8行%rsp+7仅将低3位全为1,在第9行将这3个位截断,在第10行%rax*8使结果左移3位。因此,最终结果应该只是原始的%rsp(第7行的结果)。

所以我想知道第8-10行是否无用。

为什么不只在第7行之后使用movq %rsp, %r8并删除原始的8-10行?

我正在阅读《计算机系统:程序员的观点》第三版以及3.10.5支持可变大小堆栈框架的组装,图3.43使我感到困惑。这本书的一部分正在尝试...

c assembly x86-64 callstack stack-frame
1个回答
0
投票
我认为有用的探索性程序是将您生成的代码减少为:

.globl _vframe _vframe: pushq %rbp movq %rsp, %rbp subq $16, %rsp leaq 22(, %rdi, 8), %rax andq $-16, %rax subq %rax, %rsp leaq 7(%rsp), %rax shrq $3, %rax leaq 0(, %rax, 8), %r8 mov %r8, %rax sub %rsp, %rax leave ret

© www.soinside.com 2019 - 2024. All rights reserved.