首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在递归函数中组装x86代码在堆栈推送/pop中的处理错误

在递归函数中组装x86代码在堆栈推送/pop中的处理错误
EN

Stack Overflow用户
提问于 2022-07-21 14:28:09
回答 1查看 73关注 0票数 0

在下面的图像中,有一个程序集代码。不管我多努力,我都不太明白它是如何工作的。下面是我的思考过程:我假设我输入了3。

  1. mov bp,sp //使bp指针等于sp
  2. mov,bp +2/ ax变为等于3.3,存储在ax bp之上的2个地址,返回上方的1个地址。
  3. “议定书”/“公约”缔约方会议a,1/3不等于1
  4. jz退出//代码不会跳转到退出,因为3不等于1。
  5. push ax // 3现在在bp-1
  6. 12月/ ax=2
  7. push ax // ax=2被推到bp-2上 所以现在我们有了堆栈 回邮地址bp 3 2
  8. 调用func //函数再次被调用
  9. 函数完成后添加sp,2 //返回地址,并添加sp+2删除变量

代码继续到堆栈如下所示:

代码语言:javascript
复制
return address
bp
3
2

返回添加sp,2

代码语言:javascript
复制
bp
2
1

返回添加sp,2

代码语言:javascript
复制
bp

现在,ax=1和它将跳到出口。

现在炮塔会怎么做?事情进展如何?

我怎么知道它是_cdecl还是_stdcall

EN

回答 1

Stack Overflow用户

发布于 2022-07-21 17:34:41

这是你的汇编程序逐行转换成一个等价的C程序.这可能更容易推理,因为这些操作在C中更明显。

call/ret推送/弹出的返回地址被简化为指针递减/增量,因此相对于SP的偏移量与asm相同。如果您愿意,可以使用GNU C扩展正确地模拟这一点(实际上是推送代码地址并跳转到它们)。

代码语言:javascript
复制
#include <inttypes.h>

#define SIZE 0x200
intptr_t virtual_stack[SIZE];
intptr_t *sp = virtual_stack + SIZE - 1;

intptr_t func(void) {
  intptr_t *bp = sp;   // mov bp, sp
  intptr_t ax = bp[1]; // mov ax, [bp + 2]
  if (ax == 1)     // cmp ax, 1
    goto exit;     // jz exit
  *--sp = ax;      // push ax
  --ax;            // dec ax
  *--sp = ax;      // push ax
  --sp; ax = func();   // call func  pushes a return address. 
  ++sp;            // add sp, 2
  intptr_t bx = *sp++; // pop bx
  ax = ax * bx;    // mul bx
exit:
  ++sp; return ax;  // ret  pops a return address; we just do a dummy operation
}

如果您仍然不知道,您只需调用该函数并查看输出。

代码语言:javascript
复制
#include <stdio.h>

int main(void) {
  for (int i = 1; i <= 8; ++i) {
    *sp-- = i;
    printf("%"PRIdPTR"\n", func());
  }
  return 0;
}

输出是,

代码语言:javascript
复制
1
2
6
24
120
720
5040
40320

这应该是一个非常熟悉的数列。如果不是,请在OEIS中搜索序列。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73068002

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档