程序集x86-64从堆栈中获取函数参数

时间:2016-06-04 23:05:29

标签: linux function assembly x86-64 stack-memory

最近我从书Programming from the Ground Up开始学习x86汇编,但我有一台x86-64计算机,所以事情一下子就开始出错了(本书很早就开始)。我到了处理函数的部分,特别是 power 示例。在这个例子中,他将参数压入堆栈,然后在函数中将它们复制到寄存器中。这是他的代码的样子:

pushl $3                        # second argument
pushl $2                        # first argument
call power                      # call function
...
power:
  pushl %ebp                    # save old base pointer
  movl %esp, %ebp               # make stack pointer the base pointer
  subl $4, %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 $3
pushq $2
call power
...
power:
  pushq %rbp
  movq %rsp, %rbp
  subq $4, %rsp

  movq 8(%rbp), %rdi
  movq 12(%rbp), %rsi

鉴于,我可能会混淆我应该使用的实际寄存器,但我不完全确定。我所知道的是,当我在命令movq 8(%rbp), %rdi之后在GNU调试器中打印%rdi的值时,在我看来,好像它有内存地址而不是它的内容,考虑到我得到以下结果:

(gdb) i r rdi
rdi            0x400081 4194433

此外,是否有像大会爱好者的论坛?我做了一些基本的搜索,但没有设法找到一个(除了x86汇编的论坛,只有一个帖子,这是一个欢迎帖子,http://www.x86-assembly.org/)。

谢谢!

1 个答案:

答案 0 :(得分:3)

标准的64位约定不使用这样的堆栈,它们至少传递寄存器中的前几个参数(类型允许)。当然,对于您自己的代码,您仍然可以使用堆栈。但是,您应该调整偏移量,使它们使用适当的大小,8个字节而不是4个字节。

  

subq $ 4,%rsp

除非你知道自己在做什么,否则你应该使用8的倍数。

  

movq 8(%rbp),%rdi

你希望这是第一个参数,但事实并非如此。它实际上是堆栈上的返回地址,因为现在每个项目都是8个字节。因此,在0(%rbp),您推送rbp8(%rbp)是返回地址。因此16(%rbp)是第一个参数,24(%rbp)是第二个参数。

请注意,在大多数环境中,您仍然可以编写32位代码,因此如果您想继续使用该书,则可能需要这样做而不是尝试调整64位。

PS:你得到一个使用调试器的cookie:)