gby*_*gby 5 c gcc gnu-assembler ld
我有一个内联函数定义,它包装了一个内联程序集。我希望根据参数在构建时是否已知的事实来选择不同的内联汇编实现。
我的问题是如何在 C 代码或内联汇编中询问地址值在构建时是否已知,因此适合作为立即值。如果您正在考虑 __builtin_constant_p - 请继续阅读。
这是一些说明我的意图的代码:我正在尝试找到一种方法来实现“is_immediate”。
static char arr[5];
void __attribute__((always_inline)) do_something(char * buf)
{
if(is_immediate(buf) {
// Argument is constant, can use immediate form
asm volatile ("insn1 %0" : : "i"(buf));
} else {
// Argument is computed at runtime, use a register
unsigned long tmp = (unsigned long)buf + 1;
asm volatile("insn2 %0" : : "r"(tmp));
}
int main(void)
{
do_something(&arr);
}
Run Code Online (Sandbox Code Playgroud)
乍一看,__builtin_constant_p() 似乎正是所需的魔法,但它不起作用。
不起作用的原因是,虽然在链接器将数组放入内存并为其选择地址后就知道数组的地址(因此它确实符合内联汇编的直接约束),但它不是在链接之前的编译时已知。
因此,我正在寻找一种方法来询问“这个变量是否适合作为立即值?” 而不是“这是一个常量表达式吗?”。
如果我看一下我的 x86 编译器生成的内容(这个 insn 毕竟没有意义),它就在这里:
static char arr[5];
void __attribute__((always_inline)) do_something(char * buf)
{
// Argument is constant, can use immediate form
asm volatile ("insn1 %0" : : "r"(buf));
unsigned long tmp = (unsigned long)buf;
asm volatile("insn2 %0" : : "r"(tmp));
}
int main(void)
{
char brr[5];
do_something(arr);
do_something(brr);
}
Run Code Online (Sandbox Code Playgroud)
来到
.file "inl.c"
.text
.globl do_something
.type do_something, @function
do_something:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax
#APP
# 8 "inl.c" 1
insn1 %eax
# 0 "" 2
# 12 "inl.c" 1
insn2 %eax
# 0 "" 2
#NO_APP
popl %ebp
ret
.size do_something, .-do_something
.globl main
.type main, @function
main:
pushl %ebp
movl $arr, %eax
movl %esp, %ebp
subl $16, %esp
#APP
# 8 "inl.c" 1
insn1 %eax
# 0 "" 2
# 12 "inl.c" 1
insn2 %eax
# 0 "" 2
#NO_APP
leal -5(%ebp), %eax
#APP
# 8 "inl.c" 1
insn1 %eax
# 0 "" 2
# 12 "inl.c" 1
insn2 %eax
# 0 "" 2
#NO_APP
leave
ret
.size main, .-main
.local arr
.comm arr,5,4
.ident "GCC: (SUSE Linux) 4.5.1 20101208 [gcc-4_5-branch revision 167585]"
.section .comment.SUSE.OPTs,"MS",@progbits,1
.string "OSpwg"
.section .note.GNU-stack,"",@progbits
Run Code Online (Sandbox Code Playgroud)
所以我认为立即采取可能是有意义的,因为$arr可能是立即的(而leal -5(%ebp), %eax不是)。可能只是不支持上述优化。
但另一方面,
movl $arr, %eax
insn1 %eax
Run Code Online (Sandbox Code Playgroud)
并不比
insn1 $arr
Run Code Online (Sandbox Code Playgroud)
所以它仍然是可以接受的,恕我直言。