Meh*_*dad 9 c gcc inline-assembly visual-c++
我不明白这是怎么回事.
GCC内联汇编程序很难做到,但是对于标记符号信息非常具体,因此编译器知道你正在做什么.
Microsoft Visual C++的inline assember非常容易使用(它似乎总是Just Work),但我不知道它对你的代码有什么样的保证或假设.
VC++是否试图"自动检测"哪些寄存器被破坏?它如何知道如何更改寄存器和堆栈指针?它做出任何假设吗?如果是这样,你如何解决这些假设?
Kaz*_*Kaz 20
至于为什么海湾合作委员会不像MSVC那样做,有几个原因:
GCC是一个可重定向的编译器,但汇编语法只是原始文本.为了使clobber检测自动化,GCC必须解析汇编语言以了解哪些寄存器被破坏(包括由操作码未命名寄存器的指令隐式破坏的寄存器).这必须适用于所有架构.目前,GCC不解析汇编语言; 在执行%替换后,它只是将其粘贴到程序集输出中.我们的想法是生成并避免解析.
在GCC内联汇编语言中,clobbering寄存器是例外而不是规则.原因是它是一种比MSVC更复杂的语言.GCC的内联汇编语言为您分配寄存器.所以你通常不会%eax直接使用类似的东西,而是使用%0GCC代替可用寄存器的代码.(要做到这一点,编译器不必理解汇编语言!你表达了约束,这些约束确保GCC替换%0适合使用的适当寄存器.) 如果你的汇编代码被覆盖硬编码你只需要clobber寄存器,而不是它是否覆盖GCC为您分配的输出操作数.
请注意,使用GCC内联汇编时,您不必编写从生成其初始值的C表达式加载汇编语言操作数的代码,也不必将结果操作数存储到C目标中.例如,您只是表示存在类型"r"(寄存器)的输入操作数,该操作数是从表达式派生的foo->bar + 1.GCC分配寄存器并生成代码以从中加载foo->bar + 1,然后使用%0该寄存器的名称替换汇编模板中的出现.
从文档引用:
使用__asm在C / C ++函数中编写汇编语言时,无需保留EAX,EBX,ECX,EDX,ESI或EDI寄存器。例如,在使用内联汇编编写函数的POWER2.C示例中,power2函数未将值保留在EAX寄存器中。但是,使用这些寄存器将影响代码质量,因为寄存器分配器无法使用它们在__asm块之间存储值。此外,通过在内联汇编代码中使用EBX,ESI或EDI,您可以强制编译器在函数序言和结语中保存和恢复这些寄存器。
您应将其他使用的寄存器(例如DS,SS,SP,BP和标志寄存器)保留在__asm块的范围内。您应该保留ESP和EBP寄存器,除非您出于某种原因需要更改它们(例如,切换堆栈)。另请参阅优化内联汇编。