2

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). 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):

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:

(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/).

Thanks!

3
  • 1
    Arguments aren't on the stack in the x86-64 ABI. Commented Jun 4, 2016 at 23:07
  • qwords are 8bytes and not 4, so change this movq 8(%rbp), %rdi to movq 16(rbp) (same thing with the next line) and you could use the registers for arguments, it is required for syscalls to use the x86-64-abi. Commented Jun 4, 2016 at 23:14
  • Why first parameter is 16($rbp) and not 8($rbp)? shows an example with 10 integer args, so the last 4 actually are on the stack. (Unlike here where you've invented your own calling conventions that uses stack-args even for the first 2 args) Commented Jan 4, 2021 at 13:12

1 Answer 1

7

The standard 64 bit conventions don't use the stack like that, they pass at least the first few arguments (type permitting) in registers. 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.

subq $4, %rsp

You should really use multiples of 8 unless you know what you are doing.

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. So at 0(%rbp) you have the pushed rbp, and 8(%rbp) is the return address. Thus 16(%rbp) is the first argument and 24(%rbp) is the second.

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.

PS: You get a cookie for using a debugger :)

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.