assembly - 为什么在这个简单的程序中,与 C++ 相比,gfortran 会产生如此大的堆栈大小?
问题描述
我一直在将一些简单的程序从 C++ 和 Fortran 编译成程序集,以尝试更多地了解计算机体系结构。我用 C++ 和 Fortran 编写了一个非常简单的程序来产生一些输出然后返回。我不明白为什么 Fortran 编译器 (gfortran) 会生成与 C++ 相比创建如此大的堆栈帧的程序集。
f_subroutines.f
PROGRAM F_SUBROUTINES
CALL SAY_HELLO
CALL SAY_GOODBYE
END
SUBROUTINE SAY_HELLO
PRINT '(A6)', "Hello."
END
INTEGER*4 FUNCTION GET_MY_NUMBER()
GET_MY_NUMBER = 3
END
SUBROUTINE SAY_GOODBYE
INTEGER :: GET_MY_NUMBER
PRINT '(A18, I1, A19)',
1 "Here's my number: ", GET_MY_NUMBER(), ". Call me. Goodbye!"
END
cpp_subroutines.cpp
#include <cstdio>
void say_hello()
{
std::printf("Hello.\n");
}
int get_my_number()
{
return 3;
}
void say_goodbye()
{
std::printf("Here's my number: %d. Call me. Goodbye!\n", get_my_number());
}
int main()
{
say_hello();
say_goodbye();
return 0;
}
生成文件
CPPFLAGS=-O0
all: cpp_subroutines cpp_subroutines.s f_subroutines f_subroutines.s
cpp_subroutines: cpp_subroutines.o
$(CXX) $(CPPFLAGS) -o $@ $^ $(LDFLAGS)
cpp_subroutines.s:
$(CXX) $(CPPFLAGS) -S cpp_subroutines.cpp
f_subroutines: f_subroutines.o
$(FC) -o $@ $^ $(LDFLAGS)
f_subroutines.s:
$(FC) -S f_subroutines.f
.PHONY: clean
clean:
$(RM) cpp_subroutines cpp_subroutines.o cpp_subroutines.s \
f_subroutines f_subroutines.o f_subroutines.s
cpp_subroutines.s:say_hello
_Z9say_hellov:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl $.LC0, %edi
call puts
nop
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
f_subroutines.s:say_hello
say_hello_:
.LFB2:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $480, %rsp
movq $.LC0, -472(%rbp)
movl $8, -464(%rbp)
movq $.LC4, -408(%rbp)
movl $4, -400(%rbp)
movl $4096, -480(%rbp)
movl $6, -476(%rbp)
leaq -480(%rbp), %rax
movq %rax, %rdi
call _gfortran_st_write
leaq -480(%rbp), %rax
movl $6, %edx
movl $.LC5, %esi
movq %rax, %rdi
call _gfortran_transfer_character_write
leaq -480(%rbp), %rax
movq %rax, %rdi
call _gfortran_st_write_done
nop
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
我正在使用 gfortran 和 gcc 版本 5.4.0。
我不太确定 Fortran 程序集在这里做什么:
subq $480, %rsp
movq $.LC0, -472(%rbp)
movl $8, -464(%rbp)
movq $.LC4, -408(%rbp)
movl $4, -400(%rbp)
movl $4096, -480(%rbp)
movl $6, -476(%rbp)
leaq -480(%rbp), %rax
这个堆栈帧似乎使用了 480 个字节并放置
- 源文件名 (.LC0) 从底部算起 8 个字节
- 值 13 距底部 16 个字节
- 格式说明符 '(A6)' (.LC4) 从底部算起 64 个字节
- 值 4 从底部算起 80 个字节
- 底部的值 4096(页面大小?)
- 值 6 从底部算起 4 个字节。
我对 C++ 编译的输出非常满意,但我想知道为什么
- Fortran 编译会产生如此大的堆栈帧。
- 8 美元、4 美元、4096 美元和 6 美元的价值是什么。
解决方案
这是 GFortran 中长期存在的问题,有关详细信息,请参阅https://gcc.gnu.org/bugzilla/show_bug.cgi?id=48419。
推荐阅读
- c++ - 在 C++ 中获取旋转的音高
- c++ - clang 插件:在编译期间修改 AST
- ruby-on-rails - Rails 添加 pass 变量以从循环创建新记录
- sql - 使用JPA在Sql中具有不同值的多个语句where子句
- oracle - LocalDateTime 映射到 Oracle DATE,但不映射到 H2 DATE
- c# - 在 C# 中将用户名转换为 SID
- cmake - 为什么 CMAKE 安装的目标无法链接到提供的库?
- javascript - 如何标记在 JavaScript 画布上创建的框?
- java - 在不更改 UI android 的情况下,究竟需要如何以及在何处更改以接受来自重音内容的正常字符搜索
- libraries - 为什么语言需要库?