- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个 CpuFeatures
类。该类的要求很简单:(1) 保留EBX
或RBX
,(2) 记录从CPUID
返回的值到EAX/EBX/ECX/EDX
。我不确定生成的代码是否是我想要的代码。
CpuFeatures
类代码使用 GCC Extended ASM。这是相关代码:
struct CPUIDinfo
{
word32 EAX;
word32 EBX;
word32 ECX;
word32 EDX;
};
bool CpuId(word32 func, word32 subfunc, CPUIDinfo& info)
{
uintptr_t scratch;
__asm__ __volatile__ (
".att_syntax \n"
#if defined(__x86_64__)
"\t xchgq %%rbx, %q1 \n"
#else
"\t xchgl %%ebx, %k1 \n"
#endif
"\t cpuid \n"
#if defined(__x86_64__)
"\t xchgq %%rbx, %q1 \n"
#else
"\t xchgl %%ebx, %k1 \n"
#endif
: "=a"(info.EAX), "=&r"(scratch), "=c"(info.ECX), "=d"(info.EDX)
: "a"(func), "c"(subfunc)
);
if(func == 0)
return !!info.EAX;
return true;
}
下面的代码是在 Cygwin i386 上用 -g3 -Og
编译的。当我在调试器下检查它时,我不喜欢我所看到的。
Dump of assembler code for function CpuFeatures::DoDetectX86Features():
...
0x0048f355 <+1>: sub $0x48,%esp
=> 0x0048f358 <+4>: mov $0x0,%ecx
0x0048f35d <+9>: mov %ecx,%eax
0x0048f35f <+11>: xchg %ebx,%ebx
0x0048f361 <+13>: cpuid
0x0048f363 <+15>: xchg %ebx,%ebx
0x0048f365 <+17>: mov %eax,0x10(%esp)
0x0048f369 <+21>: mov %ecx,0x18(%esp)
0x0048f36d <+25>: mov %edx,0x1c(%esp)
0x0048f371 <+29>: mov %ebx,0x14(%esp)
0x0048f375 <+33>: test %eax,%eax
...
我不喜欢我所看到的,因为看起来 EBX/RBX
没有被保留(xchg %ebx,%ebx
在 +11
)。此外,看起来保留的 EBX/RBX
被保存为 CPUID
的结果,而不是 EBX
返回的实际值 CPUID
(xchg %ebx,%ebx
在 +15
,在 mov %ebx,0x14(%esp)
之前在 +29
)。
如果我将操作数更改为使用带有 "=&m"(scratch)
的内存操作,则生成的代码为:
0x0048f35e <+10>: xchg %ebx,0x40(%esp)
0x0048f362 <+14>: cpuid
0x0048f364 <+16>: xchg %ebx,0x40(%esp)
一个相关的问题是What ensures reads/writes of operands occurs at desired times with extended ASM?
我做错了什么(除了在本应花费 5 或 15 分钟的事情上浪费了无数时间)?
最佳答案
下面的代码是一个完整的示例,我用它来编译您上面的示例代码,包括直接对 info.EBX
变量进行交换(交换)的修改。
#include <inttypes.h>
#define word32 uint32_t
struct CPUIDinfo
{
word32 EAX;
word32 EBX;
word32 ECX;
word32 EDX;
};
bool CpuId(word32 func, word32 subfunc, CPUIDinfo& info)
{
__asm__ __volatile__ (
".att_syntax \n"
#if defined(__x86_64__)
"\t xchgq %%rbx, %q1 \n"
#else
"\t xchgl %%ebx, %k1 \n"
#endif
"\t cpuid \n"
#if defined(__x86_64__)
"\t xchgq %%rbx, %q1 \n"
#else
"\t xchgl %%ebx, %k1 \n"
#endif
: "=a"(info.EAX), "=&m"(info.EBX), "=c"(info.ECX), "=d"(info.EDX)
: "a"(func), "c"(subfunc)
);
if(func == 0)
return !!info.EAX;
return true;
}
int main()
{
CPUIDinfo cpuInfo;
CpuId(1, 0, cpuInfo);
}
您应该做的第一个观察是我选择使用 info.EBX 内存位置来进行实际交换。这消除了对另一个临时变量或寄存器的需要。
我用 -g3 -Og -S -m32
组装成 32 位代码,得到了这些感兴趣的指令:
xchgl %ebx, 4(%edi)
cpuid
xchgl %ebx, 4(%edi)
movl %eax, (%edi)
movl %ecx, 8(%edi)
movl %edx, 12(%edi)
%edi
恰好包含 info
结构的地址。 4(%edi)
恰好是info.EBX
的地址。我们在 cpuid
之后交换 %ebx
和 4(%edi)
。通过该指令,ebx
恢复到 cpuid
之前的状态,4(%edi)
现在具有 ebx
的状态就在 cpuid
被执行之后。剩余的 movl
行将 eax
、ecx
、edx
寄存器放入剩余的 info
结构通过 %edi
寄存器。
上面生成的代码是我所期望的。
带有 scratch
变量(并使用约束 "=&m"(scratch)
)的代码永远不会在汇编器模板之后使用,所以 %ebx, 0x40(%esp)
具有您想要的值,但它永远不会移动到任何有用的地方。您必须将 scratch
变量复制到 info.EBX
(即 info.EBX = scratch;
)并查看所有生成的结果指令。在某些时候,数据将从 scratch
内存位置复制到生成的汇编指令中的 info.EBX
。
更新 - Cygwin 和 MinGW
我对 Cygwin 代码输出的正确性并不完全满意。半夜我有一个啊哈!片刻。当动态链接加载程序加载图像(DLL 等)并通过重新定位修改图像时,Windows 已经执行了自己的位置独立代码。不需要像在 Linux 32 位共享库中那样进行额外的 PIC 处理,因此 ebx
/rbx
没有问题。这就是为什么Cygwin和MinGW在用-fPIC
warning: -fPIC ignored for target (all code is position independent)
这是因为在 Windows 下,所有 32 位代码在被 Windows 动态加载器加载时都可以重新基址。可以在这个 Dr. Dobbs article 中找到有关重新定位的更多信息.有关 Windows 可移植可执行格式 (PE) 的信息可以在此 Wiki article 中找到. Cygwin 和 MinGW 不需要担心在针对 32 位代码时保留 ebx
/rbx
因为在他们的平台上 PIC 已经由操作系统处理,其他 re-based 工具,和链接器。
关于c++ - 生成的代码与扩展 ASM 的预期不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32131003/
我尝试理解[c代码 -> 汇编]代码 void node::Check( data & _data1, vector& _data2) { -> push ebp -> mov ebp,esp ->
我需要在当前表单(代码)的上下文中运行文本文件中的代码。其中一项要求是让代码创建新控件并将其添加到当前窗体。 例如,在Form1.cs中: using System.Windows.Forms; ..
我有此 C++ 代码并将其转换为 C# (.net Framework 4) 代码。有没有人给我一些关于 malloc、free 和 sprintf 方法的提示? int monate = ee; d
我的网络服务器代码有问题 #include #include #include #include #include #include #include int
给定以下 html 代码,将列表中的第三个元素(即“美丽”一词)以斜体显示的 CSS 代码是什么?当然,我可以给这个元素一个 id 或一个 class,但 html 代码必须保持不变。谢谢
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
我试图制作一个宏来避免重复代码和注释。 我试过这个: #define GrowOnPage(any Page, any Component) Component.Width := Page.Surfa
我正在尝试将我的旧 C++ 代码“翻译”成头条新闻所暗示的 C# 代码。问题是我是 C# 中的新手,并不是所有的东西都像 C++ 中那样。在 C++ 中这些解决方案运行良好,但在 C# 中只是不能。我
在 Windows 10 上工作,R 语言的格式化程序似乎没有在 Visual Studio Code 中完成它的工作。我试过R support for Visual Studio Code和 R-T
我正在处理一些报告(计数),我必须获取不同参数的计数。非常简单但乏味。 一个参数的示例查询: qCountsEmployee = ( "select count(*) from %s wher
最近几天我尝试从 d00m 调试网络错误。我开始用尽想法/线索,我希望其他 SO 用户拥有可能有用的宝贵经验。我希望能够提供所有相关信息,但我个人无法控制服务器环境。 整个事情始于用户注意到我们应用程
我有一个 app.js 文件,其中包含如下 dojo amd 模式代码: require(["dojo/dom", ..], function(dom){ dom.byId('someId').i
我对“-gencode”语句中的“code=sm_X”选项有点困惑。 一个例子:NVCC 编译器选项有什么作用 -gencode arch=compute_13,code=sm_13 嵌入库中? 只有
我为我的表格使用 X-editable 框架。 但是我有一些问题。 $(document).ready(function() { $('.access').editable({
我一直在通过本教程学习 flask/python http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-wo
我想将 Vim 和 EMACS 用于 CNC、G 代码和 M 代码。 Vim 或 EMACS 是否有任何语法或模式来处理这种类型的代码? 最佳答案 一些快速搜索使我找到了 this vim 和 thi
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 想改进这个问题?更新问题,使其成为 on-topic对于堆栈溢出。 7年前关闭。 Improve this
这个问题在这里已经有了答案: Enabling markdown highlighting in Vim (5 个回答) 6年前关闭。 当我在 Vim 中编辑包含 Markdown 代码的 READM
我正在 Swift3 iOS 中开发视频应用程序。基本上我必须将视频 Assets 和音频与淡入淡出效果合并为一个并将其保存到 iPhone 画廊。为此,我使用以下方法: private func d
pipeline { agent any stages { stage('Build') { steps { e
我是一名优秀的程序员,十分优秀!