标签: x86-64

LEA指令的目的是什么?

对我来说,它看起来像一个时髦的MOV.它的目的是什么,我什么时候应该使用它?

x86 assembly x86-64 x86-16

632
推荐指数
15
解决办法
54万
查看次数

如果我优化大小而不是速度,为什么GCC会生成15-20%的代码?

我在2009年首先注意到GCC(至少在我的项目和我的机器上)如果我优化尺寸(-Os)而不是速度(-O2-O3),则会产生明显更快的代码,我一直想知道为什么.

我设法创建(相当愚蠢)代码,显示这种令人惊讶的行为,并且足够小,无法在此处发布.

const int LOOP_BOUND = 200000000;

__attribute__((noinline))
static int add(const int& x, const int& y) {
    return x + y;
}

__attribute__((noinline))
static int work(int xval, int yval) {
    int sum(0);
    for (int i=0; i<LOOP_BOUND; ++i) {
        int x(xval+sum);
        int y(yval+sum);
        int z = add(x, y);
        sum += z;
    }
    return sum;
}

int main(int , char* argv[]) {
    int result = work(*argv[1], *argv[2]);
    return result;
}
Run Code Online (Sandbox Code Playgroud)

如果我用-Os它编译它,执行这个程序需要0.38秒,如果用-O2 …

c++ performance gcc x86-64 compiler-optimization

430
推荐指数
6
解决办法
9万
查看次数

为什么在强度降低乘法和循环进位加法之后,这段代码的执行速度会变慢?

我正在阅读Agner Fog优化手册,并且遇到了这个例子:

double data[LEN];

void compute()
{
    const double A = 1.1, B = 2.2, C = 3.3;

    int i;
    for(i=0; i<LEN; i++) {
        data[i] = A*i*i + B*i + C;
    }
}
Run Code Online (Sandbox Code Playgroud)

Agner 指出,有一种方法可以优化此代码 - 通过认识到循环可以避免使用昂贵的乘法,而是使用每次迭代应用的“增量”。

我用一张纸来证实这个理论,首先......

理论

...当然,他是对的 - 在每次循环迭代中,我们可以通过添加“增量”,基于旧结果计算新结果。该增量从值“A+B”开始,然后每一步增加“2*A”。

所以我们将代码更新为如下所示:

void compute()
{
    const double A = 1.1, B = 2.2, C = 3.3;
    const double A2 = A+A;
    double Z = A+B;
    double Y = C;

    int i;
    for(i=0; i<LEN; i++) {
        data[i] …
Run Code Online (Sandbox Code Playgroud)

optimization assembly x86-64 simd cpu-architecture

320
推荐指数
6
解决办法
9万
查看次数

如何确定.NET程序集是为x86还是x64构建的?

我有一个任意的.NET程序集列表.

我需要以编程方式检查每个DLL是否是为x86构建的(而不是x64或任何CPU).这可能吗?

.net 64-bit x86 assemblies x86-64

312
推荐指数
8
解决办法
16万
查看次数

为什么引入无用的MOV指令会加速x86_64汇编中的紧凑循环?

背景:

在使用嵌入式汇编语言优化某些Pascal代码时,我注意到了一条不必要的MOV指令,并将其删除.

令我惊讶的是,删除不必要的指令会导致我的程序变慢.

我发现添加任意无用的MOV指令可以进一步提高性能.

效果不稳定,并且基于执行顺序进行更改:相同的垃圾指令向上或向下移动一行会产生减速.

我知道CPU会进行各种优化和精简,但这看起来更像是黑魔法.

数据:

我的代码版本有条件地在运行时间的循环中编译三个垃圾操作2**20==1048576.(周围的程序只计算SHA-256哈希值).

在我相当老的机器(英特尔(R)Core(TM)2 CPU 6400 @ 2.13 GHz)上的结果:

avg time (ms) with -dJUNKOPS: 1822.84 ms
avg time (ms) without:        1836.44 ms
Run Code Online (Sandbox Code Playgroud)

程序在循环中运行25次,每次运行顺序随机变化.

摘抄:

{$asmmode intel}
procedure example_junkop_in_sha256;
  var s1, t2 : uint32;
  begin
    // Here are parts of the SHA-256 algorithm, in Pascal:
    // s0 {r10d} := ror(a, 2) xor ror(a, 13) xor …
Run Code Online (Sandbox Code Playgroud)

optimization performance assembly freepascal x86-64

217
推荐指数
3
解决办法
3万
查看次数

为什么GCC在实现整数除法时使用乘以奇数的乘法?

我一直在阅读divmul组装操作,我决定通过在C中编写一个简单的程序来实现它们:

文件分割

#include <stdlib.h>
#include <stdio.h>

int main()
{
    size_t i = 9;
    size_t j = i / 5;
    printf("%zu\n",j);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

然后生成汇编语言代码:

gcc -S division.c -O0 -masm=intel
Run Code Online (Sandbox Code Playgroud)

但是看生成的division.s文件,它不包含任何div操作!相反,它通过位移和魔术数字来做某种黑魔法.这是一个计算代码片段i/5:

mov     rax, QWORD PTR [rbp-16]   ; Move i (=9) to RAX
movabs  rdx, -3689348814741910323 ; Move some magic number to RDX (?)
mul     rdx                       ; Multiply 9 by magic number
mov     rax, rdx                  ; Take only the upper 64 bits of the …
Run Code Online (Sandbox Code Playgroud)

c assembly gcc x86-64 integer-division

206
推荐指数
4
解决办法
1万
查看次数

使用 -O3 进行冒泡排序比使用 GCC 的 -O2 慢

我用 C 语言实现了一个冒泡排序,并在测试其性能时发现该-O3标志使其运行速度甚至比没有标志时还要慢!与此同时-O2,它的运行速度比预期的要快得多。

没有优化:

time ./sort 30000

./sort 30000  1.82s user 0.00s system 99% cpu 1.816 total
Run Code Online (Sandbox Code Playgroud)

-O2

time ./sort 30000

./sort 30000  1.00s user 0.00s system 99% cpu 1.005 total
Run Code Online (Sandbox Code Playgroud)

-O3

time ./sort 30000

./sort 30000  2.01s user 0.00s system 99% cpu 2.007 total
Run Code Online (Sandbox Code Playgroud)

代码:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <time.h>

int n;

void bubblesort(int *buf)
{
    bool changed = true;
    for (int i = n; changed == true; …
Run Code Online (Sandbox Code Playgroud)

c gcc x86-64 cpu-architecture compiler-optimization

148
推荐指数
1
解决办法
3万
查看次数

132
推荐指数
4
解决办法
10万
查看次数

从函数返回结构时可能存在 GCC 错误

我相信我在实现 O'Neill 的 PCG PRNG 时在 GCC 中发现了一个错误。(Godbolt 编译器资源管理器上的初始代码

相乘后oldstate通过MULTIPLIER,(存储在RDI结果),GCC不该结果添加到INCREMENT,movabs'ingINCREMENT到RDX代替,然后把它用作rand32_ret.state的返回值

最小可重现示例(编译器资源管理器):

#include <stdint.h>

struct retstruct {
    uint32_t a;
    uint64_t b;
};

struct retstruct fn(uint64_t input)
{
    struct retstruct ret;

    ret.a = 0;
    ret.b = input * 11111111111 + 111111111111;

    return ret;
}
Run Code Online (Sandbox Code Playgroud)

生成的程序集(GCC 9.2、x86_64、-O3):

fn:
  movabs rdx, 11111111111     # multiplier constant (doesn't fit in imm32)
  xor eax, eax                # ret.a = 0
  imul rdi, rdx
  movabs rdx, 111111111111 …
Run Code Online (Sandbox Code Playgroud)

c assembly gcc x86-64 compiler-bug

131
推荐指数
3
解决办法
6198
查看次数

如何查找本机DLL文件是否编译为x64或x86?

我想确定本机程序集是否从托管代码应用程序(C#)编译为x64或x86 .

我认为它必须在PE头中的某处,因为OS加载器需要知道这些信息,但我找不到它.当然我更喜欢在托管代码中执行它,但如果有必要,我可以使用本机C++.

.net c# 64-bit winapi x86-64

127
推荐指数
7
解决办法
10万
查看次数