This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: How can I do calling for external address in my "C" programm by inline GAS?
Joe Abbey wrote:
> Presuming you're building this for Linux, I highly recommend you read the
> 64-bit ABI.
>
> http://www.x86-64.org/documentation/abi.pdf
>
> Chapter 3 is your friend. There's a lot of details there, hand-rolling
> 64-bit assembly is more complicated than 32-bit. There are things like
> red-zone, which you're writing into with the pushq. And since you probably
> won't read the ABI, here's fixed source:
>
> #include <stdio.h>
>
> int main(){
>
> void *p_printf = (void *)&printf;
> const char *str = "Hello\n";
>
> printf("addr of printf=%p\n", &printf); // 0x400490
>
> asm ("movq %0, %%rdi;" /* str into RDI */
> "leaq (, %1), %%rcx;" /* address of PRINTF into RCX */
> "call * %%rcx;" /* call PRINTF */
>
> : /* output */
> :
> :"r"(str),"r"(p_printf) /* input */
> :
> : "rdi", "rcx"
>
> );
>
> return 0;
> }
>
> Nota Bene: The Windows 64-bit ABI is completely different, so while this
> source may compile and work on Linux... it will not work for Windows.
>
> Cheers,
>
> Joe
Hi Joe!
Thank you for link on documentation of abi amd64.
Could you explain me, what I'm doing wrong now, maybe my cpu is broken ?:
++++++++++++++++++++++++++++++++++++++++++++++++++
user@localhost ~/ $ gdb ./call64
GNU gdb (Gentoo 7.3.1 p2) 7.3.1
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-pc-linux-gnu".
For bug reporting instructions, please see:
<http://bugs.gentoo.org/>...
Reading symbols from /home/user/call64...done.
(gdb) list 1,27
1 #include <stdio.h>
2
3 static void *p_printf = (void *)&printf;
4 static const char *str = "Hello\n";
5
6 void exec_printf(){
7 asm volatile (
8 "movq %0, %%rcx;" /* str into RCX is first integer argument (amd64
notation) */
9 "movq %1, %%rdi;" /* address of PRINTF into RDI is Must be
preserved by called function (amd64 notation) */
10 "call * %%rdi;" /* call PRINTF */
11 : /* no output */
12 :"r"(str),"r"(p_printf) /* input */
13 : "rcx", "rdi", "memory" /* clobbered register */
14 );
15 }
16
17 // gcc -g -m64 call64.c -o call64 && ./call64
18 int main(){
19
20 printf("\n[addr of printf: %p]\n", &printf); // 0x400438
21 printf("[addr of str: %p]\n", str); // 0x40069c
22
23 exec_printf();
24
25 return 0;
26 }
(gdb) display/x $rcx, $rdi
(gdb) run
Starting program: /home/user/call64
[addr of printf: 0x400438]
[addr of str: 0x40069c]
Program received signal SIGSEGV, Segmentation fault.
0x00000000004005a7 in main () at call64.c:26
26 }
1: /x $rcx, $rdi = 0x400438
(gdb) disas exec_printf
Dump of assembler code for function exec_printf:
0x0000000000400544 <+0>: push %rbp
0x0000000000400545 <+1>: mov %rsp,%rbp
0x0000000000400548 <+4>: mov 0x200ad9(%rip),%rax # 0x601028
<str>
0x000000000040054f <+11>: mov 0x200aca(%rip),%rdx # 0x601020
<p_printf>
0x0000000000400556 <+18>: mov %rax,%rcx
0x0000000000400559 <+21>: mov %rdx,%rdi
0x000000000040055c <+24>: callq *%rdi
0x000000000040055e <+26>: leaveq
0x000000000040055f <+27>: retq
End of assembler dump.
++++++++++++++++++++++++++++++++++++++++++++++++++
--
The best Regards.