相关疑难解决方法(0)

FreeBSD 系统调用比 Linux 破坏更多的寄存器?内联汇编优化级别之间的不同行为

最近我在玩 freebsd 系统调用,我对 i386 部分没有问题,因为它在这里有很好的记录但是我找不到 x86_64 的相同文档。

我看到人们在 linux 上使用相同的方式,但他们只使用程序集而不是 c。我想在我的例子中,系统调用实际上改变了一些被高优化级别使用的寄存器,所以它给出了不同的行为。

/* for SYS_* constants */
#include <sys/syscall.h>

/* for types like size_t */
#include <unistd.h>

ssize_t sys_write(int fd, const void *data, size_t size){
    register long res __asm__("rax");
    register long arg0 __asm__("rdi") = fd;
    register long arg1 __asm__("rsi") = (long)data;
    register long arg2 __asm__("rdx") = size;
    __asm__ __volatile__(
        "syscall"
        : "=r" (res)
        : "0" (SYS_write), "r" (arg0), "r" (arg1), "r" (arg2)
        : "rcx", "r11", "memory"
    ); …
Run Code Online (Sandbox Code Playgroud)

c freebsd x86-64 system-calls inline-assembly

7
推荐指数
1
解决办法
259
查看次数

ASM内联疑问

我试图了解Linux中内联汇编程序的一些内容.我正在使用以下功能:

void test_func(Word32 *var){
   asm( " addl %0, %%eax" : : "m"(var) );
   return;
}
Run Code Online (Sandbox Code Playgroud)

它生成以下汇编代码:

.globl test_func
.type   test_func, @function
test_func:
        pushl %ebp
        movl %esp, %ebp
#APP
# 336 "opers.c" 1
        addl 8(%ebp), %eax
# 0 "" 2
#NO_APP
        popl %ebp
        ret
        .size   test_func, .-test_func
Run Code Online (Sandbox Code Playgroud)

它将var mem地址与eax寄存器值相加而不是var值.

有没有办法告诉addl指令使用var值而不是var mem地址而不将var mem地址复制到寄存器?

问候

assembly gcc

6
推荐指数
1
解决办法
3123
查看次数

如何在没有扩展内联asm的情况下在gcc内联汇编中声明和初始化局部变量?

我知道这是一个非常基本的问题,但我真的很困惑.事实上,我绝对是gcc语法的新手.我希望在不使用扩展内联汇编的情况下拥有局部变量(事实上堆栈地址带有标签); 类似于intel语法中的代码:

DATA1 DB 100

MOV AL,DATA1

这是我猜可能在gcc中替代的代码:

- (int)someFunction:(int)x {

DATA1  DB  100 
MOV AL, DATA1
Run Code Online (Sandbox Code Playgroud)

但是这段代码导致了这个错误:

找不到架构x86_64的符号

我可以在x86中使用全局变量,但x64或x86_x64中的结果相同.

设置:LLVM 4.1; Xcode中使用的Cocoa 4

什么是正确的语法?

gcc scope local-variables inline-assembly

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

使用内联汇编在数组上循环

当使用内联汇编循环数组时,我应该使用寄存器修饰符"r"还是内存修饰符"m"?

让我们考虑其将两个浮标阵为例x,与y和结果写入z.通常我会使用内在函数这样做

for(int i=0; i<n/4; i++) {
    __m128 x4 = _mm_load_ps(&x[4*i]);
    __m128 y4 = _mm_load_ps(&y[4*i]);
    __m128 s = _mm_add_ps(x4,y4);
    _mm_store_ps(&z[4*i], s);
}
Run Code Online (Sandbox Code Playgroud)

这是我使用寄存器修饰符"r"提出的内联汇编解决方案

void add_asm1(float *x, float *y, float *z, unsigned n) {
    for(int i=0; i<n; i+=4) {
        __asm__ __volatile__ (
            "movaps   (%1,%%rax,4), %%xmm0\n"
            "addps    (%2,%%rax,4), %%xmm0\n"
            "movaps   %%xmm0, (%0,%%rax,4)\n"
            :
            : "r" (z), "r" (y), "r" (x), "a" (i)
            :
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

这会产生与GCC类似的组装.主要区别在于GCC将16添加到索引寄存器并使用1的标度,而内联汇编解决方案将4添加到索引寄存器并使用4的标度.

我无法使用通用寄存器作为迭代器.在这种情况下,我必须指定一个rax.是否有一个原因?

这是我想出的使用内存修饰符"m"的解决方案

void add_asm2(float *x, float *y, …
Run Code Online (Sandbox Code Playgroud)

c assembly gcc inline-assembly

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

为什么局部变量不能在 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
查看次数

来自GCC内联汇编的系统调用

是否可以使用内联汇编块中的系统调用来编写单个字符?如果是这样,怎么样?它应该看起来像这样的"东西":

__asm__ __volatile__
                    (
                     " movl $1,  %%edx \n\t"
                     " movl $80, %%ecx \n\t"
                     " movl $0,  %%ebx \n\t"
                     " movl $4,  %%eax \n\t"
                     " int $0x80       \n\t"
                     ::: "%eax", "%ebx", "%ecx", "%edx"
                    );
Run Code Online (Sandbox Code Playgroud)

80美元是ascii中的'P',但是没有返回任何内容.

任何建议非常感谢!

c linux gcc system-calls inline-assembly

4
推荐指数
2
解决办法
3671
查看次数

总线错误:在Mac OS X上使用GCC进行内联x86组装

当我尝试在Snow Leopard上运行使用gcc 4.2.1编译的代码时,我收到"总线错误"

#include <stdio.h>

/*__declspec(naked)*/ void
doStuff(unsigned long int val, unsigned long int flags, unsigned char *result)
{
    __asm{
        push eax
        push ebx
       push ecx
        push edx

        mov eax, dword ptr[esp + 24]//val
        mov ebx, dword ptr[esp + 28]//flags
        //mov ecx, dword ptr[esp + 32]//result

        and eax, ebx
        mov result, eax

        pop edx
        pop ecx
        pop ebx
        pop eax

        ret
    }
}

int main(int argc, char *argv[])
{
    unsigned long val = 0xAA00A1F2; 
    unsigned long flags = 0x00100001;   
    unsigned …
Run Code Online (Sandbox Code Playgroud)

macos assembly gcc

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

如何从汇编调用 C 函数以及如何静态链接它?

我正在玩弄并试图了解计算机和程序的低级操作。为此,我正在尝试链接 Assembly 和 C。

我有2个程序文件:

“callee.c”中的一些C代码:

#include <unistd.h>

void my_c_func() {
  write(1, "Hello, World!\n", 14);
  return;
}
Run Code Online (Sandbox Code Playgroud)

我在“caller.asm”中还有一些 GAS x86_64 程序集:

.text

.globl my_entry_pt

my_entry_pt:
  # call my c function
  call my_c_func # this function has no parameters and no return data

  # make the 'exit' system call
  mov $60, %rax # set the syscall to the index of 'exit' (60)
  mov $0, %rdi # set the single parameter, the exit code to 0 for normal exit
  syscall
Run Code Online (Sandbox Code Playgroud)

我可以像这样构建和执行程序:

$ …
Run Code Online (Sandbox Code Playgroud)

c linux assembly gcc x86-64

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

对于启用优化的大型数组,内联汇编数组总和基准时间接近于零,即使使用结果

我编写了两个获取数组总和的函数,第一个是用 C++ 编写的,另一个是用内联汇编 (x86-64) 编写的,我比较了这两个函数在我的设备上的性能。

  • 如果在编译期间未启用-O标志,则使用内联汇编的函数几乎比 C++ 版本快 4-5 倍。

    cpp time : 543070068 nanoseconds
    cpp time : 547990578 nanoseconds
    
    asm time : 185495494 nanoseconds
    asm time : 188597476 nanoseconds
    
    Run Code Online (Sandbox Code Playgroud)
  • 如果-O标志设置为-O1,它们会产生相同的性能。

    cpp time : 177510914 nanoseconds
    cpp time : 178084988 nanoseconds
    
    asm time : 179036546 nanoseconds
    asm time : 181641378 nanoseconds
    
    Run Code Online (Sandbox Code Playgroud)
  • 但是,如果我尝试将-O标志设置为-O2-O3,则使用内联汇编编写的函数会得到不寻常的2-3 位纳秒性能,该性能速度很快(至少对我来说,请耐心等待,因为我对汇编编程没有扎实的经验,所以我不知道它与用 C++ 编写的程序相比有多快或多慢。)

    cpp time : 177522894 nanoseconds
    cpp time : 183816275 nanoseconds …
    Run Code Online (Sandbox Code Playgroud)

c++ optimization performance gcc inline-assembly

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