Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 程序调用在汇编程序中是如何工作的?_Assembly_X86_Call_Function Calls - Fatal编程技术网

Assembly 程序调用在汇编程序中是如何工作的?

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

我刚刚开始修补ASM,我不确定我对过程调用的理解是否正确

假设代码中有一个过程调用

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:这取决于调用约定。这里没有自动的。调用函数和被调用函数必须就返回值的位置达成一致。