[我正在阅读《计算机系统:程序员的观点》第三版,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位全为零。
%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使我感到困惑。这本书的一部分正在尝试...
.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