简体   繁体   English

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

[英]Assembly x86-64 get function parameters from stack

Lately I've been learning x86 Assembly from the book Programming from the Ground Up , but I have an x86-64 computer, so things start to go wrong at one point (pretty early in the book). 最近我从“从头开始编程 ”一书中学习了x86汇编,但我有一台x86-64计算机,所以事情一下子就开始出错了(本书很早就开始)。 I got to the part where I'm dealing with functions, specifically the power example. 我到了处理功能的部分,特别是功能示例。 In this example he pushes the parameters onto the stack and then copies them into registers later in the function. 在这个例子中,他将参数压入堆栈,然后在函数中将它们复制到寄存器中。 Here's what his code looks like: 这是他的代码的样子:

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

Of course, this is 32-bit, and I'm running 64-bit, so I tried updating the registers and instruction suffixes to end up with something like this (comments shouldn't be needed this time): 当然,这是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

Given, I might just be confusing the actual registers I'm supposed to use, but I'm not completely sure. 鉴于,我可能只是混淆了我应该使用的实际寄存器,但我不完全确定。 All I know is that when I print the value of %rdi in the GNU Debugger after the command movq 8(%rbp), %rdi it seems to me as if it has the memory address rather than the contents of it considering I get the following: 我所知道的是,当我在命令movq 8(%rbp), %rdi之后在GNU调试器中打印%rdi的值时,%rdi在我看来好像它有内存地址而不是它的内容考虑到我得到了以下:

(gdb) i r rdi
rdi            0x400081 4194433

Also, is there something like a forum for Assembly hobbyists? 还有,像大会爱好者的论坛? I've done some basic searching but haven't managed to find one (except for a forum for x86 assembly that just has one post and it's a welcome post, http://www.x86-assembly.org/ ). 我做了一些基本的搜索,但没有设法找到一个(除了x86汇编的论坛,只有一个帖子,这是一个欢迎帖子, http://www.x86-assembly.org/ )。

Thanks! 谢谢!

The standard 64 bit conventions don't use the stack like that, they pass at least the first few arguments (type permitting) in registers. 标准的64位约定不像这样使用堆栈,它们至少传递寄存器中的前几个参数(类型允许)。 Of course for your own code you can still use the stack. 当然,对于您自己的代码,您仍然可以使用堆栈。 However, you should adjust your offsets so that they use the appropriate size, 8 bytes instead of 4. 但是,您应该调整偏移量,以便它们使用适当的大小,8个字节而不是4个字节。

subq $4, %rsp subq $ 4,%rsp

You should really use multiples of 8 unless you know what you are doing. 除非你知道自己在做什么,否则你应该使用8的倍数。

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

You expect this to be the first argument but it isn't. 你希望这是第一个参数,但事实并非如此。 It is actually the return address on the stack, since each item is 8 bytes now. 它实际上是堆栈上的返回地址,因为现在每个项目都是8个字节。 So at 0(%rbp) you have the pushed rbp , and 8(%rbp) is the return address. 因此,在0(%rbp)您具有推送的rbp ,并且8(%rbp)是返回地址。 Thus 16(%rbp) is the first argument and 24(%rbp) is the second. 因此, 16(%rbp)是第一个参数, 24(%rbp)是第二个参数。

Note that in most environments you can still write 32 bit code, so if you want to keep using that book you might want to do that instead of trying to adjust for 64 bit. 请注意,在大多数环境中,您仍然可以编写32位代码,因此如果您想继续使用该书,您可能希望这样做而不是尝试调整64位。

PS: You get a cookie for using a debugger :) PS:你得到一个使用调试器的cookie :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM