Earl Grey
Earl Grey

Reputation: 11

Calling C/C++ functions in 64-bit MASM files

So I'm new to this low-level programming and I'm trying to call the stdio.h function printf() in my assembly source file, that is linked to my C++ source file.

64-bit MASM file:

option casemap:none

.data

    string byte 'Hello Biss',10,0

.code 
    externdef printf:proc

    public asmFunc
    asmFunc proc
    sub rsp,56
    
    
    lea rcx, string
    call printf
    
    add rsp,56
ret

asmFunc endp
end

my asmFunc is being called by a C++ program:

#include <stdio.h>

extern "C"
{
    void asmFunc();
};

int main()
{
    printf("some text\n");
    asmFunc();
}

The problem is, that the code only works if I already call the print() function somewhere else in the C++ source file (see above). As soon as I delete the <printf("some text\n");> line, I get a Linking error in Visual Studio:

I assume the linker doesn't see the stdio.h file being used in my C++ source file and tries to optimize it by excluding this line(?).

Now I could obviously just solve this by using the printf() somewhere in the code, but as I'm trying to write this test code as efficiently as possible, this doesn't seem optimal...

Any advice on what is the best way to handle this?

Upvotes: 0

Views: 431

Answers (1)

MSalters
MSalters

Reputation: 180205

I assume the linker doesn't see the stdio.h file being used in my C++ source file

Correct. That's an #include. This is processed by the preprocessor. It inserts a bunch of function declarations such as printf and scanf into your Translation Unit. The function definitions are somewhere else, that's the job of the linker.

and tries to optimize it by excluding this line(?).

Incorrect. The linker simply has no work to do. Neither printf nor scanf is used by your C++ Translation Unit.

The true problem appears to be that MASM does not tell the linker that it needs printf to be linked to the executable. Assembly is of course a very primitive language; you basically ask the linker to insert the address of the printf function. That assumes that the printf function is already part of your executable, whih in turns implies that somebody else asked to include printf.

Usually, this is not a problem, because assembly is rarely used, when it's used it doesn't call out to non-assembly code, and when it does call out, it calls back to your own C or C++ functions. And the functions in your .cpp file are included by the linker because they're in your own .cpp files. printf has to come from a library, which works differently.

If MASM doesn't tell the linker what it needs, you can do it directly. /INCLUDE:printf tells the linker to add printf, even if no Translation Unit asked for it.

Upvotes: 1

Related Questions