2016-05-23 4 views
1

Я пытаюсь скомпилировать следующий код сборки с помощью команды: КодПопытка компиляции x86 с AVX файл сборки

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 

Unfortunatelly есть некоторые ошибки:

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».

+2

Это не синтаксис 'nasm'. Выглядит больше как 'masm'. Используйте это, иначе вам нужно будет настроить синтаксис. Если это из книги, я полагаю, они сказали вам, что использовать ассемблер. – Jester

+0

Из публикации книги на Amazon: * «Основная аудитория книги - разработчики программного обеспечения Windows, поскольку образец кода будет создан с использованием Visual C++ и Microsoft Macro Assembler». * –

+0

См. [Эту статью] (http: // left404. com/2011/01/04/conversion-x86-assembly-from-masm-to-nasm-3 /) для советов по преобразованию источника MASM в NASM. –

ответ

3

Он выглядит как синтаксис MASM, а не синтаксис NASM. Портирование в NASM достаточно просто, если вы знаете синтаксис NASM, но учите вас, что выходит за рамки ответа SO. См. the manual и тэги wiki .

JWasm - это портативный MASM-синтаксический ассемблер, но будьте осторожны с различиями ABI. Это может сэкономить проблемы при переносе на синтаксис NASM, но не переносить вызовы Windows API/библиотеки на вызовы системных вызовов Linux/библиотеки.

Если вы выполняете все свои операции ввода/вывода и другие системные вызовы с C и выполняете обработку данных в своих asm-функциях, вы будете в порядке (за исключением различий между вызовами между Windows и SystemV ABI).

Однако, если у вас есть функции asm, которые напрямую используют функции Windows API/библиотеки, это сложнее. Эти API не существуют в Linux (если мы не говорим о стандартных библиотечных функциях C99, таких как printf).

Вы можете теоретически запустить свой код Windows под номером 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] будет работать.

Если вы собираетесь просто загрузить И-маску в регистр (до цикла) вместо того, чтобы использовать его непосредственно из памяти, то вместо этого следует рассмотреть generating it on the fly с pcmpeqw xmm7,xmm7/psrlq xmm7, 1.


в 64-битном коде, SystemV ABI (используется в Linux) отличается от Windows, поэтому, если примеры 64bit в своей книге использовать Windows, соглашение о вызове, вы будете иметь дело с этим. Вы можете использовать __attribute__((ms_abi)) на прототипе C.

32-битный SysV ABI использует вызов, который в основном совместим с Window, со всеми аргументами в стеке. IDK, если он вообще отличается, например. для возврата структуры.

+1

Там ** являются ** сборщиками Linux, которые понимают синтаксис MASM (совместимый). Попробуйте использовать [JWasm] (https://github.com/JWasm/JWasm). – zx485

Смежные вопросы