我正在使用Visual C++ 2010开发32位Windows应用程序.有一些我真的想要使用内联汇编.但我刚刚意识到Visual C++不支持64位应用程序中的内联汇编.因此,将来移植到64位是一个大问题.
我不知道64位应用程序与32位应用程序有何不同.是否有可能在未来将32位应用程序全部升级到64位?我听说64位CPU有更多的寄存器.由于性能不是我的应用程序的问题,使用这些额外的寄存器不是我的问题.32位应用程序是否需要升级到64位还有其他原因吗?与32位应用程序相比,64位应用程序处理的方式是否有所不同,除了64位应用程序可能使用64位CPU独有的寄存器或指令?
我的应用程序需要与其他操作系统组件进行交互,例如驱动程序,我知道它必须是64位窗口中的64位.我的32位应用程序是否与它们兼容?
我们正在为高级编译语言编写一个字节码,经过一些分析和优化后,很明显当前最大的性能开销是我们用来跳转到字节码情况的switch语句.
我们调查了拉出每个case标签的地址并将其存储在字节码本身的流中,而不是我们通常打开的指令ID.如果我们这样做,我们可以跳过跳转表,并直接跳转到当前正在执行的指令的代码位置.这在GCC中非常有用,但是,MSVC似乎不支持这样的功能.
我们尝试使用内联汇编来获取标签的地址(并跳转到它们),但它可以工作,但是,使用内联汇编会导致MSVC优化器避免使用整个函数.
有没有办法让优化器仍然运行代码?遗憾的是,我们无法将内联汇编提取到另一个函数中,而不是制作标签的函数,因为即使在内联汇编中也无法为另一个函数引用标签.有什么想法或想法吗?非常感谢您的意见,谢谢!
我正在编写一个加密程序,并且核心(一个宽的乘法例程)是用x86-64汇编编写的,两者都是为了速度而且因为它广泛使用adc那些不容易从C中访问的指令.我不想内联这个函数,因为它很大,并且在内循环中被调用了好几次.
理想情况下,我还想为此函数定义一个自定义调用约定,因为它在内部使用所有寄存器(除外rsp),不破坏其参数,并在寄存器中返回.现在,它适应了C调用约定,但当然这使它变慢(大约10%).
为了避免这种情况,我可以调用它,asm("call %Pn" : ... : my_function... : "cc", all the registers);但有没有办法告诉GCC调用指令与堆栈混淆?否则GCC会将所有这些寄存器放在红色区域中,而顶部的寄存器将被破坏.我可以使用-mno-red-zone编译整个模块,但是我更喜欢告诉GCC,比方说,红色区域的前8个字节将被破坏,以便它不会放任何东西.
我想知道你是否可以在Swift中编写内联汇编.
我知道在Objective-C中你可以使用这样的东西:
inline void assemblyFunc() {
__asm__(/*Assembly*/);
}
Run Code Online (Sandbox Code Playgroud)
但在Swift中似乎你无法使用 __asm__(/*Assembly*/).
__asm__()如果有可能,有谁知道如何使用.我还没有找到任何关于它的信息,所以我认为这是一个很好的问题.
我很难理解角色约束在GCC内联汇编(x86)中的作用.我已经阅读了手册,它准确地解释了每个约束的作用.问题在于,即使我理解每个约束的作用,我也很少理解为什么要使用一个约束而不是另一个约束,或者含义可能是什么.
我意识到这是一个非常广泛的话题,所以一个小例子应该有助于缩小焦点.以下是一个简单的asm例程,它只添加了两个数字.如果发生整数溢出,则将值写入1输出C变量.
int32_t a = 10, b = 5;
int32_t c = 0; // overflow flag
__asm__
(
"addl %2,%3;" // Do a + b (the result goes into b)
"jno 0f;" // Jump ahead if an overflow occurred
"movl $1, %1;" // Copy 1 into c
"0:" // We're done.
:"=r"(b), "=m"(c) // Output list
:"r"(a), "0"(b) // Input list
);
Run Code Online (Sandbox Code Playgroud)
现在这个工作正常,除了我必须随意摆弄约束,直到我让它正常工作.最初,我使用了以下约束:
:"=r"(b), "=m"(c) // Output list
:"r"(a), "m"(b) // Input list
Run Code Online (Sandbox Code Playgroud)
请注意,我使用"m"约束而不是"0" b.这有一个奇怪的副作用,如果我用优化标志编译并调用该函数两次,由于某种原因,加法操作的结果也将被存储 …
似乎gcc 4.6.2删除了它认为从函数中未使用的代码.
int main(void) {
goto exit;
handler:
__asm__ __volatile__("jmp 0x0");
exit:
return 0;
}
Run Code Online (Sandbox Code Playgroud)
main() 0x08048404 <+0>: push ebp
0x08048405 <+1>: mov ebp,esp
0x08048407 <+3>: nop # <-- This is all whats left of my jmp.
0x08048408 <+4>: mov eax,0x0
0x0804840d <+9>: pop ebp
0x0804840e <+10>: ret
Run Code Online (Sandbox Code Playgroud)
没有启用优化,只是gcc -m32 -o test test.c(-m32因为我在64位机器上).
我怎么能阻止这种行为?
编辑:最好通过使用编译器选项,而不是通过修改代码.
我正在编写一个C代码,用于测量获取信号量所需的时钟周期数.我正在使用rdtsc,在对信号量进行测量之前,我连续两次调用rdtsc来测量开销.我在for循环中重复了这么多次,然后我将平均值用作rdtsc开销.
这是正确的,首先要使用平均值吗?
尽管如此,这里的一个大问题是,有时我会得到开销的负值(不一定是平均值,但至少是for循环中的部分值).
这也影响了连续计算sem_wait()操作所需的cpu周期数,有时也证明是负数.如果我写的不清楚,这里有一部分我正在编写的代码.
为什么我会得到这样的负值?
(编者注:请参阅获取CPU周期计数?以获得完整的64位时间戳的正确和可移植方式."=A"编译为x86-64时,asm约束只能得到低或高32位,具体取决于寄存器分配是否发生为uint64_t输出选择RAX或RDX .它不会选择edx:eax.)
(编辑的第二个注释:哎呀,这就是为什么我们得到负面结果的答案.仍然值得留下一个注释作为警告,不要复制这个rdtsc实现.)
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
static inline uint64_t get_cycles()
{
uint64_t t;
// editor's note: "=A" is unsafe for this in x86-64
__asm volatile ("rdtsc" : "=A"(t));
return t;
}
int num_measures = 10;
int main ()
{
int i, value, res1, res2;
uint64_t c1, c2;
int tsccost, tot, a;
tot=0;
for(i=0; i<num_measures; i++)
{ …Run Code Online (Sandbox Code Playgroud) 我有一些 C 代码:
#include "stdio.h"
typedef struct num {
unsigned long long x;
} num;
int main(int argc, char **argv) {
struct num anum;
anum.x = 0;
__asm__("movq %%rax, %0\n" : "=m" (anum.x) : "rax"(2));
printf("%llu\n",anum.x);
}
Run Code Online (Sandbox Code Playgroud)
我正在我的(英特尔)Mac 笔记本电脑上编译并运行它。
代码的输出似乎有所不同,具体取决于我使用 (GNU) GCC 还是 Clang 进行编译。gnucc -o gnu-test test.c我使用GCC(从https://gcc.gnu.org/install/download.htmlgnucc下载源代码后在 Mac 上从源代码构建)和Clang(内置 macOS Clang)进行编译。clang -o clang-test test.c
在我的 Mac 上,使用 GNU,结果是2(这是我所期望的)。使用 Clang,结果是140701838959608.
Clang 结果对我来说似乎是错误的,但我也想知道我的内联汇编是否不太正确,而 GCC 恰好没有暴露我的错误。
我在Compiler Explorer上尝试了相同的代码, GCC(x86-64 GCC 13.2 …
这是寄存器加载代码列表:
a eax
b ebx
c ecx
d edx
S esi
D edi
I常数值(0到31)
q,r动态分配寄存器(见下文)
g eax,ebx,ecx,edx或内存中
的变量a eax和edx合并为64位整数(使用long longs)
但这是intel i386的注册限制.我的问题是我可以在哪里找到intel x86_64系统的寄存器限制,例如:
?%r10
?%r8
?%的RDX
等等.