【问题标题】:Trying to compile x86 with AVX assembly file尝试使用 AVX 程序集文件编译 x86
【发布时间】:2016-05-23 21:33:12
【问题描述】:

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

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》一书。

【问题讨论】:

  • 这不是nasm 语法。看起来更像masm。使用它,否则您将需要调整语法。如果它来自一本书,我假设他们告诉你使用什么汇编程序。
  • 来自亚马逊上这本书的简介:“这本书的主要读者是 Windows 软件开发人员,因为示例代码将使用 Visual C++ 和 Microsoft Macro Assembler 创建。”
  • 有关将 MASM 源转换为 NASM 的提示,请参阅 this article

标签: assembly nasm x86-64 intel avx


【解决方案1】:

它看起来像 MASM 语法,而不是 NASM 语法。如果您知道 NASM 语法,那么移植到 NASM 就足够简单了,但是在 SO 答案的范围之外教您。请参阅 the manual 标签 wiki。

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

如果您从 C 执行所有 I/O 和其他系统调用,并在您的 asm 函数中执行数据处理,那么您会没事的(Windows 和 SystemV ABI 之间的调用约定差异除外)。

但是,如果您有直接使用 Windows API/库函数的 asm 函数,那就更复杂了。 Linux 上不存在这些 API(除非我们谈论的是 C99 标准库函数,例如 printf)。

理论上,您可以在 wine 下运行您的 Windows 代码,但您可以更轻松地调试普通的 Linux 可执行文件,因为 stracegdb 可以直接使用。


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

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 flypcmpeqw xmm7,xmm7 / psrlq xmm7, 1 结合使用。


在 64 位代码中,SystemV ABI(在 Linux 上使用)与 Windows 不同,因此如果您书中的 64 位示例使用 Windows 调用约定,您将不得不处理它。您可以在 C 原型上使用__attribute__((ms_abi))

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

【讨论】:

  • Linux 汇编器可以理解 MASM(兼容)语法。尝试使用JWasm
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-14
  • 1970-01-01
  • 2018-10-07
  • 2011-09-06
  • 1970-01-01
  • 2011-10-28
相关资源
最近更新 更多