我正在尝试使用 ICC 2018 编译以下代码:
__asm {
mov ebx, xx ;xx address to registers
}
其中 xx 是 int16 类型。这是我的函数中的第一条指令。
我使用上面的汇编代码收到以下警告:
警告 #13212:在需要堆栈对齐的函数中引用 ebx
令人惊讶的是,当我用 eax 或 esi 替换 ebx 时,我看到警告消失了。我不明白为什么我只看到 ebx 的问题,据我所知,ebx 和 eax 都具有相同的架构(32 位寄存器)。
另外,当我用 ICC 2013 编译相同的代码时,我没有看到警告。
谁能帮我解决这个警告?
谢谢!
最佳答案
如果需要额外对齐,所选平台上的编译器(ICC,因为它模仿 MSVC 的行为)使用 EBX 来保存原始堆栈指针值。因此,您无法安全地覆盖它。
程序的行为将变得不确定。编译器警告只是告诉你这一点。
为了帮助保存/恢复受汇编 block 影响的所有寄存器,建议使用具有所谓的 clobber 列表的扩展语法。您的示例使用 MSVC 样式 __asm{...}
句法。在 MSVC 风格的语法中,编译器检测您接触的寄存器并为您保存/恢复它们。
ICC 还支持类似 GCC 的表示法,用于扩展 asm 和 clobber 列表:asm("...":::)
.它还支持更简单的 GCC asm("...")
没有clobber列表部分。看到这个 question了解更多详情(感谢 Peter Cordes 的链接和解释)。
我在学习使用 clobber 列表时发现有用的文档(我实际上一直在使用它,因为不可能记住它对人类不友好的语法):
没有 clobber 列表的简单内联汇编 block 只能在以下情况下安全使用:
INT3
, HLT
, WRMSR
etc 指令要么不接触寄存器,要么只影响编译器不使用的系统寄存器。但是,大多数此类指令是特权指令,不能在用户应用程序中使用。还可以读取所有可用的寄存器,前提是此类读取没有副作用。 register asm
做到这一点语句(不记得相同的技巧是否适用于其他编译器)。因此,您可以声明一个变量绑定(bind)到某个寄存器。请注意,这种技术会减少编译器在其寄存器分配阶段可用的寄存器数量,这会降低其生成的代码质量。请求过多的寄存器,编译器会束手无策,拒绝工作。类似地,不能要求从编译器中删除具有专用角色的寄存器,例如堆栈指针或程序计数器。 也就是说,扩展
asm
使用 clobber 列表的语法提供了一个不错的选择。它变成了 asm
从黑盒到内联内部“函数”的部分,该函数声明了自己的输入、输出和资源,它覆盖了与外部函数共享的资源。
关于c++ - 警告 #13212 : Reference to ebx in function requiring stack alignment,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49023844/