我想在使用g ++的C ++程序中使用naked function。不幸的是,与VC ++不同,g ++不支持裸函数,管理它的唯一方法是在单独的文件中编写自己的汇编代码并与C ++文件链接。我试图找到一些很好的x86教程来混合汇编和C / C ++文件,但找不到任何好的。
如果您了解任何问题,请告诉我。请注意,除了在C或程序集中使用它们之外,我不是要求内联汇编而是链接C和汇编文件以及在汇编中声明C的外部变量的方法,反之亦然,以及使用Makefile链接C和asm文件的方法
答案 0 :(得分:17)
在C ++文件中:
extern "C" void foo(); // Stop name mangling games
int main() {
foo();
}
在“裸”的asm文件中,对于x86:
# modified from http://asm.sourceforge.net/howto/hello.html
.text # section declaration
.global foo
foo:
# write our string to stdout
movl $len,%edx # third argument: message length
movl $msg,%ecx # second argument: pointer to message to write
movl $1,%ebx # first argument: file handle (stdout)
movl $4,%eax # system call number (sys_write)
int $0x80 # call kernel
# and exit
movl $0,%ebx # first argument: exit code
movl $1,%eax # system call number (sys_exit)
int $0x80 # call kernel
.data # section declaration
msg:
.ascii "Hello, world!\n" # our dear string
len = . - msg # length of our dear string
编译,汇编和链接(用g ++而不是ld,因为用C ++这样做更容易)并运行:
ajw@rapunzel:/tmp > g++ -Wall -Wextra test.cc -c -o test.o
ajw@rapunzel:/tmp > as -o asm.o asm.S
ajw@rapunzel:/tmp > g++ test.o asm.o
ajw@rapunzel:/tmp > ./a.out
Hello, world!
如果要将参数传递给函数或返回任何需要遵守调用约定的内容。
答案 1 :(得分:5)
这是一个实现“裸体功能”效果的技巧示例。
#include <stdio.h>
extern "C" int naked_func ();
static void
dummy ()
{
__asm__ __volatile__
(
" .global naked_func\n"
"naked_func:\n"
" movq $3141569, %rax\n"
" ret\n"
);
}
int
main ()
{
printf ("%d\n", naked_func ());
return 0;
}
答案 2 :(得分:1)
我只想在上一篇文章中添加一件事。 想象一下,你想要一个接受参数的函数: (像
int add(int,int);
原型)
segment .text
global add
add:
enter 0,0
mov eax,[ebp+8] ; first argument
mov ebx,[ebp+12] ; second argument
add eax,ebx
leave
ret
答案 3 :(得分:0)
这是我在程序集中定义函数的方法,这不需要有一个单独的汇编程序文件,也不需要转义每个换行符。您只需将程序集文件的内容复制到string-literal即可。 注意: raw multiline string literal是C ++ 11的一项功能(您还标记了C ++)。如果您想在一个.c
- / .cpp
文件中编译所有内容,这很有用。
extern"C" int rand_byte(void);
asm (R"(
.globl rand_byte
rand_byte:
call rand
and eax, 255
ret
)");
您只能在全局范围内使用没有其他参数的基本程序集语句。
使用GCC或Clang和arm处理器时,您可以使用[[gnu::naked]]
/ __attribute__((naked))
。
[[gnu::naked]]
int rand_byte(void) {
asm volatile (R"(
push {lr}
bl rand
and r0, #255
pop {pc}
)");
};
第一种方法总是允许定义裸功能。 这也有助于制作更多可移植的代码。
extern"C" int _cdecl rand_byte(void);
#if defined __x86__
// NOTE: the names are decorated with a '_' on windows 32-bit
// You can use extern"C" int _cdecl rand_byte() asm("rand_byte");
// to make the asm symbol name always be rand_byte, without an _
asm volatile (R"(
.globl _rand_byte
_rand_byte:
call rand
and eax, 255
ret
)");
#elif defined __x86_64__
asm volatile (R"(
.globl rand_byte
rand_byte:
call rand
and rax, 255 # eax works here, too. x86-32 and -64 could share the same source.
ret
)");
#elif defined __arm__
asm (R"(
.global rand_byte
rand_byte:
push {lr}
bl rand
and r0, #255
pop {pc}
)");
#else
#error There is no code for your platform yet...
#endif