News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

What's the matter with CRT functions?

Started by brouwer89, April 08, 2015, 01:10:23 AM

Previous topic - Next topic

brouwer89

Good day to everyone!
I'm a wannabe assembly programmer with just some experience in C/C++, and this is my first post, so please be patient if I look somewhat thickheaded! :icon_redface:

I was trying to see if I had understood the PROTO directive, so I created this simple program:

.386
.model flat, stdcall

includelib kernel32.lib
includelib msvcrt.lib

ExitProcess  proto stdcall nExitCode:dword
;Here's my naive attempt with _imp__printf
_imp__printf proto C args:vararg

.data
mystring db "Hello, world!",0

.code
main:
invoke _imp__printf, offset mystring
invoke ExitProcess, 0
end main


After successfully compiling it with
ml /c /coff file.asm /Fo file.obj
and linking it with
link /subsystem:console file.obj /out:file.exe ,
the program crashes every time I launch it.

By investigating what was wrong, I noticed that in msvcrt.inc the declaration for _imp__printf does not use PROTO, but is the following:

c_msvcrt typedef PROTO C :VARARG
externdef _imp__printf:PTR c_msvcrt


Substituting this declaration in place of my previous attempt, resulted in a working program.

The same type of declaration is done for every other CRT function in msvcrt.inc, while, in the other .inc files, Win32 functions are declared with PROTO.
As I'm able to understand from the code, CRT functions need to be declared as function pointers instead of "regular" functions.
Why this discrepancy? What's special/different with CRT function?

Thank a lot in advance! :biggrin:

hutch--

If you are using the MASM32 version of MSVCRT, you need to include BOTH the library AND the INCLUDE file. To avoid naming conflicts with other functions and MASM reserve words, the function names are prefixed with crt_ . Use the include file and library together and you get the range of MSVCRT functionality that is listed in the include file. You will of course need to know the argument count and types to pass to the MSVCRT functions.

TWell

I create msvcrt.lib with polib and this code works with poasm:
.386
.model flat, stdcall
option casemap :none

includelib kernel32.lib
includelib msvcrt.lib

ExitProcess  proto stdcall nExitCode:dword
printf proto cdecl args:vararg

.data
mystring db "Hello, world!",13,10,0

.code
main:
invoke printf, addr mystring
invoke ExitProcess, 0
end main
msvcrt.defLIBRARY msvcrt.dll
EXPORTS
printf

dedndave

i think what he's asking is - why msvcrt exports are handled differently than API exports

as far as i know, the difference is in the way the names are decorated (mangled)
and, as Hutch mentioned, some C names might conflict with masm names

if you look inside Kernel32.dll, you will find ExitProcess
if you look inside Msvcrt.dll, most names are decorated for the C compiler

Erol will probably correct me if i'm wrong   :biggrin:

brouwer89

Thanks for all the replies, they clarified a lot!  :biggrin:

dedndave is right: I was wondering why CRT and Win32 exports are treated differently. In fact I was conjecturing that the difference had to do with some property of the C runtime in general, something like a CRT initialization happening at runtime.
But I now understand, and TWell's reply confirms it, that actually the difference has to do with the MASM32's version of MSVCRT, and that other versions of the library treat CRT and Win32 exports in the same way.
I've also just tried the code I posted above with the version of MSVCRT bundled with Visual Studio, and that worked regularly.

To hutch--:
Actually I knew that I should have included also the .inc files, but I was, between other things, trying to experiment and understand how my code interfaces with the .lib files.  ;)