在下面的图像中,有一个程序集代码。不管我多努力,我都不太明白它是如何工作的。下面是我的思考过程:我假设我输入了3。
代码继续到堆栈如下所示:
return address
bp
3
2返回添加sp,2
bp
2
1返回添加sp,2
bp现在,ax=1和它将跳到出口。
现在炮塔会怎么做?事情进展如何?
我怎么知道它是_cdecl还是_stdcall


发布于 2022-07-21 17:34:41
这是你的汇编程序逐行转换成一个等价的C程序.这可能更容易推理,因为这些操作在C中更明显。
被call/ret推送/弹出的返回地址被简化为指针递减/增量,因此相对于SP的偏移量与asm相同。如果您愿意,可以使用GNU C扩展正确地模拟这一点(实际上是推送代码地址并跳转到它们)。
#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
}如果您仍然不知道,您只需调用该函数并查看输出。
#include <stdio.h>
int main(void) {
for (int i = 1; i <= 8; ++i) {
*sp-- = i;
printf("%"PRIdPTR"\n", func());
}
return 0;
}输出是,
1
2
6
24
120
720
5040
40320这应该是一个非常熟悉的数列。如果不是,请在OEIS中搜索序列。
https://stackoverflow.com/questions/73068002
复制相似问题