【问题标题】:Can anybody explain what does this function do? [closed]谁能解释一下这个功能是做什么的? [关闭]
【发布时间】:2025-12-02 16:05:02
【问题描述】:
do_something(int):
   push rbp
   mov rbp, rsp
   push rbx
   sub rsp, 24
   mov DWORD PTR [rbp-20], edi
   cmp DWORD PTR [rbp-20], 1
   jg .L2
   mov eax, DWORD PTR [rbp-20]
   jmp .L3
.L2:
   mov eax, DWORD PTR [rbp-20]
   sub eax, 1
   mov edi, eax
   call do_something(int)
   mov ebx, eax
   mov eax, DWORD PTR [rbp-20]
   sub eax, 2
   mov edi, eax
   call do_something(int)
   add eax, ebx
.L3:
   add rsp, 24
   pop rbx
   pop rbp
   ret

【问题讨论】:

  • 代码中的所有内容都被隐藏 100% 的代码正在调用您没有提供的其他函数和偏移量,没有人可以帮助您
  • @coderx64: call do_something(int) 正在调用相同的函数;这个问题的问题只是缺乏努力/尝试。这显然是未经优化的g++ 输出复制/粘贴自godbolt.org。将 demangled 的 do_something(int) 更改为有效的 asm 符号名称,如 do_something,您可以编写一个调用程序,然后组装并运行它,以便您可以单步执行。它是一个自包含的递归函数。
  • @PeterCordes 但有很多 [rbp-20] 我们不知道它是什么。
  • @coderx64:注意 push rbp / mov rbp, rsp 堆栈帧设置,然后 mov [rbp-20], edi 将传入的整数 arg 转储到堆栈。访问相对于帧指针的局部变量(以及每个 C 语句之间的溢出/重新加载)是未优化代码的 100% 标准(“调试”构建,如 gcc -O0,gcc/clang 的默认值。)Why does clang produce inefficient asm with -O0 (for this simple floating point sum)?跨度>
  • 这个问题不会帮助任何偶然发现它的人。 “有人可以解释这是做什么的吗”甚至不是一个问题,因此它不会为社区提供价值。只是你自己。

标签: assembly x86-64


【解决方案1】:

它是 64 位 SystemV 调用约定中的未优化递归函数,带有一个返回整数值的整数参数。它在内部使用RBX 加上一个位于[rbp-20] 的4 字节(DWORD)局部变量。

用否定参数调用,比如 -1,它返回 RAX=0x00000000_FFFFFFFF
使用零参数调用它返回 0。
一步一步地通过它给出了

do_something(0)=0;
do_something(1)=1;
do_something(2)=1;
do_something(3)=2;
do_something(4)=3;
do_something(5)=5;
do_something(6)=8;
do_something(7)=13;
...

通常,对于正数 n,此函数返回其两个前任的总和:do_somenging(n)=do_something(n-1)+do_something(n-2)

【讨论】:

  • 这不是一个 24 字节的局部变量,这是一个误导性的无用描述,所以我为您修复了它。额外的 16 字节 GCC 保留但未使用(超出保存的 RBX 下面的 8 个字节,需要对齐以遵循 ABI)只是一个错过的优化。 Why does GCC allocate more space than necessary on the stack, beyond what's needed for alignment?
  • @PeterCordes 是的,名字错误。抱歉破坏
  • @phuclv:也删除了我的评论,所以未来的读者必须从数字中识别出顺序。
最近更新 更多