Running asm procedure in cpp file

2019-08-04 13:08发布

问题:

I am trying to run procedure from asm file in cpp file but i get such errors:

Error   1   error LNK2019: unresolved external symbol _calka referenced in function _main   D:\Addem\main.obj   Project
Error   2   error LNK1120: 1 unresolved externals   D:\Addem\Debug\Project.exe  1   1   Project

Here is my main.cpp:

#include <iostream>
using namespace std; 

extern "C" void calka();

int main()
{
    calka();

    system("Pause");
    return 0;
}

And my calka.asm

; The calka Subroutine    (calka.asm)
public _calka                  

INCLUDELIB kernel32.lib
INCLUDELIB user32.lib
INCLUDELIB Irvine32.lib
INCLUDE Irvine32.inc
INCLUDE macros.inc



.data
BUFFER_SIZE = 50
buffer BYTE BUFFER_SIZE DUP(?)
filename    BYTE 80 DUP(0)
fileHandle  HANDLE ?
Rozmiar dw ?
Znak db ?
Suma dw ?
Minus db 0
wynik dw ?
temp dd ?

.code
_calka proc near

; Let user input a filename.
    mWrite "Podaj nazwe pliku (z rozszerzeniem): "
    mov edx,OFFSET filename
    mov ecx,SIZEOF filename
    call    ReadString

; Open the file for input.
    mov edx,OFFSET filename
    call    OpenInputFile
    mov fileHandle,eax

; Check for errors.
    cmp eax,INVALID_HANDLE_VALUE        ; error opening file?
    jne file_ok                 ; no: skip
    mWrite <"Cannot open file",0dh,0ah>
    jmp quit                        ; and quit
file_ok:

; Read the file into a buffer.
    mov edx,OFFSET buffer
    mov ecx,BUFFER_SIZE
    call    ReadFromFile
    jnc check_buffer_size           ; error reading?
    mWrite "Error reading file. "       ; yes: show error message
    call    WriteWindowsMsg
    jmp close_file

check_buffer_size:
    cmp eax,BUFFER_SIZE         ; buffer large enough?
    jb  buf_size_ok             ; yes
    mWrite <"Error: Buffer too small for the file",0dh,0ah>
    jmp quit                        ; and quit

buf_size_ok:    
    mov buffer[eax],0       ; insert null terminator
    ;mWrite "File size: "
    ;call   WriteDec            ; display file size
    ;call   Crlf

; Display the buffer.


; Pytanie o wielkosc przedzialu

    mWrite "Podaj wielkosc przedzialu h na osi x: "
    mov edx,OFFSET Rozmiar
    mov ecx,SIZEOF Rozmiar
    call    ReadDec

    mov Rozmiar, ax


    ;mWrite <"Buffer:",0dh,0ah,0dh,0ah>
    ;mov    edx,OFFSET buffer   ; display the buffer
    ;call   WriteString
    ;call   Crlf

    mov ecx, 15
    mov ebx, OFFSET buffer

mov si, 0
        jmp odczyt1
odczyt:
        mov ebx, temp
        inc ebx

odczyt1:
        mov cl, byte ptr [ebx]
        mov Znak, cl

        mov temp, ebx

        cmp Znak, '$' ;koniec pliku
        je koniec
        cmp Znak, 3bh ;srednik - nastepna liczba
        je nastepna
        cmp Znak, 20h ;spacja - ponowne wczytanie
        je odczyt
        cmp Znak, '-'
        je Zmien_znak


        mov al, Znak
        sub al, 30h
        mov bl, al
        mov bh, 0
        mov ax, 10
        mul si
        add ax, bx
        mov si, ax
        jmp odczyt

Zmien_znak:
        mov Minus, 1
        jmp odczyt

nastepna:
        cmp Minus, 0
        je dodaj
        jne odejm
dodaj:
        add Suma, si
        mov si, 0
        jmp odczyt
odejm:
        sub Suma, si
        mov Minus, 0
        mov si, 0
        jmp odczyt

koniec:
        cmp Minus, 0
        je dod
        jne minu
dod:
        add Suma, si
        mov si, 0
        jmp kon
minu:
        sub Suma, si
        mov Minus, 0
        mov si, 0
kon:
        mov ax, Suma
        mul Rozmiar

    mWrite "Wynik calkowania: "
    cmp ax,0
    ;mov ebx, eax
    jg plus
    mWrite "-"
    mov bx, 0
    sub bx, ax
    mov ax, bx

plus:
    call WriteDec


close_file:
    mov eax,fileHandle
    call    CloseFile

    ; Zeby aplikacja sie nie zamknela, heheszki :D
    mov edx,OFFSET Rozmiar
    mov ecx,SIZEOF Rozmiar
    call    ReadString

quit:
    exit
_calka ENDP

END

I have tried everything what I can focus on - adding obj files to linker and so on. I only want to type the name of file, read date from it and calculate it. Calka.asm works well unless I try to get it work in my cpp file.

What am I doing wrong?

回答1:

Irvine32.inc includes SmallWin.inc and that sets .MODEL flat, stdcall. So, every procedure will be decorated by default as if the calling convention were STDCALL. _calka becomes _calka@0. For the CDECL calling convention needed for main.cpp you have to override the default calling convention for the procedure with PROC C. Now the underscore will be added automatically. TLDR: calka proc C.

The best is, you create a new project. I'll describe the procedure for Microsoft Visual Studio 2015 RC on Windows 10. The procedure is quite similar for other VS versions.

1) Start Visual Studio 2015 RC and choose FILE - New - Project.

2) In the next window choose Win 32 Console Application.

3) You get a confirmation. Click on Next >.

4) In the next window choose
[X] Console application
[X] Empty project
Click on Finish.

5) Now choose PROJECT - Build Customizations....

6) In the next window tick masm(.targets,.props) and click on OK.

7) Create main.cpp: PROJECT - Add New Item.

8) In the next window choose C++File(.cpp), give it a name and click on Add.

9) Create calka.asm: PROJECT - Add New Item. In the next window choose C++File(.cpp) and - IMPORTANT! - give it a name with .asm extension. Click on Add.

10) Now check if the .asm file has the right properties. In the Solution Explorer right-click on the file and choose Properties.

11) In the Property Page you should see
Excluded From Build (empty) or No
Item Build Microsoft Macro Assembler
Click on OK.

12) Now you can fill the files with content.

You don't need system("Pause") since CTRL-F5 builds, runs and pauses the application.

In the .asm file delete

INCLUDELIB kernel32.lib
INCLUDELIB user32.lib

and let Visual Studio them automatically include. Add to

INCLUDELIB Irvine32.lib
INCLUDE Irvine32.inc
INCLUDE macros.inc

the full path to the files. That's better than to change the settings of VS.

Change

_calka proc near
...
_calka ENDP

to

calka PROC C
...
calka ENDP

13) Build and run with CTRL-F5.

The application will be opened in a new window.