2017-02-10 3 views
0

Ich habe ein Problem mit einem kompilierenden Assembly-Code (Nasm).Link Assembly NASM-Code zu GCC

Auf Linux (Elf32) schlägt es nicht nach der Kompilierung mit g ++, aber wenn ich versuchte, es mit i686-w64-mingw32-g ++ (für Win32) zu bauen, schlug es fehl.

Mein build.sh Skript:

#!/bin/bash 

nasm -fwin32 wct.asm 
i686-w64-mingw32-g++ -m32 -O2 -Wall -fno-exceptions -ffloat-store -ffast-math -fno-rounding-math -fno-signaling-nans -fcx-limited-range -fno-math-errno -funsafe-math-optimizations -fassociative-math -freciprocal-math -ffinite-math-only -fno-signed-zeros -fno-trapping-math -frounding-math -fsingle-precision-constant -fcx-fortran-rules -fno-rtti -mfpmath=387 -mfancy-math-387 -fno-ident -fmerge-all-constants -mpreferred-stack-boundary=2 -falign-functions=1 -falign-jumps=1 -falign-loops=1 -fno-unroll-loops -fno-math-errno -s main.cpp wct.obj -o wct.exe 
strip --strip-unneeded wct.exe 

Es ist Assembler-Code:

[bits 32] 
    section .text 
    global wct 

    wct: 

    mov esi, [esp+4] 
    mov edi, esi 
    mov ecx, [esp+8] 

    @L: 
      lodsw 
      sub ax, 04141h 

      cmp al,0Fh 
      jne @F 
      dec al 
      jmp @E 
      @F: 
      cmp al,0Eh 
      jne @E 
      inc al 
      @E: 

      mov bx, ax 
      shr bx, 8 

      cmp bl,0Fh 
      jne @@F 
      dec bl 
      jmp @@E 
      @@F: 
      cmp bl,0Eh 
      jne @@E 
      inc bl 
      @@E: 

      shl al, 4 
      add ax, bx 
      stosb 
    loop @L 
    ret 

main.cpp:

#include <fstream> 

using namespace std; 

extern "C" int wct(char* buff, int N); 

#define N 1024*1024 

char buff[N]; 
ifstream in; 
ofstream out; 
int size; 

int main(int argc, char* argv[]) { 

    if (argc == 1) return 0; 

    in.open(argv[1], ios_base::in | ios_base::binary); 

    if (argc >= 3) 
     out.open(argv[2], ios_base::out | ios_base::binary); 

    if(in.is_open()) 
    { 
     while(!in.eof()) 
     { 
      in.read((char *)&buff, sizeof buff); 
      size = in.gcount()/2; 
      wct((char *)&buff, size); 

      if (out.is_open()) 
       out.write((char *)&buff, size); 
      else 
      { 
       out.close(); 
      } 
     } 
    } 

    in.close(); 
    out.close(); 

    return 0; 
} 

ich offensichtlich etwas nicht stimmt, weil ich tue, bekomme immer den gleichen Fehler bei der Verwendung von build.sh script:

/tmp/cc3SD7dA.o:main.cpp:(.text.startup+0x90): undefined reference to `wct' 
collect2: error: ld returned 1 exit status 

Wie kann ich das beheben?

+0

@ smac89: In * wct.obj *, der Objektcode, der die NASM zu kompilierten auflistet. Ich denke, es gibt eine Diskrepanz zwischen der Verwendung des undekorierten und dekorierten Symbols. Entweder NASM Mangels, oder GCC. So oder so, es braucht auch eine Aufrufkonvention. – IInspectable

+0

@Intspectable, wie kann ich Convention aufrufen? –

+1

Konsultieren Sie das [Handbuch des Compilers] (https://gcc.gnu.org/onlinedocs/gcc/x86-Function-Attributes.html). – IInspectable

Antwort

0

Unter Windows erwartet der GCC-Compiler einen führenden Unterstrich in externen Symbolen. Ändern Sie also alle wct in der asm-Datei in _wct.

Wenn Sie das Programm in Windows testen und in Linux können Sie „globalisieren“ zwei aufeinanderfolgende Etiketten: wct und _wct:

... 
global wct 
global _wct 
... 
wct: 
_wct: 
... 

Linux bekommt die wct ohne Unterstrich und Windows wird es mit ihm.

BTW: Die Montage ist eine C-Funktion und muss der CDECL calling convention folgen. Die Funktion kann die Register EAX, ECX und EDX (Anrufer gespeichert) frei ändern. Die anderen Register (EBX, ESI, EDI, EBP) müssen unverändert zurückgegeben werden. Wenn die Funktion, sie benutzen muss, hat sie zu speichern und diese wiederherstellen, (Angerufenen gespeichert):

wct: 
_wct: 

push esi    ; sp+= 4 
push edi    ; sp+= 4 
push ebx    ; sp+= 4 
         ; ====== 
         ; sp+= 12 
mov esi, [esp+16] 
mov edi, esi 
mov ecx, [esp+20] 

... 

pop ebx 
pop edi 
pop esi 
ret 
Verwandte Themen