最近我从书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/)。
谢谢!
答案 0 :(得分:3)
标准的64位约定不使用这样的堆栈,它们至少传递寄存器中的前几个参数(类型允许)。当然,对于您自己的代码,您仍然可以使用堆栈。但是,您应该调整偏移量,使它们使用适当的大小,8个字节而不是4个字节。
subq $ 4,%rsp
除非你知道自己在做什么,否则你应该使用8的倍数。
movq 8(%rbp),%rdi
你希望这是第一个参数,但事实并非如此。它实际上是堆栈上的返回地址,因为现在每个项目都是8个字节。因此,在0(%rbp)
,您推送rbp
,8(%rbp)
是返回地址。因此16(%rbp)
是第一个参数,24(%rbp)
是第二个参数。
请注意,在大多数环境中,您仍然可以编写32位代码,因此如果您想继续使用该书,则可能需要这样做而不是尝试调整64位。
PS:你得到一个使用调试器的cookie:)