0

I'm writing an assembly program (MASM compatible) for win64 and want to use the C function mainCRTStartup() if possible to set up the environment and pass the command line arguments. Can I do that somehow?

When you run a (console) C program, mainCRTStartup() is the first function to be called and it calls the program's main function. Where does the mainCRTStartup() function come from? Is it added by the compiler or the linker, or is it contained in the MSVCRT.DLL? I'm not using the Microsoft linker, I use JWasm and JWlink.

I know perfectly well how to call ordinary C functions from assembly, but mainCRTStartup() is very special and I'm not even sure it's a C function at all, maybe a windows OS function.

If I can call it somehow I need to pass my own main() along for callback.

Henrik
  • 332
  • 3
  • 12
  • @HarryJohnston - no, `mainCRTStartup` is part of `exe` - it entry point - so it can not be in `msvcrt.dll` – RbMm Jan 08 '17 at 01:51
  • As that code sets up the C runtime environment, it is not clear why you want to call it from assembly code. Typically it is the other way 'round: you cann an assembly function from C code. The first function called in a C program is `main`. – too honest for this site Jan 08 '17 at 01:53
  • @Olaf: use of the C runtime library from assembler is a fairly common practice. Makes life a lot easier to have `printf` and the like. – Harry Johnston Jan 08 '17 at 01:54
  • @HarryJohnston: That would still not be the correct way to call it from assmbly. Instead the assembly code should provide a `main` with the C standard conventions and have the crt linked normally. My comment stands: XY problem. – too honest for this site Jan 08 '17 at 01:56
  • 1
    @Olaf: Oh, I thought you meant it wasn't clear why he wanted to use the CRT from assembly code at all. As for "why" I'm guessing that he just doesn't know how to set the entry point, although it's also possible that he wants to run some other code first. It ought to work perfectly well either way. There's no reason why `mainCRTStartup` *has* to be the very first bit of code to run. – Harry Johnston Jan 08 '17 at 02:03
  • I just want mainCRTStartup() to do the job, that's all. Otherwise I'll have to write my own code for setting it all up and parsing the command line. Do you know of a better way? – Henrik Jan 08 '17 at 02:09
  • I already stated trhe common way. – too honest for this site Jan 08 '17 at 02:10
  • @HarryJohnston: It might help if you read my comment **carefully** and understand the implications. – too honest for this site Jan 08 '17 at 02:11
  • @Olaf: You mean I should write a C program instead of assembly? I can't do that. I have JWasm and JWlink and nothing else. – Henrik Jan 08 '17 at 02:13
  • Whatever JWasm and JWlink are. Not that you cannot use gcc or clang, but that was not my point! – too honest for this site Jan 08 '17 at 02:14
  • @Olaf: What IS your point? I don't understand. JWasm is an assembler and JWlink a linker. I'm working on win64. – Henrik Jan 08 '17 at 02:16
  • @Olaf: you may think your comments are clear as written, but [they really aren't](http://lesswrong.com/lw/ke/illusion_of_transparency_why_no_one_understands/). I have no idea what your point is either. – Harry Johnston Jan 08 '17 at 02:24
  • Just as an aside, third-party use of `msvcrt.dll` isn't officially supported. You may find there are oddities in the runtime library behaviour that don't match the publicly available documentation. – Harry Johnston Jan 08 '17 at 02:35
  • @RbMm: right you are. I don't really see why the application entry point couldn't have been inside the CRT DLL (the DLL is already loaded by the time the entry point is called, after all) but regardless of whether it could or not, it isn't. – Harry Johnston Jan 08 '17 at 02:58
  • @olaf i agree with Harry –  Jan 08 '17 at 02:58
  • simply entry point of PE file - must be in this PE file. entry point in extreme case can be imported function(`XXX`) and containing single instruction `jmp qword ptr [__imp_XXX]` but this instruction *inside* this PE. about specified `mainCRTStartup` - this function always *inside* exe, not depended of type of `CRT` we use(static or dynamic) – RbMm Jan 08 '17 at 11:08
  • So what is unclear about "That would still not be the correct way to call it from assmbly. **Instead the assembly code should provide a main with the C standard conventions and have the crt linked normally.**"? Leave the rest as-is, i.e. first the startup code is run, then your assembly `main` is called with all set up correctly and the arguments passed by normal C ABI. Sorry, but one should put at least **some** thoughts instead of blocking and just writing complaining comments. After all, this is what programming is about. – too honest for this site Jan 08 '17 at 13:03
  • @Olaf: well, one ambiguity is "linked normally" with no further explanation. I understood what you meant by that, since I have some familiarity with how the CRT works, but I doubt the OP did. In any case, your advice is not particularly helpful since we don't know how to do that with the JW toolset. (Which isn't to say that you shouldn't have suggested it. It's just that you still seem to think that we're ignoring your advice. We're not, we simply *don't know how to implement it*.) – Harry Johnston Jan 11 '17 at 22:01
  • Henrik, this might be relevant: http://stackoverflow.com/a/41598416/886887 – Harry Johnston Jan 11 '17 at 22:02
  • @HarryJohnston: Thanks, I know about that. It's not the problem. I have discovered that the import lib files constructed by JW contain function names that sometimes deviate slightly from the ones exported by MSVCRT.DLL . Also, these import libs don't offer all the functions exported by MSVCRT.DLL by far. So what I intend to do is create new .LIB files (import libs). – Henrik Jan 11 '17 at 22:28

1 Answers1

3

int mainCRTStartup() have no arguments. so you can not (or not need) direct pass arguments for it. he take command line or by call GetCommandLine or by calling __[w]getmainargs to MSVCRT.DLL or statically linked CRT code. (very depended from CRT version)

mainCRTStartup is EXE entry point. first code which executed from EXE but of course not first code which executed in process (all statically dll dependences already loaded and initialized (including MSVCRT.DLL if application use it )

mainCRTStartup come from LIB :libcmt.lib or msvcrt.lib or msvcurt.lib. when you link exe - at first you use some LIBs and OBJs as linker input and for EXE you must set /ENTRY:function option. you can set this function explicitly, or if you not do this - default will be used:

By default, the starting address is a function name from the C run-time library. The linker selects it according to the attributes of the program, as shown in the following table.

in your case this will be mainCRTStartup - linker will be search it in all LIBs and OBJs which you pass to him as input. if he not found it - you got error unresolved external symbol. if linker found it - he use it code as part of exe. so linker take code of mainCRTStartup from lib (for example even msvcrt.lib containing mainCRTStartup as code, but not as import thunk) and link it to exe.

mainCRTStartup is not a windows OS function. it just EXE entry point. not more.

I not exactly understand why you try todo. if you want simply use CRT in own assembly code - you need do next:

  1. implement _main or _wmain (for x86) or main or wmain (for x64)
  2. use say msvcrt.lib as linker input lib
  3. set /ENTRY:[w]mainCRTStartup in project settings or in MASM END [w]mainCRTStartup

if you want own custom function, which will be executed before mainCRTStartup - let name it start - you need change point 3:

  1. set /ENTRY:start in project settings or in MASM END start

and code of start

start PROC
; do something here
call [w]mainCRTStartup ; no args, can even jump instead call
start ENDP

and [w]mainCRTStartup alredy call your [w]main callback. you not need to pass own main because [w]mainCRTStartup called [w]main not by address but by name - so all what you need have [w]main implemented in your code. linker already bind call from [w]mainCRTStartup to your [w]main or say about unresolved symbol

RbMm
  • 31,280
  • 3
  • 35
  • 56
  • I don't imagine the OP has a copy of `msvcrt.lib` since he isn't using Microsoft build tools. Not sure whether he'll have a close-enough equivalent or not. – Harry Johnston Jan 08 '17 at 02:31
  • I do have msvcrt.lib . The problem is: When I follow RbMm's latter advice the program crashes with the message (from win) : Cannot find entry point mainCRTStartup in the DLL. Do I have to use the Microsoft linker for this to work? Is there a solution not requiring it? – Henrik Jan 08 '17 at 02:37
  • @HarryJohnston - but code of wmainCRTStarup not compiler or linker generated. it taked from LIB. about not Microsoft environment I not just correct understand.. hm even don't know are this is possible do without this environment – RbMm Jan 08 '17 at 02:37
  • @Henrik - you mean link error ? are you add `msvcrt.lib` to build ? – RbMm Jan 08 '17 at 02:39
  • @Henrik, where did the version of `msvcrt.lib` you are using come from? – Harry Johnston Jan 08 '17 at 02:40
  • @Henrik - you can download and use this - http://landinghub.visualstudio.com/visual-cpp-build-tools here compiler and linker and libs – RbMm Jan 08 '17 at 02:44
  • @RbMm: I'm using the JWlinker instead of the MS one. No, I don't mean link error, I mean windows runtime error with a message box coming up. The program crashes. Yes, I added includelib msvcrt.lib to my assembly code. Thanks for offering me MS tools, but no thanks, I want to solve this problem :) – Henrik Jan 08 '17 at 02:45
  • @HarryJohnston: The version of msvcrt.lib came with the JW package. There is a special one for 64 bit code. – Henrik Jan 08 '17 at 02:49
  • @Henrik - "Cannot find entry point mainCRTStartup in the DLL" - in which DLL ? your exe *import* `mainCRTStartup` ? from ? – RbMm Jan 08 '17 at 02:51
  • Sounds like the JW `msvcrt.lib` simply doesn't include the runtime library initialization code, possibly because that would violate Microsoft's copyright. (I wonder what MinGW does?) – Harry Johnston Jan 08 '17 at 02:51
  • @RbMm: It calls my program test.exe a DLL and says that mainCRTStartup cannot be found in there. That's all. I know no more. – Henrik Jan 08 '17 at 02:56
  • @HarryJohnston: That's a clue! Maybe you're right. But why doesn't JW say so? All right, maybe I'll just give up and write my own mainCRTStartup() function. Takes less time! But it's a challenging problem anyhow. – Henrik Jan 08 '17 at 02:58
  • Have you tried setting mainCRTStartup as the entry point, as RbMm's answer suggests first? Or just not specifying an entry point at all? (I'm thinking JW might have an built-in mechanism for initializing the CRT and your efforts to do so explicitly are confusing it.) – Harry Johnston Jan 08 '17 at 03:02
  • @HarryJohnston: In my assembly code I set no entry point, but in the call to the JWlinker I do: jwlink format win pe f %1.obj Libpath %JWinc%\Lib64 op start=mainCRTStartup so I tell it to use the standard entry point which must come from msvcrt.lib . The linker doesn't complain, everything seems fine, but the prog crashes. – Henrik Jan 08 '17 at 03:09
  • At this point I think only someone familiar with JW could answer. – Harry Johnston Jan 08 '17 at 03:14
  • @Henrik - `Cannot find entry point mainCRTStartup in the DLL` - windows error message in place `DLL` write specific dll name. and I ask about this specific dll name. say `msvcrt.dll` or ? `It calls my program test.exe a DLL and says that mainCRTStartup` - I can not understand this .. you build exe or dll ? what is actual EP or your PE , what he imported – RbMm Jan 08 '17 at 11:21
  • @RbMm: It's indeed an enigmatic message. The only file quoted is my own program file text.exe . It's an EXE, not a DLL. I now suspect that it's not a win message after all. Maybe the mainCRTStartup() function included in the JW (wininc) version of msvcrt.lib is just a placeholder, opening this box and reminding you in case you forget to write a mainCRTStartup() function of your own. – Henrik Jan 08 '17 at 17:30
  • @Henrik - hard to say based only on this info. need debug this `exe` to view what is really happens – RbMm Jan 08 '17 at 17:40