程序集 x86-64 从堆栈中获取函数参数
Assembly x86-64 get function parameters from stack
最近我一直在从 Programming from the Ground Up 书中学习 x86 汇编,但我有一台 x86-64 计算机,所以有一点开始出错(在书中很早的时候)。我到了处理函数的部分,特别是 power 示例。在这个例子中,他将参数压入堆栈,然后在函数后面将它们复制到寄存器中。他的代码如下所示:
pushl # second argument
pushl # first argument
call power # call function
...
power:
pushl %ebp # save old base pointer
movl %esp, %ebp # make stack pointer the base pointer
subl , %esp # get room for our local storage
movl 8(%ebp), %ebx # put first argument in %eax
movl 12(%ebp), %ecx # put second argument in %ecx
当然,这是 32 位的,而我是 运行 64 位的,所以我尝试更新寄存器和指令后缀以得到这样的结果(不需要注释)这次):
pushq
pushq
call power
...
power:
pushq %rbp
movq %rsp, %rbp
subq , %rsp
movq 8(%rbp), %rdi
movq 12(%rbp), %rsi
鉴于此,我可能只是混淆了我应该使用的实际寄存器,但我不完全确定。我所知道的是,当我在命令 movq 8(%rbp), %rdi
之后在 GNU 调试器中打印 %rdi 的值时,在我看来它似乎具有内存地址而不是它的内容考虑到我得到以下内容:
(gdb) i r rdi
rdi 0x400081 4194433
此外,是否有类似 Assembly 爱好者的论坛?我已经进行了一些基本的搜索,但没能找到一个(x86 程序集论坛除外,该论坛只有一个 post,欢迎 post,http://www.x86-assembly.org/)。
谢谢!
标准的 64 位约定不会像那样使用堆栈,它们至少会在寄存器中传递前几个参数(类型允许)。当然,对于您自己的代码,您仍然可以使用堆栈。但是,您应该调整您的偏移量,以便它们使用适当的大小,8 个字节而不是 4 个字节。
subq , %rsp
除非你知道自己在做什么,否则你真的应该使用 8 的倍数。
movq 8(%rbp), %rdi
您希望这是第一个参数,但事实并非如此。它实际上是堆栈上的 return 地址,因为现在每个项目都是 8 个字节。所以在 0(%rbp)
你有推送的 rbp
,8(%rbp)
是 return 地址。因此 16(%rbp)
是第一个参数,24(%rbp)
是第二个参数。
请注意,在大多数环境中,您仍然可以编写 32 位代码,因此如果您想继续使用那本书,您可能希望这样做,而不是尝试针对 64 位进行调整。
PS:您将获得一个使用调试器的 cookie :)
最近我一直在从 Programming from the Ground Up 书中学习 x86 汇编,但我有一台 x86-64 计算机,所以有一点开始出错(在书中很早的时候)。我到了处理函数的部分,特别是 power 示例。在这个例子中,他将参数压入堆栈,然后在函数后面将它们复制到寄存器中。他的代码如下所示:
pushl # second argument
pushl # first argument
call power # call function
...
power:
pushl %ebp # save old base pointer
movl %esp, %ebp # make stack pointer the base pointer
subl , %esp # get room for our local storage
movl 8(%ebp), %ebx # put first argument in %eax
movl 12(%ebp), %ecx # put second argument in %ecx
当然,这是 32 位的,而我是 运行 64 位的,所以我尝试更新寄存器和指令后缀以得到这样的结果(不需要注释)这次):
pushq
pushq
call power
...
power:
pushq %rbp
movq %rsp, %rbp
subq , %rsp
movq 8(%rbp), %rdi
movq 12(%rbp), %rsi
鉴于此,我可能只是混淆了我应该使用的实际寄存器,但我不完全确定。我所知道的是,当我在命令 movq 8(%rbp), %rdi
之后在 GNU 调试器中打印 %rdi 的值时,在我看来它似乎具有内存地址而不是它的内容考虑到我得到以下内容:
(gdb) i r rdi
rdi 0x400081 4194433
此外,是否有类似 Assembly 爱好者的论坛?我已经进行了一些基本的搜索,但没能找到一个(x86 程序集论坛除外,该论坛只有一个 post,欢迎 post,http://www.x86-assembly.org/)。
谢谢!
标准的 64 位约定不会像那样使用堆栈,它们至少会在寄存器中传递前几个参数(类型允许)。当然,对于您自己的代码,您仍然可以使用堆栈。但是,您应该调整您的偏移量,以便它们使用适当的大小,8 个字节而不是 4 个字节。
subq , %rsp
除非你知道自己在做什么,否则你真的应该使用 8 的倍数。
movq 8(%rbp), %rdi
您希望这是第一个参数,但事实并非如此。它实际上是堆栈上的 return 地址,因为现在每个项目都是 8 个字节。所以在 0(%rbp)
你有推送的 rbp
,8(%rbp)
是 return 地址。因此 16(%rbp)
是第一个参数,24(%rbp)
是第二个参数。
请注意,在大多数环境中,您仍然可以编写 32 位代码,因此如果您想继续使用那本书,您可能希望这样做,而不是尝试针对 64 位进行调整。
PS:您将获得一个使用调试器的 cookie :)