_start 可以是拇指函数(在 Linux 用户程序中)吗?
是的,它可以。这些步骤并不像您想象的那么简单。
请.code 16
按照其他人的描述使用。另请查看ARM Script 谓词;我的回答显示了如何检测拇指二进制文件。入口符号必须具有传统_start+1
值,否则 Linux 将决定以_start
ARM模式调用您。
您的代码也试图模仿,
int main(void) { return 2; }
该_start
符号不得这样做(根据auselen)。要在ARM_start
模式下执行操作,您需要,main()
#include <linux/unistd.h>
static inline void exit(int status)
{
asm volatile ("mov r0, %0\n\t"
"mov r7, %1\n\t"
"swi #7\n\t"
: : "r" (status),
"Ir" (__NR_exit)
: "r0", "r7");
}
/* Wrapper for main return code. */
void __attribute__ ((unused)) estart (int argc, char*argv[])
{
int rval = main(argc,argv);
exit(rval);
}
/* Setup arguments for estart [like main()]. */
void __attribute__ ((naked)) _start (void)
{
asm(" sub lr, lr, lr\n" /* Clear the link register. */
" ldr r0, [sp]\n" /* Get argc... */
" add r1, sp, #4\n" /* ... and argv ... */
" b estart\n" /* Let's go! */
);
}
最好清除lr
以便堆栈跟踪将终止。如果你愿意,你可以避免argc
和argv
处理。start
展示了如何使用它。这estart
只是将main()
返回代码转换为exit()
调用的包装器。
您需要将上述汇编程序转换为Thumb等效项。我建议使用gcc inline assembler。如果内联可以工作,则可以转换为纯汇编源代码。但是,在“C”源代码中执行此操作可能更实用,除非您尝试制作一个非常小的可执行文件。
有用的gcc争论是,
-nostartfiles -static -nostdlib -isystem <path to linux user headers>
添加-mthumb
,您应该有一个用于任何一种模式的线束。