Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.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 打电话给don';I don’我没有按预期工作_Assembly_X86_Return_Stack_Nasm - Fatal编程技术网

Assembly 打电话给don';I don’我没有按预期工作

Assembly 打电话给don';I don’我没有按预期工作,assembly,x86,return,stack,nasm,Assembly,X86,Return,Stack,Nasm,我仍然经常对与堆栈相关的操作感到迷茫,在这种情况下,问题是RET指令,它会弹出一个错误的eip寄存器地址。我使用了NASM,我的代码如下所示: start: call GiveMeAHandler call GetCommandLine ret GiveMeAHandler: push ebp mov ebp, esp push edi push esi push dword -11 call dword [F_GetSt

我仍然经常对与堆栈相关的操作感到迷茫,在这种情况下,问题是RET指令,它会弹出一个错误的eip寄存器地址。我使用了NASM,我的代码如下所示:

start:
    call GiveMeAHandler
    call GetCommandLine
    ret

GiveMeAHandler:
    push ebp
    mov ebp, esp
    push edi
    push esi
    push dword -11
    call dword [F_GetStdHandle] ; It executes correctly and returns
    mov [StdHandler], eax ; StdHandler is stored in BSS
    add esp, 4
    pop esi
    pop edi
    pop ebp
    ret ; This returns to some weird address

GetCommandLine:
    ; ...
    ; I don't get here because the function above wrong return

也许我对推送和弹出
ebp、edi、esi
有点夸张(它们毕竟没有改变),但即使我删除它们,
ret
指令仍然返回错误的地址(77AE7094),而不是0040100A,在这里我调用第二个函数。

让我们看看NASM为推送dword-11生成了什么:

6AF5    push byte -0xb
因此,NASM将您的
dword
替换为
字节
(CPU会将其升级为
,因为
是您可以
推到堆栈上的最小单元)。
它为什么这样做?嗯,有一个默认启用的,它将尝试优化即时消息的大小

由于您(可以理解)认为您推送了一个
dword
,然后在
esp
中添加了4,因此最终导致堆栈不平衡

要阻止这种情况发生,您可以添加
strict
说明符,如下所示:

push strict dword -11

或者在组装时使用
-O0
选项

让我们看看NASM为推送dword-11生成了什么:

6AF5    push byte -0xb
因此,NASM将您的
dword
替换为
字节
(CPU会将其升级为
,因为
是您可以
推到堆栈上的最小单元)。
它为什么这样做?嗯,有一个默认启用的,它将尝试优化即时消息的大小

由于您(可以理解)认为您推送了一个
dword
,然后在
esp
中添加了4,因此最终导致堆栈不平衡

要阻止这种情况发生,您可以添加
strict
说明符,如下所示:

push strict dword -11

或者在组装时使用
-O0
选项

默认情况下,Windows使用
stdcall
调用约定,将函数参数推送到堆栈上(从右到左),被调用方清理堆栈。换句话说,当
GetStdHandle
返回时,堆栈将在
push dword-11
指令之前恢复。尝试删除添加esp,4行,看看是否能解决问题。

默认情况下,Windows使用
stdcall
调用约定,函数参数被推送到堆栈上(从右到左),被调用方清理堆栈。换句话说,当
GetStdHandle
返回时,堆栈将在
push dword-11
指令之前恢复。尝试删除“添加esp,4”行,看看是否能解决问题。

在《英特尔软件开发人员手册》第二卷中,“推送”指令:“操作数大小(16、32或64位)决定堆栈指针的递减量(2、4或8)。”假设这是32位代码,默认操作数大小将为32位,因此,CPU实际上会将其升级为dword
推送字节-0xb
只是dword
推送的立即数的压缩编码。没有
66
操作数大小前缀,因此默认的32位操作数大小适用于32位模式,而不是任何模式下可用的最小值。无论如何,强制对dword push进行不太紧凑的编码在这里是没有用的。在《英特尔软件开发人员手册》第二卷中,“操作数大小(16、32或64位)决定堆栈指针的递减量(2、4或8)。”假设这是32位代码,默认操作数大小为32位,因此,CPU实际上会将其升级为dword
推送字节-0xb
只是dword
推送的立即数的压缩编码。没有
66
操作数大小前缀,因此默认的32位操作数大小适用于32位模式,而不是任何模式下可用的最小值。无论如何,强制对dword push进行不太紧凑的编码在这里是没有用的。是的,事实上,我可以看到retn 4并删除了我自己的堆栈清理。谢谢,事实上,我可以看到retn 4并移除了我自己的堆栈清理。谢谢