2016-05-23 8 views
1

Ich versuche, den folgenden Assembler-Code mit dem Befehl zu kompilieren:Versuch x86 mit AVX Baugruppendatei zu kompilieren

nasm -f elf AvxScalarFloatingPointArithmetic_.asm 

Assembly Code:

.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 

Leider gibt es einige Fehler:

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 

Wie soll ich diese Datei kompilieren? Der Code sollte korrekt sein. Es stammt aus dem Buch: "Moderne X86-Assembler-Programmierung: 32-Bit, 64-Bit, SSE und AVX".

+2

Das ist nicht 'Nasm' Syntax. Sieht eher aus wie "masm". Verwenden Sie das, oder Sie müssen die Syntax anpassen. Wenn es aus einem Buch stammt, nehme ich an, dass sie dir gesagt haben, welcher Assembler zu verwenden ist. – Jester

+0

Aus dem Klappentext des Buchs auf Amazon: * "Die primäre Zielgruppe für das Buch sind Windows-Softwareentwickler, da der Beispielcode mit Visual C++ und Microsoft Macro Assembler erstellt wird." * –

+0

Siehe [diesen Artikel] (http: // left404. com/2011/01/04/Converting-X 86-Assembly-von-Masm-zu-Nasm-3 /) für Tipps zum Konvertieren von MASM-Quelle zu NASM. –

Antwort

3

Es sieht wie MASM-Syntax aus, nicht NASM-Syntax. Die Portierung auf NASM ist einfach genug, wenn Sie die NASM-Syntax kennen, aber Ihnen das über den Rahmen einer SO-Antwort hinaus beibringen. Siehe the manual und das -Tag-Wiki.

JWasm ist ein tragbarer MASM-Syntax-Assembler, aber seien Sie vorsichtig bei ABI-Unterschieden. Dies kann die Portierung auf die NASM-Syntax erschweren, jedoch nicht die Portierung von Windows API-/Bibliotheksaufrufen auf Linux-Systemaufrufe/Bibliotheksaufrufe.

Wenn Sie alle Ihre E/A und andere Systemaufrufe von C ausführen und die Datenverarbeitung in Ihren asm-Funktionen durchführen, sind Sie in Ordnung (mit Ausnahme von Unterschieden zwischen den Windows- und SystemV-ABIs).

Wenn Sie jedoch asm-Funktionen haben, die Windows API/Bibliotheksfunktionen direkt verwenden, ist es komplizierter. Diese APIs existieren unter Linux nicht (es sei denn, wir sprechen über C99-Standardbibliotheksfunktionen wie printf).

Sie könnten theoretisch Ihren Windows-Code unter wine ausführen, aber Sie werden es leichter haben, normale Linux-Programme zu debuggen, da strace und gdb direkt verwendbar sind.


In diesem Fall könnte man so etwas tun:

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

Ich entfernte real8 ptr gerade da der Befehl die Operanden-Größe gerade fein impliziert. qword [ebp+8] würde funktionieren.

Wenn Sie diese UND-Maske in ein Register laden wollen gerade (vor einer Schleife) anstelle der Verwendung es pcmpeqw xmm7,xmm7/psrlq xmm7, 1 betrachten direkt aus dem Speicher, sollten Sie stattdessen generating it on the fly mit.


in 64-Bit-Code, der SystemV ABI (verwendet auf Linux) unterscheidet sich von Windows so, wenn die 64-Bit-Beispiele in Ihrem Buch das Windows verwenden Aufrufkonvention, werden Sie damit umgehen müssen. Sie könnten __attribute__((ms_abi)) auf dem C-Prototyp verwenden.

Der 32-Bit-SysV-ABI verwendet einen Aufruf, der grundsätzlich mit Windows kompatibel ist, mit allen Argumenten auf dem Stapel. IDK, wenn es sich überhaupt unterscheidet, z.B. für Strukturrückgaben.

+1

Dort sind ** Linux-Assembler, die MASM (kompatible) Syntax verstehen. Versuchen Sie es mit [JWasm] (https://github.com/JWasm/JWasm). – zx485

Verwandte Themen