首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >编写可移植的x86 asm函数(win/linux/osx),而不依赖于yasm/asm?

编写可移植的x86 asm函数(win/linux/osx),而不依赖于yasm/asm?
EN

Stack Overflow用户
提问于 2015-07-30 21:20:10
回答 1查看 543关注 0票数 2

par2有一个很小且相当干净的C++代码库,我认为它可以很好地构建在GNU、OS和MSVC++上。

我想合并一个x86-64ASM版本的一个功能,几乎所有的CPU时间。(有更多详细信息的邮件列表帖子.我的这里的实现/基准.)

本质可能是一个显而易见的解决方案,但gcc并没有生成足够好的代码,可以从64位寄存器中一次获取一个字节作为索引输入LUT。我也可能会花时间来安排指令,这样每个uop缓存行都有4个uop的倍数,因为uop吞吐量是瓶颈,即使输入/输出缓冲区的大小相当大。

我不想引入对yasm的依赖,因为很多人都安装了gcc,但没有安装。

有没有一种方法可以在一个单独的文件中编写一个函数,gcc / clang和MSVC可以组装?的目标是:

  • 没有额外的软件作为一个构建。(没有亚玛斯)
  • 每个asm函数只有一个版本。(没有维护相同代码的MASM & AT&T版本。)

Par2cmdline的构建系统是Unix的autoconf/automake,Windows .sln

我知道GNU汇编有一个.intel_syntax noprefix指令,但它只改变指令格式,而不是其他汇编程序指令。例如.align 16align 16。我的代码很简单,而且很小,所以可以使用C-预处理程序#define来处理不同的指令,如果可以的话。

我假设在C++中执行CPU检测和根据结果设置函数指针并不是一个问题,即使我必须为此使用一些#ifdef条件编译。

如果没有我所期望的解决方案,我可能会引入一个依赖于yasm的构建,并有一个./configure --no-asm选项来禁用在x86上构建的人的asm加速功能,而不是yasm可用。

在Windows和Linux中处理不同调用约定的首选计划是在我的C原型上为我的asm函数使用__attribute__((sysv_abi))。然后,我只需要为SysV ABI编写函数序言。MSVC有类似的东西吗?根据SysV ABI的某些功能,会把args放到regs中吗?(顺便说一句,这让编译器错误很痒,所以如果您想让代码与当前的gcc一起工作,请注意这个想法。)

EN

回答 1

Stack Overflow用户

发布于 2015-09-25 11:16:54

虽然我没有很好的解决方案来消除对特定汇编程序的依赖,但对于如何处理64位调用约定( Microsoft x64与SysV ABI )这两种不同的调用约定,我确实有一个建议。

最低的通用分母是Microsoft x64调用约定,因为它只能通过寄存器传递前四个值。因此,如果仅限于此,并使用宏定义寄存器,则可以轻松地将代码编译为Unix (Linux/BSD/OSX)和Windows。

例如,查看Agner‘s 阿斯利卜中的文件阿斯利卜

代码语言:javascript
复制
%IFDEF  WINDOWS
%define Rpar1   rcx                    ; function parameter 1
%define Rpar2   rdx                    ; function parameter 2
%define Rpar3   r8                     ; function parameter 3
%ENDIF
%IFDEF  UNIX
%define Rpar1   rdi                    ; function parameter 1
%define Rpar2   rsi                    ; function parameter 2
%define Rpar3   rdx                    ; function parameter 3
%ENDIF

        push    Rpar1                  ; dest
        push    Rpar2                  ; src
        call    A_strlen               ; length of dest
        push    rax                    ; strlen(dest)
        mov     Rpar1, [rsp+8]         ; src
        call    A_strlen               ; length of src
        pop     Rpar1                  ; strlen(dest)
        pop     Rpar2                  ; src
        add     Rpar1, [rsp]           ; dest + strlen(dest)
        lea     Rpar3, [rax+1]         ; strlen(src)+1
        call    A_memcpy               ; copy
        pop     rax                    ; return dest
        ret

;A_strcat ENDP

我不认为四个寄存器实际上是一个限制,因为如果您想要在程序集中编写某些东西,那么在这种情况下,调用开销的函数与函数本身相比应该是可以忽略不计的,因此,如果需要的话,在调用函数时将一些值推送/弹出不会对性能产生影响。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31734263

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档