Link assembly NASM code to GCC

为君一笑 提交于 2020-01-30 09:05:43

问题


I have a trouble with a compiling assembly code (nasm).

On Linux (elf32) it not fails after compilation using g++, but when I tried to build it with i686-w64-mingw32-g++ (for Win32) it failed.

My build.sh script:

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

There is assembly 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;
}

I am obviously doing something wrong, because of I am always getting the same error while using build.sh script:

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

How I can fix that?


回答1:


On Windows the GCC compiler expects a leading underscore in external symbols. So change all wct in the asm file to _wct.

If you want to test the program in Windows and in Linux you can "globalize" two consecutive labels: wct and _wct:

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

Linux gets the wct without underscore and Windows gets it with it.

BTW: The assembly procedure is a C function and has to follow the CDECL calling convention. The function can freely change the registers EAX, ECX, and EDX (caller saved). The other registers (EBX,ESI,EDI,EBP) have to be returned unchanged. If the function needs to use them, it has to save and restore them (callee saved):

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


来源:https://stackoverflow.com/questions/42169037/link-assembly-nasm-code-to-gcc

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!