【问题标题】:(Homework) Translating a C recursive function to assembly (AT&T syntax)(作业)将 C 递归函数转换为汇编(AT&T 语法)
【发布时间】:2015-05-19 04:23:25
【问题描述】:

这是我的 C 代码:

void combinationComputer(int* temp, int* arr, int* data, int start, int end,
                         int index, int k, int* x, int* y, int count) {
    int i;

    if (index == k) {
        if (count > k) {
            *x = *x + k;
            *y = *y + k;
        }

        for (i = *x; i < *y; i++)
            temp[i] = data[i - *x]; // storing all combinations into temp[] as a
                                    // single chunk, one combination at a time

        return;
    }

    for (i = start; i <= end && end - i + 1 >= k - index; i++) {
        data[index] = arr[i]; // each combination is stored in data[], with each
                              // subsequent combination overwriting the previous
                              // one.
        count = count + 1;
        combinationComputer(temp, arr, data, i + 1, end, index + 1, k, x, y,
                            count); // recursive call
    }
}

这个函数的作用与问题不太相关,我只是在返回后卡在 for 循环中。请参阅此 for 循环以递归方式调用该函数。最终 for 循环将不成立,它只会在到达最后一个括号时退出函数。

在 C 语言中,这会自动将控制权返回给组合计算机的父调用,在此 for 循环内。我不确定如何在汇编中实现这一点。在 C 中是否有此行为的特定名称? (是尾调用消除)?

基本上我要问的是当您退出(通过到达最后一个括号)递归调用的函数并返回到父调用时调用的行为是什么。这如何在汇编中实现(请不要代码,只是逻辑)如果您需要更多信息,请询问。

【问题讨论】:

  • 到达结尾大括号的void 函数会执行返回,就像您明确地将return; 放在那里一样。它与第一个return; 完全相同,通常使用ret 指令。尾调用消除完全是另外一回事,这里不适用,因为递归调用不在尾部位置。
  • 好吧,我不知道。谢谢。将其发布为答案。我会选择它。
  • “将 C […] 函数转换为程序集”——您应该为此使用 C 编译器。
  • 检查您的 C 编译器是否有生成汇编源代码的选项(通常是 -S(大写字母“S”))。然后你可以编辑它以提高可读性和调整。

标签: c assembly recursion att


【解决方案1】:

首先,汇编中的一些重要说明:

  • CALL:压入调用后要执行的下一条指令的地址,调用函数或方法。
  • RET:弹出栈顶元素并跳转到该地址。
  • 堆栈:堆栈是您的朋友,可以在寄存器不可用时将变量从一个递归调用传递给另一个。

如需了解有关英特尔指令的更多信息,请查看:Intel Manuals

一些示例代码(asm 中的斐波那契):

  mov eax, 10     # calculating fib(10)
  call fib        # eax contain the fib to calc
  .. PRINT fib result in eax ..
  ..

proc fib:
  cmp eax, 0     # checking for final conditions 0 or 1
  jnz continue1;
  mov ebx, 1     # returning 1 for fib(0)
  ret
continue1:
  cmp eax, 1
  jnz continue2
  mov ebx, 1     # returning 0 for fib(1)
  ret
continue2:
  dec eax        # decrementing the **n** value to calc (the first
  push eax       # saving n-1
  call fib       # calc fib(n-1)
  mov edx, eax   # saving result in edx
  pop eax        # restoring n-1 in eax
  dec eax
  call fib       # calc fib(n-2)
  add edx, eax   # add to the previos fib(n-1)
  ret

您可以使用 gcc -o [.asm output file] -S [.c to compile] 并阅读输出以了解有关代码生成的更多信息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-25
    • 2014-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-23
    • 1970-01-01
    相关资源
    最近更新 更多