问题 在C中使用标签


我只需要一种方法来加载标签的地址,例如MyLabel:例如'src.asm'变为例如变量'src.c'。 (这些文件将链接在一起)我使用gcc和nasm来组装这些文件。如何加载标签地址?


10366
2017-11-08 01:57


起源



答案:


这有两个步骤。首先,必须使用。将程序集文件中的标签导出为全局 global 指示。

global MyLabel

MyLabel: dd 1234    ; data or code, in whatever section.  It doesn't matter.

接下来,您必须在C中将标签声明为外部。您可以在使用它的代码中或在标头中执行此操作。

// It doesn't matter, and can be plain void,
// but prefer giving it a C type that matches what you put there with asm
extern void MyLabel(void);            // The label is code, even if not actually a function
extern const uint32_t MyLabel[];      // The label is data
// *not*  extern long *MyLabel, unless the memory at MyLabel *holds* a pointer.

最后,您获得C中标签的地址的方式与获取任何变量的地址的方式相同。

doSomethingWith( &MyLabel );

请注意,某些编译器会在C变量和函数名称的开头添加下划线。例如,GCC在Mac OS X上执行此操作,但不在Linux上执行此操作。我不知道其他平台/编译器。为了安全起见,您可以添加一个 asm 声明变量声明告诉GCC变量的汇编名称是什么。

extern uint8_t MyLabel asm("MyLabel");

16
2017-11-08 02:12



我认为这种方式更可取(如果它确实是提问者想要的),因为它只是使标签在链接器级别可见,并使用原始C代码来访问它,就像任何其他符号一样。不需要内联asm。 (我注意到下划线错位问题; #ifdef检查是否是使用正确名称的更好方法?) - Edmund
我认为 void * 可能是你能给它的最危险的类型(因为它很容易忘记 &)。该 char 通常选择类型为任意符号,但是 void 也应该工作。 - Dietrich Epp
如果是的话 char,至少你在分配它时会遇到类型错误(因为你不能分配 char 指针),但有 void * 您可以将其分配给任何指针类型而无需强制转换。 - Dietrich Epp
@ughoavgfhw:从测试来看,似乎是这样 clang 会发出警告 &symbol 如果 symbol 被宣布为 extern void symbol;  - 不是为了声明,而是因为你不能取类型表达式的地址 void。这只发生在 -pedantic,无论我通过什么标志,我都无法让GCC发出任何警告或错误消息。 (这是相当切合的,但......) - Dietrich Epp
我发现了类似的东西,我最终做到了 extern void MyLabel(); - Kendall Frey


答案:


这有两个步骤。首先,必须使用。将程序集文件中的标签导出为全局 global 指示。

global MyLabel

MyLabel: dd 1234    ; data or code, in whatever section.  It doesn't matter.

接下来,您必须在C中将标签声明为外部。您可以在使用它的代码中或在标头中执行此操作。

// It doesn't matter, and can be plain void,
// but prefer giving it a C type that matches what you put there with asm
extern void MyLabel(void);            // The label is code, even if not actually a function
extern const uint32_t MyLabel[];      // The label is data
// *not*  extern long *MyLabel, unless the memory at MyLabel *holds* a pointer.

最后,您获得C中标签的地址的方式与获取任何变量的地址的方式相同。

doSomethingWith( &MyLabel );

请注意,某些编译器会在C变量和函数名称的开头添加下划线。例如,GCC在Mac OS X上执行此操作,但不在Linux上执行此操作。我不知道其他平台/编译器。为了安全起见,您可以添加一个 asm 声明变量声明告诉GCC变量的汇编名称是什么。

extern uint8_t MyLabel asm("MyLabel");

16
2017-11-08 02:12



我认为这种方式更可取(如果它确实是提问者想要的),因为它只是使标签在链接器级别可见,并使用原始C代码来访问它,就像任何其他符号一样。不需要内联asm。 (我注意到下划线错位问题; #ifdef检查是否是使用正确名称的更好方法?) - Edmund
我认为 void * 可能是你能给它的最危险的类型(因为它很容易忘记 &)。该 char 通常选择类型为任意符号,但是 void 也应该工作。 - Dietrich Epp
如果是的话 char,至少你在分配它时会遇到类型错误(因为你不能分配 char 指针),但有 void * 您可以将其分配给任何指针类型而无需强制转换。 - Dietrich Epp
@ughoavgfhw:从测试来看,似乎是这样 clang 会发出警告 &symbol 如果 symbol 被宣布为 extern void symbol;  - 不是为了声明,而是因为你不能取类型表达式的地址 void。这只发生在 -pedantic,无论我通过什么标志,我都无法让GCC发出任何警告或错误消息。 (这是相当切合的,但......) - Dietrich Epp
我发现了类似的东西,我最终做到了 extern void MyLabel(); - Kendall Frey


您可能会考虑汇编程序“getter”例程。

此外,您可以简单地伪造标签,使其看起来像C活页夹的例程,以便您可以获取“过程”的地址。


0
2017-11-08 02:06