2017-02-10 116 views
0

我在編譯彙編代碼(nasm)時遇到了麻煩。鏈接彙編到GCC的NASM代碼

在Linux(elf32)上使用g ++編譯後不會失敗,但是當我試圖用i686-w64-mingw32-g ++(對於Win32)編譯時失敗。

我build.sh腳本:

#!/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 

有彙編代碼:

[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; 
} 

我明明做錯事,因爲我我在使用build.sh腳本時總是得到相同的錯誤:

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

我該如何解決這個問題?

+0

@ smac89:在* wct.obj *,即NASM上市編譯成目標代碼。我想使用未修飾和裝飾符號之間存在不匹配。 NASM或者摧毀它,或者GCC。無論哪種方式,它也需要一個調用約定。 – IInspectable

+0

@Inspectable,我該如何調用約定? –

+1

請查閱您的[編譯器手冊](https://gcc.gnu.org/onlinedocs/gcc/x86-Function-Attributes.html)。 – IInspectable

回答

0

在Windows上,GCC編譯器需要外部符號中的前導下劃線。因此,將asm文件中的所有wct更改爲_wct

如果你想測試在Windows程序和在Linux中,你可以「全球化」的兩個連續標號:wct_wct

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

的Linux得到wct沒有下劃線和Windows與它得到它。

順便說一句:彙編程序是C函數,必須遵循CDECL calling convention。該功能可以自由更改寄存器EAX,ECXEDX(保存主叫方)。其他寄存器(EBX,ESI,EDI,EBP)必須保持不變。如果函數需要使用它們,它具有保存和恢復它們(被調用函數保存):

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