2017-02-10 1 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はそれをmanglesかGCCのどちらかにします。いずれにしても、呼び出し規約が必要です。 – IInspectable

+0

@IInspectable、どのように私は国際大会を呼び出すことができますか? –

+1

[コンパイラのマニュアル](https://gcc.gnu.org/onlinedocs/gcc/x86-Function-Attributes.html)を参照してください。 – IInspectable

答えて

0

Windowsでは、GCCコンパイラは外部シンボルに先頭のアンダースコアが必要です。したがって、asmファイルのwctをすべて_wctに変更してください。

は、WindowsでプログラムをテストしたいとLinuxで使用すると、2つの連続したラベル「グローバル化」することができた場合:wct_wct

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

をLinuxには、アンダースコアなしwctを取得し、Windowsはそれでそれを取得します。

BTW:アセンブリプロシージャはC関数であり、CDECL calling conventionに従わなければなりません。この機能は、レジスタEAXECX、およびEDX(発信者が保存されている)を自由に変更することができます。他のレジスタ(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 
関連する問題