Author Topic: Chapter 13 - High Level Language Interface  (Read 429 times)

TheGodOfKratos

  • Regular Member
  • *
  • Posts: 13
  • Because I Can
Chapter 13 - High Level Language Interface
« on: April 26, 2017, 01:20:20 AM »
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?
Visual Studio 2017 - Microsoft's MASM

jj2007

  • Member
  • *****
  • Posts: 7752
  • Assembler is fun ;-)
    • MasmBasic
Re: Chapter 13 - High Level Language Interface
« Reply #1 on: April 26, 2017, 02:01:01 AM »
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

  • Regular Member
  • *
  • Posts: 13
  • Because I Can
Re: Chapter 13 - High Level Language Interface
« Reply #2 on: April 26, 2017, 02:19:52 AM »
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?

Code: [Select]
LNK2019: unresolved external symbol _printf rferenced in function _asm_main FIle: asmMain.obj
Visual Studio 2017 - Microsoft's MASM

jj2007

  • Member
  • *****
  • Posts: 7752
  • Assembler is fun ;-)
    • MasmBasic
Re: Chapter 13 - High Level Language Interface
« Reply #3 on: April 26, 2017, 02:29:39 AM »
I'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

  • Regular Member
  • *
  • Posts: 13
  • Because I Can
Re: Chapter 13 - High Level Language Interface
« Reply #4 on: April 26, 2017, 02:40:53 AM »
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.

Code: [Select]

// 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);
*/
}


Code: [Select]

; 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
« Last Edit: April 26, 2017, 07:33:53 AM by TheGodOfKratos »
Visual Studio 2017 - Microsoft's MASM