标签: inline-assembly

如何访问 C 变量以进行内联汇编操作?

鉴于此代码:

#include <stdio.h>

int main(int argc, char **argv)
{
    int x = 1;
    printf("Hello x = %d\n", x);
}
Run Code Online (Sandbox Code Playgroud)

我想在内联汇编中访问和操作变量 x 。理想情况下,我想使用内联汇编更改其值。GNU 汇编器,并使用 AT&T 语法。

c assembly gcc inline-assembly

5
推荐指数
1
解决办法
4913
查看次数

如何读取寄存器:RAX、RBX、RCX、RDX、RSP。C 或 C++ 中的 RBP、RSI、RDI?

假设我想从双核 x64 CPU 上的这些寄存器(以及所有这些)中读取值。我怎样才能做到这一点?我可以简单地写一些类似的东西:

uint64_t rax = 0, rbx = 0;
__asm__ __volatile__ (
    /* read value from rbx into rbx */
    "movq %%rdx, %0;\n"
    /* read value from rax into rax*/
    "movq %%rax, %1;\n"
    /* output args */
    : "=r" (rbx), "=r" (rax)
    : /* no input */
    /* clear both rdx and rax */
    : "%rdx", "%rax"
);
Run Code Online (Sandbox Code Playgroud)

然后只是打印出来raxrbx?干杯

c c++ inline-assembly

5
推荐指数
1
解决办法
5346
查看次数

x86_64 上的原子 16 字节操作

以下 16 字节原子操作是否正确实现?还有更好的选择吗?

typedef struct {
    uintptr_t low;
    uintptr_t high;
} uint128_atomic;


uint128_atomic load_relaxed(uint128_atomic const *atomic)
{
    uint128_atomic ret;
    asm volatile("xor %%eax, %%eax\n"
                 "xor %%ebx, %%ebx\n"
                 "xor %%ecx, %%ecx\n"
                 "xor %%edx, %%edx\n"
                 "lock; cmpxchg16b %1"
                 : "=A"(ret)
                 : "m"(*atomic)
                 : "cc", "rbx", "rcx");
    return ret;
}

bool cmpexch_weak_relaxed(
    uint128_atomic *atomic,
    uint128_atomic *expected,
    uint128_atomic desired)
{
    bool matched;
    uint128_atomic e = *expected;
    asm volatile("lock; cmpxchg16b %1\n"
                 "setz %0"
                 : "=q"(matched), "+m"(atomic->ui)
                 : "a"(e.low), "d"(e.high), "b"(desired.low), "c"(desired.high)
                 : "cc");
    return matched;
} …
Run Code Online (Sandbox Code Playgroud)

c x86-64 inline-assembly

5
推荐指数
1
解决办法
1874
查看次数

迭代卡汉求和的优化实现

介绍
Kahan 求和/补偿求和是解决编译器无法尊重数字关联属性的技术。截断误差导致 (a+b)+c 不完全等于 a+(b+c),从而在较长的和序列上累积不希望的相对误差,这是科学计算中的常见障碍。

任务
我希望 Kahan 求和的最佳实现。我怀疑使用手工汇编代码可以实现最佳性能。

尝试
下面的代码使用三种方法计算 [0,1] 范围内的 1000 个随机数的总和。

  1. 标准求和:累积均方根相对误差的朴素实现,其增长为 O(sqrt(N))

  2. Kahan summation [g++]:使用 c/c++ 函数“csum”进行补偿求和。评论中的解释。请注意,某些编译器可能具有使此实现无效的默认标志(请参见下面的输出)。

  3. Kahan summation [asm]:使用与“csum”相同的算法实现为“csumasm”的补偿求和。评论中的神秘解释。

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

extern "C" void csumasm(double&, double, double&);
__asm__(
    "csumasm:\n"
    "movsd  (%rcx), %xmm0\n" //xmm0 = a
    "subsd  (%r8), %xmm1\n"  //xmm1 - r8 (c) | y = b-c
    "movapd %xmm0, %xmm2\n"  
    "addsd  %xmm1, %xmm2\n"  //xmm2 + xmm1 (y) | b = a+y
    "movapd %xmm2, %xmm3\n" 
    "subsd  %xmm0, %xmm3\n" …
Run Code Online (Sandbox Code Playgroud)

c++ sse x86-64 inline-assembly fast-math

5
推荐指数
1
解决办法
648
查看次数

glibc的atomic_forced_read函数的目的是什么?

我试图理解atomic_forced_read定义的目的,它经常出现在malloc.c的GNU libc实现中。

我不太擅长内联汇编,但看起来这会返回完全相同的值,并且类型与输入值相同。我在这里缺少什么?

原子强制读取定义在atomic.h中

523 #ifndef atomic_forced_read
524 # define atomic_forced_read(x) \
525   ({ __typeof (x) __x; __asm ("" : "=r" (__x) : "0" (x)); __x; })
526 #endif
Run Code Online (Sandbox Code Playgroud)

链接到atomic.h

https://code.woboq.org/userspace/glibc/include/atomic.h.html

c glibc atomic libc inline-assembly

5
推荐指数
1
解决办法
507
查看次数

为什么局部变量不能在 GNU C 基本内联 asm 语句中使用?

main为什么我不能在基本 asm 内联中使用局部变量?它只允许在扩展汇编中使用,但为什么会这样呢?

(我知道局部变量在返回地址之后位于堆栈上(因此一旦函数返回就不能使用),但这不应成为不使用它们的原因)

以及基本汇编的示例:

int a = 10; //global a
int b = 20; //global b
int result;

int main() {
    asm ( "pusha\n\t"
          "movl a, %eax\n\t"
          "movl b, %ebx\n\t"
          "imull %ebx, %eax\n\t"
          "movl %eax, result\n\t"
          "popa");

    printf("the answer is %d\n", result);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

扩展的例子:

int main (void) {
    int data1 = 10;  //local var - could be used in extended
    int data2 = 20;
    int result;

    asm ( "imull %%edx, %%ecx\n\t"
          "movl %%ecx, %%eax" 
          : "=a"(result) …
Run Code Online (Sandbox Code Playgroud)

c gcc language-design inline-assembly

5
推荐指数
2
解决办法
2737
查看次数

如何防止 gcc 优化破坏 rep movsb 代码?

我试图用rep movsb指令创建我的 memcpy 代码。当优化被禁用时,它适用于任何尺寸。但是,当我启用优化时,它没有按预期工作。

问题

  1. 如何防止 gcc 优化破坏 rep movsb 代码?
  2. 我的代码有问题所以导致未定义的行为吗?

创建我自己的 memcpy 的动机:

我从Intel® 64 and IA-32 Architectures Optimization Reference Manual section 3.7.6 中阅读了有关 memcpy 的增强 movsb 。我来到了 libc 源代码,我看到 libc 的默认 memcpy 使用 SSE 而不是movsb.

因此,我想比较memcpy 的SSE 指令rep movsb之间的性能。但是现在,我发现它有些不对劲。

重现问题的简单代码(test.c)

#include <stdio.h>
#include <string.h>

inline static void *my_memcpy(
  register void *dest,
  register const void *src,
  register size_t n
) {
  __asm__ volatile(
    "mov %0, %%rdi;"
    "mov %1, …
Run Code Online (Sandbox Code Playgroud)

c optimization gcc x86-64 inline-assembly

5
推荐指数
1
解决办法
342
查看次数

使用 goto 扩展 asm,包括 gcc 文档中的一个示例,无法编译

某些使用goto限定符的扩展汇编语句无法使用 GCC 10.1.0 进行编译。具体来说,

int foo(int count)
{
  asm goto ("dec %0; jb %l[stop]"
            : "+r" (count)
            :
            :
            : stop);
  return count;
stop:
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

(这是GCC 扩展 asm 文档中的一个示例)无法使用消息编译expected ‘:’ before string constant。删除"+r" (count)dec %0允许它成功编译,但无论我在何时尝试在与 goto 标签相同的 asm 语句中提供输出操作数时,它都会以同样的方式出错。

c gcc goto inline-assembly

5
推荐指数
2
解决办法
220
查看次数

如何在cython中调用C内联汇编asm?

如何asm()在cython中调用C语言的内联汇编函数?我尝试了一个简单的asm("mov $eax, 0x1") or __asm__(). 它 cythonizes 很好,直到asm-call,然后给我以下错误:

NameError:名称“asm”未定义

我将我的代码编译为python setup.py build_ext --inplace && python runids.py

c inline-assembly cython

5
推荐指数
1
解决办法
647
查看次数

Google 的“DoNotOptimize()”函数如何强制语句排序

我试图准确理解谷歌的DoNotOptimize()运作方式。

为了完整起见,以下是它的定义(对于 clang 和非常量数据):

template <class Tp>
inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp& value) {
  asm volatile("" : "+r,m"(value) : : "memory");
}
Run Code Online (Sandbox Code Playgroud)

据我了解,我们可以在如下代码中使用它:

start_time = time();
bench_output = run_bench(bench_inputs);
result = time() - start_time;
Run Code Online (Sandbox Code Playgroud)

为了确保基准保持在关键部分:

start_time = time();
DoNotOptimize(bench_inputs);
bench_output = run_bench(bench_inputs);
DoNotOptimise(bench_output);
result = time() - start_time;
Run Code Online (Sandbox Code Playgroud)

具体来说,我不明白的是为什么这保证(是吗?)run_bench()不会移到上面start_time = time()

(有人在这个评论中问过这个问题,但我不明白答案)。

据我了解,上面DoNotOptimze()做了几件事:

  • 它强制value进入堆栈,因为它是通过 C++ 引用传递的。您不能有指向寄存器的指针,因此它必须位于内存中。
  • 因为value现在位于堆栈上,因此随后破坏内存(如在 asm 约束中完成的那样)将迫使编译器假设value通过调用DoNotOptimize(value).
  • (我不清楚+r,m …

benchmarking inline-assembly compiler-optimization google-benchmark instruction-reordering

5
推荐指数
1
解决办法
1312
查看次数