代码之家  ›  专栏  ›  技术社区  ›  kstanisz

尝试使用AVX程序集文件编译x86

  •  1
  • kstanisz  · 技术社区  · 9 年前

    我正在尝试使用命令编译以下程序集代码:

    nasm -f elf AvxScalarFloatingPointArithmetic_.asm
    

    组件代码:

        .model flat,c
            .const
    AbsMask qword 7fffffffffffffffh, 7fffffffffffffffh
            .code
    
    ; extern "C" void AvxSfpArithmetic_(double a, double b, double results[8]);
    ;
    ; Description:  The following function demonstrates how to use basic
    ;               scalar DPFP arithmetic instructions.
    ;
    ; Requires:     AVX
    
    AvxSfpArithmetic_ proc
            push ebp
            mov ebp,esp
    
    ; Load argument values
            mov eax,[ebp+24]                    ;eax = ptr to results array
            vmovsd xmm0,real8 ptr [ebp+8]       ;xmm0 = a
            vmovsd xmm1,real8 ptr [ebp+16]      ;xmm1 = b
    
    ; Perform basic arithmetic using AVX scalar DPFP instructions
            vaddsd xmm2,xmm0,xmm1               ;xmm2 = a + b
            vsubsd xmm3,xmm0,xmm1               ;xmm3 = a - b
            vmulsd xmm4,xmm0,xmm1               ;xmm4 = a * b
            vdivsd xmm5,xmm0,xmm1               ;xmm5 = a / b
            vmovsd real8 ptr [eax+0],xmm2       ;save a + b
            vmovsd real8 ptr [eax+8],xmm3       ;save a - b
            vmovsd real8 ptr [eax+16],xmm4      ;save a * b
            vmovsd real8 ptr [eax+24],xmm5      ;save a / b
    
    ; Compute min(a, b), max(a, b), sqrt(a) and fabs(b)
            vminsd xmm2,xmm0,xmm1               ;xmm2 = min(a, b)
            vmaxsd xmm3,xmm0,xmm1               ;xmm3 = max(a, b)
            vsqrtsd xmm4,xmm0,xmm0              ;xmm4 = sqrt(a)
            vandpd xmm5,xmm1,xmmword ptr [AbsMask]  ;xmm5 = fabs(b)
            vmovsd real8 ptr [eax+32],xmm2      ;save min(a, b)
            vmovsd real8 ptr [eax+40],xmm3      ;save max(a, b)
            vmovsd real8 ptr [eax+48],xmm4      ;save sqrt(a)
            vmovsd real8 ptr [eax+56],xmm5      ;save trunc(sqrt(a))
    
            pop ebp
            ret
    AvxSfpArithmetic_ endp
            end
    

    不幸的是,有一些错误:

    AvxScalarFloatingPointArithmetic_.asm:1: error: attempt to define a local label before any non-local labels
    AvxScalarFloatingPointArithmetic_.asm: error: parser: instruction expected
    AvxScalarFloatingPointArithmetic_.asm:2: error: attempt to define a local label before any non-local labels
    AvxScalarFloatingPointArithmetic_.asm:3: error: parser: instruction expected
    AvxScalarFloatingPointArithmetic_.asm:13: error: parser: instruction expected
    

    我应该如何编译这个文件? 代码应该正确。它摘自《现代X86汇编语言编程:32位、64位、SSE和AVX》一书。

    1 回复  |  直到 9 年前
        1
  •  3
  •   Community CDub    8 年前

    它看起来像MASM语法,而不是NASM语法。如果您知道NASM语法,那么移植到NASM就足够简单了,但这超出了SO的范围。看见 the manual 、和 标记wiki。

    JWasm 是一个可移植的MASM语法汇编程序,但要注意ABI的差异。这可以避免移植到NASM语法的麻烦,但不能将Windows API/库调用移植到Linux系统调用/库调用。

    如果您从C进行所有的I/O和其他系统调用,并在asm函数中进行数据处理,那么就可以了(除了调用Windows和SystemVABI之间的约定差异)。

    但是,如果您有直接使用WindowsAPI/库函数的asm函数,则会更加复杂。Linux上不存在这些API(除非我们讨论的是C99标准库函数,如 printf ).

    理论上,您可以在 wine ,但是调试正常的Linux可执行文件会更容易,因为 strace gdb 将直接可用。


    在这种情况下,您可以执行以下操作:

    default rel
    
    section .rodata
    AbsMask dq 7fffffffffffffffh, 7fffffffffffffffh
    
    section .text
    ; extern "C" void AvxSfpArithmetic_(double a, double b, double results[8]);
    global AvxSfpArithmetic
    AvxSfpArithmetic:
           push ebp
           mov ebp,esp       ; you don't need to waste instructions on this stack frame crap, as you will soon learn.
    
    ; Load argument values
            ;mov eax,[esp+20]                    ;eax = ptr to results array
            vmovsd xmm0,  [ebp+8]       ;xmm0 = a
            vmovsd xmm1,  [ebp+16]      ;xmm1 = b
            ...
    

    我刚删除 real8 ptr 因为指令暗示操作数大小刚好合适。 qword [ebp+8] 会奏效的。

    如果只想将AND掩码加载到寄存器中(在循环之前),而不是直接从内存中使用它,那么应该考虑 generating it on the fly 具有 pcmpeqw xmm7,xmm7 / psrlq xmm7, 1 .


    在64位代码中,SystemVABI(在Linux上使用)与Windows不同,因此,如果您书中的64位示例使用Windows调用约定,您必须处理这一点。你可以用 __attribute__((ms_abi)) 在C原型上。

    32位SysVABI使用的调用基本上与Window兼容,所有参数都在堆栈中。IDK,如果它完全不同,例如对于struct返回。