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
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.
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
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 (http://www.masm32.com/board/index.php?PHPSESSID=8b0c44760f320a182111c3613da5584c&topic=6067.0).
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.
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?
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
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
oh ! - you may also have folders in these paths for the psdk
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
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.