News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Link Error, unresolved external symbol

Started by psault, February 07, 2009, 03:04:21 AM

Previous topic - Next topic

psault

I really don't know if I have any clue of what I am doing.  I am trying to write a "readkey" function using assembler, and link it with some C++ code.
This is what I have:


.386
.model FLAT, STDCALL
OPTION CASEMAP:NONE

INCLUDE c:\masm32\include\windows.inc
INCLUDE c:\masm32\include\kernel32.inc
INCLUDELIB c:\masm32\lib\kernel32.lib

.data
         KeyEventRecord STRUCT
                  bKeyDown          WORD 0
                  wRepeatCount      WORD 0
                  wVirtualKeyCode   WORD 0
                  wVirtualScanCode  WORD 0
                  wCharSizeChar     WORD 0
                  dwControlKeyState DWORD 0
         KeyEventRecord ENDS

         IRecord STRUCT
                  eventType         WORD 0
                  keyEvent          KeyEventRecord <>
         IRecord ENDS

         hStdIn            DWORD 0
         pInputRecord      IRecord <>
         nRecordsRead      WORD 0

.code
start PROC
         INVOKE   GetStdHandle, STD_INPUT_HANDLE
         mov      hStdIn, eax

lp1:     INVOKE   ReadConsoleInput, hStdIn, ADDR pInputRecord, 1, ADDR nRecordsRead
         mov      ax, pInputRecord.eventType
         cmp      ax, KEY_EVENT
         jne      lp1
         movzx    eax, pInputRecord.keyEvent.wCharSizeChar
         push     eax
         INVOKE   ExitProcess, 0
start ENDP
END start


My C++ Code is simple:


#include <iostream>

extern "C" { char _stdcall start(void); }

int main()
{
  char c;
  std::cout << "test" << std::endl;
  c = start();
  std::cout << c << std::endl;
}


I assemble the assembly code with:

Quote
ml /c /coff readkey.asm

I try to link using:

Quote
cl readkeyt.cpp readkey.obj /link /subsystem:console

This is my output:

Quote
C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\INCLUDE\xlocale(342) : warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc
Microsoft (R) Incremental Linker Version 9.00.30729.01
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:readkeyt.exe
/subsystem:console
readkeyt.obj
readkey.obj
LIBCMT.lib(a_env.obj) : error LNK2019: unresolved external symbol __imp__GetEnvironmentStrings@0 referenced in function ___crtGetEnvironmentStringsA
readkeyt.exe : fatal error LNK1120: 1 unresolved externals

If I compile/link with:

Quote
cl /MD readkeyt.cpp readkey.obj /link /subsystem:console

It does not error out on me, but the program does not produce any output.  It does wait for a keypress before returning to the command prompt.

I would appreciate any kind of comments on what I am trying to do, especially if someone can help me get this to work.
I was unable to resolve this problem on my own using the search.

Thanks!

~psault

MichaelW

I'm not set up to do anything with C++, but I think to start out the asm procedure should be very simple and should not call any library or API functions (to eliminate as many failure points as possible). Perhaps something like:

testproc proc C
  mov eax, 123
  ret
testproc endp


You would simply call it from your C++ code and display the return value.
eschew obfuscation

japheth

There are a few errors:

1. if you want to call your assembly routine from C and both object modules are linked into one binary, don't place "start" behind the END directive! The END directive must have NO argument then. Also, your 'start' proc should do a simple RET then, it mustn't call ExitProcess.

2. Your definition of KeyEventRecord isn't correct. There's one already in windows.inc, it's called KEY_EVENT_RECORD.

3. Your definition of IRecord isn't correct either. It's name is INPUT_RECORD and it's contained in windows.inc as well. It's also important that the keyevent member starts at offset 4 in the structure.

4. nRecordsRead should be of size 4, not size 2

Mark Jones

#3
I have a similar issue with "unresolved external symbol __imp__GetEnvironmentStrings@0" from the v5.12 MS linker when referencing the libcmt.lib file (and oldnames.lib) from assembler. I'm not sure what is going on yet, but am also looking into it. ("GetEnvironmentStrings" is, or was, a Kernel32 import.)

Edit 1: Hutch might hit on this issue here.

Edit 2: Interesting. At first glance, the import could be resolved by adding the following:

include msvcrt.inc
includelib "C:\Program Files\Microsoft Visual Studio 9.0\VC\lib\msvcrt.lib"


However, the executable would not run. Thinking this may be a conflict of file versions, the MSVCRT90.DLL file was ran through DLL2INC and POLIB to produce a new set of .inc and .libs. These however, also lack the definition for "__imp__GetEnvironmentStrings@0". Hmmmm indeed.
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

Mark Jones

I did get my executable to run when the VC 9.0 linker created a *.exe.manifest file, but the linker placed a large-ish wrapper on the routines and requires MSVCRT90.dll -- not ideal.

Psault, have you gotten your code working yet?
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

dedndave

i am guessing that the lib path environment variables are not set up to find the visual studio libraries
i am having virus troubles or i could be more help

dedndave

    At this link (scrolldown a bit) is info on how to set up environment variables for masm (folder names are different than masm32).

http://faculty.kfupm.edu.sa/COE/mudawar/coe205/tools/index.htm#Installing

    However, because you also have vs2008 and are using vista 64, your lib and include paths should look like this, I believe:

INCLUDE=C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\INCLUDE;C:\masm32\include

LIB=C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\LIB;C:\masm32\lib

    With Visual Studio 2008, there are a variety of other environment variables, but these are the ones that will cause "unresolved external" errors.

I hope this helps,
    Dave

dedndave

oh ! - you may also have folders in these paths for the psdk

psault

Thanks, all, for your responses.

japheth - Thank you for telling me about the data structures being available through the include file.

dedndave - Thanks!  My include and library paths are set correctly, and when I removed "c:\masm32\lib\" from my INCLUDELIB directives, the linker had no problems with it.

My assembler function returns upon any kind of keypress.  Not quite what I want, but still very interesting to see the two object files working together like this.

~psault

dedndave

lol - yes - I remember the first time I linked an asm obj with basic compiler (ms version 1.0 - lol).
It kinda gives you a heady feeling. Of course, since then, I have written many C-callable routines.