Tag: x86 64

为什么x86很丑? 与其他人相比,为什么被认为是劣等的?

最近我一直在阅读一些SO档案,并遇到了针对x86架构的声明。 为什么我们需要不同的CPU架构的服务器和迷你/大型机和混合核心? 说 “ PC架构是一团糟,任何OS开发者都会告诉你的。 学习汇编语言是否值得努力? ( 存档 )说 “ 意识到x86架构至多是可怕的 ” 学习x86汇编程序的简单方法是什么? 说 “ 大多数大学都会在像MIPS这样的东西上进行汇编,因为它比较容易理解,x86汇编真的很难看 ” 还有更多的评论 “与大多数架构相比,X86糟透了。” “ 这绝对是X86不如MIPS,SPARC和PowerPC的传统智慧 ” “ x86很难看 ” 我尝试search,但没有find任何理由。 我不认为x86可能是坏的,因为这是我熟悉的唯一架构。 有人可以友好地给我考虑x86相比其他人的丑陋/坏/劣等原因。

为什么要引入无用的MOV指令可以加速x86_64程序集中的紧密循环?

背景: 当用embedded汇编语言优化一些Pascal代码时,我注意到一个不必要的MOV指令,并将其删除。 令我惊讶的是,删除不必要的指令导致我的程序放慢速度 。 我发现添加任意的,无用的MOV指令可以进一步提高性能 。 效果是不稳定的,并根据执行顺序进行更改: 相同的垃圾指令由单行上下移动会产生减速 。 我了解CPU可以进行各种优化和精简,但是,这看起来更像黑魔法。 数据: 我的代码版本有条件地编译运行2**20==1048576次循环中间的三个垃圾操作 。 (周围的程序只是计算SHA-256散列)。 我的老机器(Intel(R)Core(TM)2 CPU 6400 @ 2.13 GHz)上的结果如下: avg time (ms) with -dJUNKOPS: 1822.84 ms avg time (ms) without: 1836.44 ms 程序循环运行25次,每次运行顺序随机更改。 摘抄: {$asmmode intel} procedure example_junkop_in_sha256; var s1, t2 : uint32; begin // Here are parts of the SHA-256 algorithm, in Pascal: […]

炸弹实验室阶段_4

Dump of assembler code for function func4 <+0>: mov %rbx,-0x18(%rsp) <+5>: mov %rbp, -0x10(%rsp) <+10>: mov %r12,-0x8(%rsp) <+15>: sub $0x18,%rsp <+19>: mov %edi,%ebx <+21>: mov %esi,%ebp <+23>: test %edi, %edi <+25>: jg 0x400fb2<func4+34> <+27>: mov $0x0,%ebp <+32>: jmp 0x400fd2<func4+66> <+34> cmp $0x1, %edi <+37>: je 0x400fd2<func4+66> <+39>: lea -0x1(%rbx),%edi <+42>: callq 0x400f90 <func4> <+47>: mov […]

在x64上使用非临时存储获取/释放语义

我有这样的东西: if (f = acquire_load() == ) { … use Foo } 和: auto f = new Foo(); release_store(f) 你可以很容易地想象一下,使用带有load(memory_order_acquire)和store(memory_order_release)的primefaces的acquire_load和release_store的实现。 但是现在如果release_store是通过_mm_stream_si64实现的,这是一个非暂时写入,而不是相对于x64上的其他存储进行sorting的呢? 如何获得相同的语义? 我认为以下是最低要求: atomic<Foo*> gFoo; Foo* acquire_load() { return gFoo.load(memory_order_relaxed); } void release_store(Foo* f) { _mm_stream_si64(*(Foo**)&gFoo, f); } 并如此使用它: // thread 1 if (f = acquire_load() == ) { _mm_lfence(); … use Foo } 和: […]

什么是x86_64 va_list结构的格式?

任何人都可以参考x86_64 ABI(在Linux上使用的)中的va_list的表示? 我试图debugging一些代码堆栈或参数看起来腐败,这将有助于理解我应该看到什么…

将一个32位偏移量添加到x86-64 ABI的指针时,是否需要符号或零扩展?

简介:我正在查看汇编代码来指导我的优化,并将int32添加到指针时看到大量符号或零扩展。 void Test(int *out, int offset) { out[offset] = 1; } ————————————- movslq %esi, %rsi movl $1, (%rdi,%rsi,4) ret 起初,我认为我的编译器在添加32位到64位整数时遇到了挑战,但是我已经用Intel ICC 11,ICC 14和GCC 5.3证实了这种行为。 这个线程证实了我的发现,但是不清楚符号或零扩展是否必要。 只有在高32位还没有设置的情况下,这个符号/零扩展才是必要的。 但是,x86-64 ABI不会足够聪明,需要吗? 我有点不情愿改变我所有的指针偏移ssize_t,因为注册溢出会增加代码的caching足迹。

x86-64 Linux中不再允许32位绝对地址?

64位Linux默认使用小内存模式,这将使所有的代码和静态数据低于2GB的地址限制。 这确保您可以使用32位绝对地址。 老版本的gcc使用静态数组的32位绝对地址来保存一个额外的相对地址计算指令。 但是,这不再起作用。 如果我试图在程序集中创build一个32位的绝对地址,我得到链接器错误:“在创build共享对象时不能使用对`.data的重定位R_X86_64_32S;使用-fPIC重编译”。 这个错误信息当然是误导性的,因为我没有创build一个共享对象,-fPIC也没有帮助。 到目前为止我发现的是:gcc版本4.8.5使用静态数组的32位绝对地址,gcc版本6.3.0不使用。 版本5可能不会。 binutils 2.24中的链接器允许32位绝对地址,而2.28版本则不允许。 这种改变的后果是,旧的库必须重新编译,旧的汇编代码被破坏。 现在我想问一下:这个改变是什么时候发生的? 有logging吗? 有没有一个链接器选项,使其接受32位绝对地址?

为什么在x86(-64)上有符号和无符号乘法不同的指令?

我认为2的补充的全部意义在于可以以相同的方式对有符号和无符号数字执行操作。 维基百科甚至专门列出乘法作为有益的操作之一 。 那么为什么x86对每个mul和imul都有单独的指示? 这对于x86-64还是这样吗?

在整数除以零的平台上触发浮点exception?

在另一个问题中,有人想知道为什么当他们在C ++程序中有一个整除零时,他们得到了一个“浮点错误”。 围绕这个问题进行了讨论,其中一些人声称浮点exception事实上从来没有被浮动除以零产生,而是只在整数除以零时产生。 这听起来很奇怪,因为我知道: 所有Windows平台上的x86和x64上的MSVC编译代码报告int除以零为“0xc0000094:整数除零”,浮点除以零作为0xC000008E“浮点除零”(启用时) IA-32和AMD64 ISA将#DE (整数#DE除外)指定为中断0.浮点exception触发中断16(x87浮点)或中断19(SIMD浮点)。 其他硬件也有类似的不同中断( 例如, PPC在float-div-by-zero上产生0x7000,并且根本不捕获int / 0)。 我们的应用程序用_controlfp_s内部函数(最终是stmxcsr op)取消了被零除的浮点exception,然后捕获它们用于debugging目的。 所以我在实践中已经明确地看到了IEEE754除零的例外。 所以我得出结论,有一些平台将intexception报告为浮点exception,例如x64 Linux(不pipeALUpipe道是否提升所有算术错误的SIGFPE) 。 什么其他操作系统(或C / C ++运行时,如果您是操作系统)报告整数div-by-zero作为浮点exception?

__builtin_prefetch,它读多less?

我试图通过使用优化一些RK4 GCC C ++代码 __builtin_prefetch 我在试图弄清楚如何预取一整堂课时遇到一些麻烦。 我不明白有多less的const void *addr被读取。 所以我有from和加载的下一个值。 for (int i = from; i < to; i++) { double kv = myLinks[i].kv; particle* from = con[i].Pfrom; particle* to = con[i].Pto; //Prefetch values at con[i++].Pfrom & con[i].Pto; double pos = to->px- from->px; double delta = from->r + to->r – pos; double k1 = axcel(kv, […]