News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Chapter 13 - High Level Language Interface

Started by TheGodOfKratos, April 26, 2017, 01:20:20 AM

Previous topic - Next topic

TheGodOfKratos

I've been playing with the "Directory Listing Program" in 13.3.5 of Kips book. It was a learning/tweaking process to get it working. And now I know how but I don't understand why.

5 standard C++ functions are called from the .asm source code: _printf, _scanf, _system, _fopen, and _fclose. Well, only 3 of them are recognized by the linker "wihout" having used them in the main .cpp file. I can call _system, _fopen, and _fclose from the .asm source code and during the linker phase they are successfully resolved external symbols. However, the linker seems to be unable to resolve the external symbols _printf and _scanf "unless" I call printf and scanf at least once from the main.cpp file.
When I do the calls from the .cpp file (that is scanf and printf) the linker resolves all 5 external symbols successively. 3 out of 5 isn't bad, right? But why the bias, what's really going on?

jj2007

Why should the linker bother with _printf and _scanf if you don't use them?
Why don't you post the exact error messages here?

TheGodOfKratos

Why does the linker bother with _system, _fopen, and _fclose even though they aren't used at all in the main .cpp file? :) That was part of my question.

I'm calling 5 standard C++ functions from an .asm file (.obj ultimately). The linker resolves 3 of the 5 "without" having "first" called them in the main .cpp file. So, it reports _printf and _scanf as unresolved.

I fix this by calling 2 out of the 5 in the main.cpp file. But why must I do this for these 2 when I didn't do it for the other 3?


LNK2019: unresolved external symbol _printf rferenced in function _asm_main FIle: asmMain.obj

jj2007

Quote from: TheGodOfKratos on April 26, 2017, 02:19:52 AMI'm calling 5 standard C++ functions from an .asm file (.obj ultimately).

Maybe the linker looks for them because you are trying to use them in your asm/obj file?
Have you tried externdef "C"... in your cpp file?

Can't help you more right now, I can't find my crystal ball :(

TheGodOfKratos

#4
My guess is Visual Studio includes one of the required .libs unconditionally which _system, _fopen, and _fclose "happen by chance" to reside in. The _printf and _scanf containing .lib doesn't get linked unless the main .cpp file see's it as necessary.

**UPDATE**: So yeah, my theory seems to be correct. Windows does some crazy stuff behind the scenes with printf and scanf. For starters, Kip gave prototypes for the C++ vprintf and vscanf functions, not the regular printf and scanf functions. I still don't understand all of it. Still working on figuring it out. May take a few....years.



// ConsoleApplication1.cpp : Defines the entry point for the console application.
//


#include <iostream>
//#include <fstream>
//#include <cstdlib>

using namespace std;

extern "C" void asm_main(); // asm startup proc

void main()
{
asm_main();

int age;
char fname[60], lname[60];
float hourlyWage;

/* uncomment this code as a hack to fix the 2 unresolved external symbols reported by the linker, dunno why but this fixes the problem
printf("\n\nPlease enter your age, first and last name, and hourly wage: ");
scanf("%d %s %s %f", &age, fname, lname, &hourlyWage);
printf("\n\nYou entered this data: %d %s %s %.2f ", age, fname, lname, hourlyWage);
*/
}





; ASM program launched from C++ (asmMain.asm)

.586
.MODEL flat,C

; Standard C library functions:
system PROTO, pCommand:PTR BYTE
printf PROTO, pString:PTR BYTE, args:VARARG
scanf PROTO, pFormat:PTR BYTE, pBuffer:PTR BYTE, args:VARARG
fopen PROTO, mode:PTR BYTE, filename:PTR BYTE
fclose PROTO, pFile:DWORD

BUFFER_SIZE = 5000

.data

str1 BYTE "cls",0
str2 BYTE "dir/w",0
str3 BYTE "Enter the name of a file:",0
str4 BYTE "%s",0
str5 BYTE "cannot open file", 0dh,0ah,0
str6 BYTE "The file has been opened",0dh,0ah,0
modeStr BYTE "r", 0

fileName BYTE 60 DUP(0)
pBuf DWORD ?
pFile DWORD ?

.code

asm_main PROC C

; clear the screen, display disk directory
INVOKE system, ADDR str1
INVOKE system, ADDR str2

; ask for a filename
INVOKE printf, ADDR str3
INVOKE scanf, ADDR str4, ADDR filename

; try to open the file
INVOKE fopen, ADDR fileName, ADDR modeStr
mov pFile, eax

.IF eax == 0 ; cannot open file?
INVOKE printf, ADDR str5
jmp quit
.ELSE
INVOKE printf, ADDR str6
.ENDIF
; Close the file
INVOKE fclose, pFile

quit:
ret ; return to C++ main

asm_main ENDP

END