标签: x86-64

错误:"push"的指令后缀无效

我试图通过assmbly中的堆栈研究将参数传递给函数.我正在使用Fedora 20,64位系统.

当我尝试以下代码时,

pushl%ebp

popl%ebp

我得到错误,错误:"推"的无效指令后缀

我将如何克服这个错误!

我编译它,如-ggstabs -o Function_Stack.o Function_Stack.c

assembly x86-64

15
推荐指数
1
解决办法
2万
查看次数

Visual Studio中的外部程序集文件

我搜索并发现我无法__asm在视觉工作室的x64中使用.相反,我必须使用外部程序集文件.

如何将外部程序集文件添加到我的win32控制台项目?

如何编译它们?

你能一步一步解释吗?

x86 assembly x86-64 masm visual-studio

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

为什么编译器坚持在这里使用被调用者保存的寄存器?

考虑这个 C 代码:

void foo(void);

long bar(long x) {
    foo();
    return x;
}
Run Code Online (Sandbox Code Playgroud)

当我在 GCC 9.3 上使用-O3或编译它时-Os,我得到这个:

bar:
        push    r12
        mov     r12, rdi
        call    foo
        mov     rax, r12
        pop     r12
        ret
Run Code Online (Sandbox Code Playgroud)

除了选择rbx而不是r12作为被调用者保存的寄存器之外,clang 的输出是相同的。

但是,我希望/期望看到看起来更像这样的程序集:

bar:
        push    rdi
        call    foo
        pop     rax
        ret
Run Code Online (Sandbox Code Playgroud)

由于无论如何您都必须将某些内容推送到堆栈中,因此将您的值推送到那里似乎更短,更简单,并且可能更快,而不是将一些任意的被调用者保存的寄存器值推送到那里,然后将您的值存储在该寄存器中。call foo当你把东西放回去后,反之亦然。

我的组装错了吗?它在某种程度上比弄乱额外的寄存器效率低吗?如果这两个的答案都是“否”,那么为什么 GCC 或 clang 不这样做呢?

Godbolt 链接


编辑:这是一个不太简单的例子,即使变量被有意义地使用,它也会发生:

long foo(long);

long bar(long x) {
    return foo(x * x) - x;
}
Run Code Online (Sandbox Code Playgroud)

我明白了:

bar:
        push    rbx …
Run Code Online (Sandbox Code Playgroud)

c assembly gcc x86-64 register-allocation

15
推荐指数
1
解决办法
737
查看次数

为什么这个函数在额外读取内存时运行得如此之快?

我目前正在尝试了解 x86_64(特别是我的 Intel(R) Core(TM) i3-8145U CPU @ 2.10GHz 处理器)上某些循环的性能属性。具体来说,在循环体内部添加一个额外的读取内存指令几乎可以使性能翻倍,而细节并不是特别重要。

我一直在使用一个测试程序,它由两个主要部分组成:一个测试循环和一个被测函数。测试循环运行被测函数 2 32次,一次将每个有符号的 32 位整数作为参数(按从INT_MIN到 的顺序INT_MAX)。被测函数(名为body)是一个小函数,用于检查是否使用预期参数调用它,否则将错误记录在全局变量中。测试程序涉及的内存量足够小,所有东西都可能适合 L1 缓存。

为了消除可能由编译器行为引起的任何速度差异,我用汇编语言编写了两个有问题的函数(我clang用作汇编程序),并被迫从固定地址(这种测试循环的性能通常受与对齐或缓存相关的影响所支配,因此使用固定地址将消除任何与更改无关的对齐效果或缓存效果)。

这是反汇编的测试循环(它需要函数的地址在 中循环%rdi):

  401300:       53                      push   %rbx
  401301:       55                      push   %rbp
  401302:       51                      push   %rcx
  401303:       48 89 fd                mov    %rdi,%rbp
  401306:       bb 00 00 00 80          mov    $0x80000000,%ebx
loop:
  40130b:       89 df                   mov    %ebx,%edi
  40130d:       ff d5                   callq  *%rbp
  40130f:       83 c3 01                add    $0x1,%ebx
  401312:       71 f7                   jno    40130b <loop> …
Run Code Online (Sandbox Code Playgroud)

performance assembly x86-64 cpu-architecture clang

15
推荐指数
1
解决办法
209
查看次数

x86-64 的缓存填充大小应该为 128 字节吗?

我发现了一条来自 的评论crossbeam

从 Intel 的 Sandy Bridge 开始,空间预取器现在一次提取成对的 64 字节缓存线,因此我们必须对齐到 128 字节而不是 64。

资料来源:

我在英特尔的手册中没有找到这样的说法。但直到最新的提交,folly仍然使用 128 字节填充,这让我很有说服力。所以我开始编写代码来看看是否可以观察到这种行为。这是我的代码。

#include <thread>

int counter[1024]{};

void update(int idx) {
    for (int j = 0; j < 100000000; j++) ++counter[idx];
}

int main() {
    std::thread t1(update, 0);
    std::thread t2(update, 1);
    std::thread t3(update, 2);
    std::thread t4(update, 3);
    t1.join();
    t2.join();
    t3.join();
    t4.join();
}
Run Code Online (Sandbox Code Playgroud)

编译器资源管理器

我的CPU是锐龙3700X。当索引为0123时,大约需要 1.2 秒才能完成。当索引为0, 16, 32,时 …

c++ x86-64 rust cpu-cache false-sharing

15
推荐指数
1
解决办法
2210
查看次数

用gcc清理x86_64组件输出?

我已经通过在C中编写语句,用"gcc -S"编译它们并研究输出,一直在教自己GNU Assembly一段时间.这在x86(并使用-m32编译)上工作正常,但在我的AMD64框中,对于此代码(仅作为示例):

int main()
{
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

GCC给了我:

 .file "test.c"
 .text
.globl main
 .type main, @function
main:
.LFB2:
 pushq %rbp
.LCFI0:
 movq %rsp, %rbp
.LCFI1:
 movl $0, %eax
 leave
 ret
.LFE2:
 .size main, .-main
 .section .eh_frame,"a",@progbits
.Lframe1:
 .long .LECIE1-.LSCIE1
.LSCIE1:
 .long 0x0
 .byte 0x1
 .string "zR"
 .uleb128 0x1
 .sleb128 -8
 .byte 0x10
 .uleb128 0x1
 .byte 0x3
 .byte 0xc
 .uleb128 0x7
 .uleb128 0x8
 .byte 0x90
 .uleb128 0x1
 .align 8
.LECIE1:
.LSFDE1:
 .long .LEFDE1-.LASFDE1
.LASFDE1:
 .long .LASFDE1-.Lframe1
 .long .LFB2
 .long …

assembly gcc x86-64

14
推荐指数
2
解决办法
3792
查看次数

"mov rax,QWORD PTR fs:0x28"汇编指令有什么作用?

在执行该指令之前,fs包含0x0.

另外我想知道如何从GDB中的这个内存区读取,这个命令是什么?

linux assembly gdb x86-64

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

生成LLVM C++ API代码作为后端

在线LLVM演示页面有一个选项生成LLVM C++ API代码从一个源代码后端.但是,该演示页面现已禁用.我想知道我们如何使用可用的LLVM工具自己完成它.

我尝试了以下内容

clang++ -c -emit-llvm input.cpp -o input.ll
llc -march=cpp -o input.ll.cpp input.ll
Run Code Online (Sandbox Code Playgroud)

这给出了以下错误

llc: error: invalid target 'cpp'.
Run Code Online (Sandbox Code Playgroud)

我使用的是LLVM/Clang 3.2版.

c++ linux x86-64 llvm

14
推荐指数
1
解决办法
5694
查看次数

了解gcc -S输出

我在下面的x86_64非常复杂的程序上做了gcc -S:

int main() {
    int x = 3;
    x = 5;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

而我得到的是:

       .file   "main.c"
        .text
.globl main
        .type   main, @function
main:
.LFB0:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        movl    $3, -4(%rbp)
        movl    $5, -4(%rbp)
        movl    $0, %eax
        leave
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE0:
        .size   main, .-main
        .ident  "GCC: (GNU) 4.4.7 20120313 (Red Hat 4.4.7-3)"
        .section        .note.GNU-stack,"",@progbits
Run Code Online (Sandbox Code Playgroud)

我想知道是否有人可以帮助我理解输出或引用我的一些链接解释.具体来说,cfi ,LFB0,LFE0 , leave意味着什么?关于这些我能找到的就是这篇文章但却无法完全理解它的用途.另外,ret在这种情况下做什么?我猜它正在回归__libc_start_main(),反过来会打电话 …

assembly gcc x86-64

14
推荐指数
2
解决办法
5011
查看次数

带有gcc 7.3的__atomic_fetch_or的意外x64程序集

我试图使用64位积分作为位图,并原子地获取/释放各个位的所有权.

为此,我编写了以下无锁代码:

#include <cstdint>
#include <atomic>

static constexpr std::uint64_t NO_INDEX = ~std::uint64_t(0);

class AtomicBitMap {
public:
    static constexpr std::uint64_t occupied() noexcept {
        return ~std::uint64_t(0);
    }

    std::uint64_t acquire() noexcept {
        while (true) {
            auto map = mData.load(std::memory_order_relaxed);
            if (map == occupied()) {
                return NO_INDEX;
            }

            std::uint64_t index = __builtin_ctzl(~map);
            auto previous =
                mData.fetch_or(bit(index), std::memory_order_relaxed);
            if ((previous & bit(index)) == 0) {
                return index;
            }
        }
    }

private:
    static constexpr std::uint64_t bit(std::uint64_t index) noexcept {
        return std::uint64_t(1) << index;
    }

    std::atomic_uint64_t mData{ …
Run Code Online (Sandbox Code Playgroud)

c++ assembly gcc x86-64 compiler-bug

14
推荐指数
1
解决办法
457
查看次数