Assembly 程序调用在汇编程序中是如何工作的?
我刚刚开始修补ASM,我不确定我对过程调用的理解是否正确 假设代码中有一个过程调用Assembly 程序调用在汇编程序中是如何工作的?,assembly,x86,call,function-calls,Assembly,X86,Call,Function Calls,我刚刚开始修补ASM,我不确定我对过程调用的理解是否正确 假设代码中有一个过程调用 call dword ptr[123] 该过程仅由一个命令ret组成: ret 0004 此过程调用的效果如何,返回值将存储在何处?我在某处读到一个2字节的返回值将存储在AX中,但是当我将过程调用替换为 mov AX, 0004 (连同必要的NOP)程序崩溃。我不认为返回值存储在寄存器AX中 // possibly there are arguments pushed here ... call dword
call dword ptr[123]
该过程仅由一个命令ret组成:
ret 0004
此过程调用的效果如何,返回值将存储在何处?我在某处读到一个2字节的返回值将存储在AX中,但是当我将过程调用替换为
mov AX, 0004
(连同必要的NOP)程序崩溃。我不认为返回值存储在寄存器AX中
// possibly there are arguments pushed here
...
call dword ptr[123] // push next OP code offset in the stack and jump to procedure
// procedure
...
ret 0004 // pop offset, set EIP to that offset and decrease ESP by 4
如果在调用过程之前在堆栈中推送了参数,那么我们还可以减少ESP
如果有推送参数,您的程序会崩溃,因为您没有弹出它们。当前过程的返回偏移量将是错误的,因为它将从一个推送参数中获取一个值作为偏移量。在x86汇编程序中,
ret
指令的参数表示:
retimmediate
返回调用过程并从堆栈中弹出即时字节
(引自)
因此,当您键入:
ret 0004
您告诉CPU在调用后立即返回指令,并从堆栈中弹出4个字节。如果在调用之前将4个字节推送到堆栈上,这将非常好
push eax
call dword ptr[123]
请注意,这与返回值无关。事实上,程序集中的过程无法指定值是返回值。这一切都是按惯例进行的。据我所知,大多数编译器都会使用EAX
来保存返回值,但这是正确的,因为调用函数将在那里预期结果
所以你的电话号码是:
call dword ptr [123]
mov dword ptr [result], eax
mov eax, 4
ret
返回值4的函数是:
call dword ptr [123]
mov dword ptr [result], eax
mov eax, 4
ret
这完全取决于所使用的设备。我不会在这里重复维基百科的文章,只是阅读定义
例如,在中,返回值将是EAX/AX/AL。您的单个指令没有返回值:它是一个void函数,包含大约4个字节的参数(可能是一个int),但不执行任何操作。由于被调用方有责任清理此调用约定中的堆栈,因此忽略此操作并用“mov ax”替换调用是不起作用的
我还怀疑您在阅读16位文档时可能正在修补32位汇编。这不是什么大问题,但您应该意识到其中的差异。谢谢!我在谷歌上搜索的大多数教程都只使用了ret,没有解释ret的即时操作。当LLVM汇编器显然有一个“ret”命令时,我更加困惑了。有什么理由可以让ret返回到调用之外的某个地方吗?我刚刚创建了一个问题,并在相关的问题中发现了这个问题,如果您操纵了CALL
推到堆栈上的返回地址。@int3:这取决于调用约定。这里没有自动的。调用函数和被调用函数必须就返回值的位置达成一致。