LinuxQuestions.org
Support LQ: Use code LQ3 and save $3 on Domain Registration
Go Back   LinuxQuestions.org > Blogs > rainbowsally
User Name
Password

Notices

Rate this Entry

ASM: 64 bit intel asm in linux

Posted 02-03-2012 at 04:01 PM by rainbowsally

If you're used to 32 bit asm in gcc, the 64 bit asm might throw you for a loop initially. That's because part of the stack is passed around in registers.

Let's compile a bit of test code and see what's going on.

If you're using our makefile-creator put this in a subdirectory named "src" or use whatever method you prefer if not.

file: src/main.c
Code:
// main.c
#include <stdio.h>

void  dbg(){}

// macros to define an asm function
#define __L(name) \
  ".text;\n" \
  ".globl "#name";\n" \
  ".type " #name", @function;\n" \
  ""#name":"

#define FUNCTION(name) \
  asm( \
  ".text;\n" \
  ".align 4\n" \
  __L(name) \
  ); \
  asm

// iterative tester, first test (long a), then (long a, long b) and so forth
// to see the pattern using a debugger or using 'objdump -d asm64-test'.
long c_test(long a, long b, long c, long d, long e, long f, long g, long h)
{
  return g;  // offset 0x10 from ebp = offset 8 in asm code below
}


long rval;

long asm_test(long a, long b, long c, long d, long e, long f, long g, long h);

void asm_section()
{
  FUNCTION(asm_test)
  (
      "movq 8(%rsp), %rax;\n" // get first item above the return address off the stack
      "movq %rax, rval(%rip)\n;"
      "ret;\n"
  );
}
 
int main(int argc, char** argv)
{
  dbg();
  //  test code ------->
  // rdi = 1, rsi = 2,  rdx = 3, rcx = 4, r8 = 5, r9 = 6, 
  
  long n1 = c_test(1, 2, 3, 4, 5, 6, 7, 8);
  printf("C test  : first item on machine stack is #%d in (1,2,3,4,5,6,7,8)\n", n1);
  
  long n2 = asm_test(1,2,3,4,5,6,7, 8);
  printf("ASM test: first item on machine stack is #%d in (1,2,3,4,5,6,7,8)\n", n2);
  // <------- test code
  return 0;
}
To name the output file 'asm64-test' using our makefile generator:
Code:
makefile-creator asm64-test
edit Makefile # and change the -m32 switches to -m64
make
Whatever way you do this, with or without debug symbols, or optimization, run the test code as
Code:
asm64-test
And verify that both test outputs are the same verifying that that the 7th parameter is the first one actually pushed onto the machine stack.

By iteratively* adding parameters to a standard C call we can determine that the parameters that are not on the machine stack are in registers in the
following order:
Code:
rdi = 1, rsi = 2,  rdx = 3, rcx = 4, r8 = 5, r9 = 6
so that the first item on the stack is in rdi, the second is in rsi, and so forth up to 6 stacked values before the actual machine stack is involved at all.

Other than that 64 bit asm pretty much follows the same conventions as 32 bit asm except for the 'q' suffix for quads replacing the 'l' suffix for dwords when needed and variables (like rval above) being addressed relativeto rip).

If you need more clues it's easy to write a simple C file and add the '--save-temps' flag to the CFLAGS line to get the intermediate asm file (*.s) from the compiler.

Note: if you need the intel syntax, take a quick peek at earlier asm blog entries.

--------
* Iteratively adding parameters to the list is easier than trying to save registers to variables and picking them up in C for display. At least it is for me. :-)
Posted in Uncategorized
Views 1007 Comments 0
« Prev     Main     Next »
Total Comments 0

Comments

 

  



All times are GMT -5. The time now is 10:28 AM.

Main Menu
Advertisement

My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration