为什么不能在GNU C基本内联asm语句中使用局部变量? [英] Why can't local variable be used in GNU C basic inline asm statements?

本文介绍了为什么不能在GNU C基本内联asm语句中使用局部变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!



Why cannot I use local variables from main to be used in basic asm inline? It is only allowed in extended asm, but why so?


(I know local variables are on the stack after return address (and therefore cannot be used once the function return), but that should not be the reason to not use them)


int a = 10; //global a
int b = 20; //global b
int result;
int main()
 asm ( "pusha\n\t"
 "movl a, %eax\n\t"
 "movl b, %ebx\n\t"
 "imull %ebx, %eax\n\t"
 "movl %eax, result\n\t"
printf("the answer is %d\n", result);
return 0;


int main (void) {

    int data1 = 10;  //local var - could be used in extended
    int data2 = 20;
    int result;

    asm ("imull %%edx, %%ecx\n\t"
          "movl %%ecx, %%eax" 
          : "=a"(result)
          : "d"(data1), "c"(data2));

    printf("The result is %d\n",result);

    return 0;

编译: gcc -m32 somefile.c

平台: uname -a: Linux 5.0.0-32-generic #34-Ubuntu SMP Wed Oct 2 02:06:48 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux


基本asm"和扩展asm"之间几乎没有区别; 基本汇编"只是一个特殊情况,其中__asm__语句没有输出,输入或修饰符的列表.编译器不会在Basic asm的汇编字符串中执行%替换.如果需要输入或输出,则必须指定它们,这就是人们所说的扩展的asm".

There is little distinction between "Basic asm" and "Extended asm"; "basic asm" is just a special case where the __asm__ statement has no lists of outputs, inputs, or clobbers. The compiler does not do % substitution in the assembly string for Basic asm. If you want inputs or outputs you have to specify them, and then it's what people call "extended asm".


In practice, it may be possible to access external (or even file-scope static) objects from "basic asm". This is because these objects will (respectively may) have symbol names at the assembly level. However, to perform such access you need to be careful of whether it is position-independent (if your code will be linked into libraries or PIE executables) and meets other ABI constraints that might be imposed at linking time, and there are various considerations for compatibility with link-time optimization and other transformations the compiler may perform. In short, it's a bad idea because you can't tell the compiler that a basic asm statement modified memory. There's no way to make it safe.

"memory" Clobber(扩展的asm)可以使从asm模板中按名称访问静态存储变量变得安全.

A "memory" clobber (Extended asm) can make it safe to access static-storage variables by name from the asm template.

基本asm的用例是仅修改机器状态的事物,例如内核中的asm("cli")以禁用中断,而无需读取或写入任何C变量. (即使那样,您也经常使用内存"缓冲区来确保编译器在更改计算机状态之前已经完成了较早的内存操作.)

The use-case for basic asm is things that modify the machine state only, like asm("cli") in a kernel to disable interrupts, without reading or writing any C variables. (Even then, you'd often use a "memory" clobber to make sure the compiler had finished earlier memory operations before changing machine state.)


Local (automatic storage, not static ones) variables fundamentally never have symbol names, because they don't exist in a single instance; there's one object per live instance of the block they're declared in, at runtime. As such, the only possible way to access them is via input/output constraints.

来自MSVC领域的用户可能会感到惊讶,因为MSVC的内联汇编方案通过将内联asm版本中的局部变量引用转换为相对于堆栈指针的访问来解决了该问题.但是,它提供的内联汇编版本与优化编译器不兼容,并且使用该类内联汇编的函数几乎没有优化可以进行. GCC和与Unix一起与C一起成长的更大的编译器世界没有任何相似之处.

Users coming from MSVC-land may find this surprising since MSVC's inline assembly scheme papers over the issue by transforming local variable references in their version of inline asm into stack-pointer-relative accesses, among other things. The version of inline asm it offers however is not compatible with an optimizing compiler, and little to no optimization can happen in functions using that type of inline asm. GCC and the larger compiler world that grew alongside C out of unix does not do anything similar.

这篇关于为什么不能在GNU C基本内联asm语句中使用局部变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

登录 关闭
发送“验证码”获取 | 15天全站免登陆