News:

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

Main Menu

LINK : error LNK2001: unresolved external symbol _mainCRTStartup

Started by cyrus, September 15, 2024, 12:28:17 PM

Previous topic - Next topic

cyrus

I know this seems silly. I've been programming in assembly for a bit. started with 64-bit actually and now doing 32-bit stuff. For context, I'm not using masm32.exe. I'm actually using ml.exe from Visual Studio 2022. I have written programs with GNU as 32 as well. For that, I get functions through PEB from kernel32 and LoadLibrary and don't have any issues running it on any system since I am using an archane as.exe and ld.exe from mingw  :smiley: .

For my particular program written in ml format, I am using EXTERNDEF for my functions which works fine. I have tried using PEB but I am not able to retrieve LoadLibrary for some reason. I debugged it and it just fails so I know this ml is going through a different route or something is blocking me from retrieving LoadLibrary so I can get ucrtbase.dll and msvcrt.dll to get my functions. My goal is to use my program on systems that may not have Visual Studio installed  :rolleyes: . Therefore, I noticed out of 4 system, 2 have failed with the typical VCRUNTIME140.DLL not found. I know this has to do with CRT. I am not sure how to statically link my program. I'm using the following directive:

.386   
.model flat, c
option casemap :none

cyrus

I do in fact. In my code:

entry:
main proc

[everything between]

end entry
endp

I have also omitted entry and end entry and simply referenced it when compiling by appending /entry:main

zedd151

Okay, it is something different than what I was thinking... sorry.


But but, wait


Should be
main proc
... ... ...
main endp

end main

And for link.exe...

/entry:main

cyrus

I appreciate the response. I'm just confused about why I am not able to build a static binary. With ml64.exe I don't have this issue but I can't code my program in 64-bits because the functions I need are written in 32-bits.

cyrus

Quote from: zedd151 on September 15, 2024, 12:35:22 PMOkay, it is something different than what I was thinking... sorry.


But but, wait


Should be

main proc
... ... ...
main endp

end

Yeah but I mentioned in my post above yours, I did try omitting that but it did not work  :smiley:

zedd151

Can you post or attach your source code?
Or you could make a simple test program that only calls MessageBox and ExitProcess, to see if that will assemble and link.

I assume from what you posted above, that you are using Visual Studio?
And just for clarification, are you working with 32 or 64 bit for this project?
Another thing, you don't need to put 'entry' anywhere in the source code.

cyrus

; ml.exe /c /coff print-exit.asm && link.exe /SUBSYSTEM:console print-exit.obj

.386   
.model flat, c
option casemap :none


.data
; including these will cause an error when running on a non-visual studio installed system
includelib ucrt.lib
includelib msvcrt.lib   ; strstr is in this? lol
includelib legacy_stdio_definitions.lib
includelib kernel32.lib


EXTERNDEF printf: PROC
EXTERNDEF fopen: PROC
EXTERNDEF fread: PROC
EXTERNDEF fwrite: PROC
EXTERNDEF fclose: PROC
EXTERNDEF exit: PROC
EXTERNDEF ExitProcess: PROC

hello db "hello",10,0

.code


main proc

push offset hello
call printf
add esp, 4

call exit

    call ExitProcess

main endp

end

I can't even get ExitProcess from this. It somehow cannot get any functions from kernel32.lib even though I am referencing it. I tried referencing the entire path as well, didn't help. I am using 32-bits for this. The 64-bit ml.exe does not give me any issues but the functions I need are written by someone else and available in 32-bit that works because their 64-bit version doesn't compile.

zedd151

Before you declare the .libs, you must include the include .inc files.
You don't need to use EXTERNDEF's this way. Do you even have the Masm32 SDK installed?

Your methods are somewhat foreign to me, maybe someone else might have other suggestions for you. Basically I give up, but I tried.

All that being said, I am certain there is a simple solution that will work for you.  :smiley:


cyrus

I don't have anything masm32 installed and I know that's kind of funny because I'm on a masm32 forum  :rolleyes: but I figured I can use this forum to find answers (and help others if possible although I'm not sure I'm ready for that yet lol) and I really do like the people on here. I'm not sure I am using ml.exe correctly and I had considered installing masm but got kind of lost because there are many versions. Also, the syntax is different in the way things are set up and I already learned so many different assembly languages and syntaxes! But I guess I might have to learn it the masm way. Would this avoid my issue with any of these VCRUNTIME140.DLL errors? I know that it is seeking something from Visual Studio but I don't get why those developers assume that every .exe is going to be running on a developer's machine! I'm able to link statically for 64-bits but not 32-bits with ml.exe. I just don't get why I can't statically compile an .exe with ml.exe

NoCforMe

You absolutely do need the right include files (and the includelib files) so that 1) MASM (ml.exe) knows how many arguments each function takes and 2) the linker knows how to access those library functions.

I would recommend going ahead and installing MASM32; it's not painful, doesn't take up an enormous amount of space, and if you don't need to use it you can just ignore it (doesn't mess with the registry or anything intrusive like that). After you install it the include files will be in the include folder (makes sense, huh?). Try including the file masm32rt.inc, which will definitely let you access LoadLibrary().
Assembly language programming should be fun. That's why I do it.

sinsi

Easy fix, replace ExitProcess with ExitProcess@4
You have to get the import right :biggrin:

You could also do
EXTERNDEF ExitProcess@4: PROC
ExitProcess TEXTEQU <ExitProcess@4>
...
call ExitProcess

Easiest fix, install the MASM32 SDK - it already has all the EXTERNDEFs and a lot more.
Tá fuinneoga a haon déag níos fearr :biggrin:

cyrus

Quote from: sinsi on September 15, 2024, 02:41:48 PMEasy fix, replace ExitProcess with ExitProcess@4
You have to get the import right :biggrin:

You could also do
EXTERNDEF ExitProcess@4: PROC
ExitProcess TEXTEQU <ExitProcess@4>
...
call ExitProcess

Easiest fix, install the MASM32 SDK - it already has all the EXTERNDEFs and a lot more.


ARGH! jeez why on earth do they make it that painful? @4 ? that's the thing, figuring out each little niche thing about each different assembly. ml is so different than ml64. even including other files. you have to be exact with stating .386 and .model I had to look these up. ml64.exe is much easier but I want to code in 32-bits for this project and I have to give up on ml.exe from VS.

I ended up installing masm32 and playing around with invoke which is new to me. I know I can use the other format. I'm enjoying this standalone platform for development. I tested a simple program on another system and didn't see any VCRUNTIME140.DLL errors  :biggrin:

Even though I moved on to the real masm now, I'd still like to know why I have this _mainCRTStartup problem and how can I actually make my build static, or is it just not possible with this VC/VS version and I should just move on... ?

NoCforMe

Quote from: cyrus on September 15, 2024, 05:02:32 PMARGH! jeez why on earth do they make it that painful? @4 ? that's the thing, figuring out each little niche thing about each different assembly. ml is so different than ml64. even including other files. you have to be exact with stating .386 and .model I had to look these up.

If you're doing 32-bit programming you don't have to worry about that stuff; it's already in the include files.

If you use masm32rt.inc as I suggested, it has all this stuff right near the top:

      .486                                      ; create 32 bit code
      .model flat, stdcall                      ; 32 bit memory model
      option casemap :none                      ; case sensitive

One small gotcha: since there's no .nolist directive in this file, you'll get a shit-ton of unwanted stuff (like everything that's in all the include files, since this "master" include file includes other files) if you generate a listing file. That's why I do this in all my programs:

.nolist
    include \masm32\include\masm32rt.inc
.list

Assembly language programming should be fun. That's why I do it.

Vortex

Hi cyrus,

QuoteARGH! jeez why on earth do they make it that painful? @4 ?

_ExitProcess@4 is a an example of name mangling :

QuoteName mangling (C++ only)

QuoteName mangling is the encoding of function and variable names into unique names so that linkers can separate common names in the language. Type names may also be mangled. Name mangling is commonly used to facilitate the overloading feature and visibility within different scopes.

https://www.ibm.com/docs/en/i/7.5?topic=linkage-name-mangling-c-only

If you are trying to use UCRT ( Universal C runtime ) with Masm, here is an example :

.386
.model flat,stdcall
option casemap:none

_stdout equ 1

ExitProcess             PROTO :DWORD
printf                  PROTO C :DWORD,:VARARG
__acrt_iob_func         PROTO C :DWORD

; int __cdecl __stdio_common_vfprintf(unsigned __int64 _Options,FILE* _Stream,
;                                     char const* _Format,int _Locale,va_list);

__stdio_common_vfprintf PROTO C :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
_strupr                 PROTO C :DWORD

includelib  \masm32\lib\kernel32.lib
includelib  ucrt.lib

.data

frmt    db '%s %s %s %u.',0
a1      db 'This',0
b1      db 'is',0
c1      db 'printf test',0

.code

start:

    invoke  _strupr,ADDR c1

    invoke  printf,ADDR frmt,ADDR a1,ADDR b1,eax,1

    invoke  ExitProcess,0


printf PROC C _format:DWORD,args:VARARG

;   #define _stdout (__acrt_iob_func(1))

    invoke  __acrt_iob_func,_stdout   

    lea     ecx,args
    invoke  __stdio_common_vfprintf,0,0,\ ; unsigned __int64 _Options
            eax,_format,0,ecx
    ret

printf ENDP

END start

https://masm32.com/board/index.php?topic=11525.0

mineiro

I noted that you have used 10 in your example as being a new line. On windows a new line is 13,10, on linux that's 10. End os string in both are 0.
The C calling convention is equal in windows32 and linux32, so, if you try jwasm/uasm/asmc you're able to create  an executable in linux too. The main problem will be function names that exist in both O.S.
This is a snippet to try.
;ML.EXE /c /coff /Cp /nologo /I"C:\Masm32\Include" "printf.asm"
;LINK.EXE /SUBSYSTEM:CONSOLE /RELEASE /VERSION:4.0 /LIBPATH:"C:\Masm32\Lib" /OUT:"printf.exe" "printf.obj"

.386
option casemap:none
.model flat,stdcall

WIN32 EQU 1 ;define WIN32

IFDEF LIN32
NL EQU 10
ENDIF

IFDEF WIN32

include msvcrt.inc
include kernel32.inc

includelib msvcrt.lib
includelib kernel32.lib

printf textequ <crt_printf>
exit textequ <crt_exit>
NL EQU 13,10
ENDIF

.data
fmt_msg db "have %d good days",NL,0

.code
main proc

invoke printf,addr fmt_msg,10
invoke exit,0

main endp

end main
I'd rather be this ambulant metamorphosis than to have that old opinion about everything