Recently started learning 86 assembly and made a basic helloworld.exe but when I run it through cmd there's no output. I did get an output from it once though and I didn't change any code. It also assembled and linked fine so I'm not sure why nothing happens when I run it.
cmd image
Here's the code just in case I messed up:
.386
.model flat, stdcall
option casemap :none
include \masm32\include\kernel32.inc
include \masm32\include\masm32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\masm32.lib
.data
message db "HelloWorld!", 0
.code
main:
invoke StdOut, addr message
invoke ExitProcess, 0
end main
Thank you Michael Petch, not sure how to mark you comment as the answer (first time using stack overflow), the default linker on Masm32 was the issue, using /SUBSYSTEM:CONSOLE as the linker through command line fixed the issue.
Related
Having such a simple assembly Win 32 program:
.386
.model flat, stdcall
option casemap :none
EXTERN printf :PROC ; declare printf
.data
HelloWorld db "Hello Wolrd!:-)", 0
.code
start:
sub esp, 4
push offset HelloWorld
call printf
add esp, 4
ret
end start
I can successfully compile it by just:
ml.exe /c HelloWorld.asm
BUT have a problem linking it. When I use:
link HelloWorld.obj libcmt.lib
I'm getting an error:
unresolved external symbol _main called in _mainCRTStartup
What have I change/correct to to successfully link the program to run it?
P.S.
Please don't tell me to use just nasm. I'd like to use ml & link from my MSVC.
With some minor tweaks this now builds correctly.
.386
.model flat, c
option casemap :none
includelib libcmt.lib
includelib legacy_stdio_definitions.lib
EXTERN printf :PROC ; declare printf
.data
HelloWorld db "Hello World!:-)", 0
.code
main PROC
push offset HelloWorld
call printf
add esp, 4
ret
main ENDP
END
The main edits are
.model flat, c sets the calling conventions for procedures to C.
If you decide to keep .model flat, stdcall it'll require these changes.
Replace
EXTERN printf :PROC
main PROC
with
printf PROTO NEAR C,:DWORD
main PROC NEAR C
Included libcmt.lib and legacy_stdio_definitions.lib which statically links the native C-Runtime startup into your code.
Changed entry point from start to main. There's an entry point (_mainCRTStartup) within the C-Runtime library (CRT) libcmt.lib, which does some initialization tasks, and then hands off control to the entry point for your application main. You can change the default entry point, but usually you want the convenience of the initialization the CRT entry point does for you automatically.
Removed the first sub esp,4 so the remaining one push is balanced by the add esp,4, so ESP is pointing at the return address when ret runs.
To build, open a Windows command prompt and run:
"C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Auxiliary\Build\vcvars32.bat"
to set the MSVC Environment initialized for: 'x86'
Next, run these MASM commands
ml.exe /c /coff HelloWorld.asm
link.exe /SUBSYSTEM:console HelloWorld.obj
The program displays
Hello World!:-)
Your error message says that it can't find the exported symbol (i.e. function) "_main". I expect renaming your start function to _main would get it to compile.
Having such a simple assembly Win 32 program:
.386
.model flat, stdcall
option casemap :none
EXTERN printf :PROC ; declare printf
.data
HelloWorld db "Hello Wolrd!:-)", 0
.code
start:
sub esp, 4
push offset HelloWorld
call printf
add esp, 4
ret
end start
I can successfully compile it by just:
ml.exe /c HelloWorld.asm
BUT have a problem linking it. When I use:
link HelloWorld.obj libcmt.lib
I'm getting an error:
unresolved external symbol _main called in _mainCRTStartup
What have I change/correct to to successfully link the program to run it?
P.S.
Please don't tell me to use just nasm. I'd like to use ml & link from my MSVC.
With some minor tweaks this now builds correctly.
.386
.model flat, c
option casemap :none
includelib libcmt.lib
includelib legacy_stdio_definitions.lib
EXTERN printf :PROC ; declare printf
.data
HelloWorld db "Hello World!:-)", 0
.code
main PROC
push offset HelloWorld
call printf
add esp, 4
ret
main ENDP
END
The main edits are
.model flat, c sets the calling conventions for procedures to C.
If you decide to keep .model flat, stdcall it'll require these changes.
Replace
EXTERN printf :PROC
main PROC
with
printf PROTO NEAR C,:DWORD
main PROC NEAR C
Included libcmt.lib and legacy_stdio_definitions.lib which statically links the native C-Runtime startup into your code.
Changed entry point from start to main. There's an entry point (_mainCRTStartup) within the C-Runtime library (CRT) libcmt.lib, which does some initialization tasks, and then hands off control to the entry point for your application main. You can change the default entry point, but usually you want the convenience of the initialization the CRT entry point does for you automatically.
Removed the first sub esp,4 so the remaining one push is balanced by the add esp,4, so ESP is pointing at the return address when ret runs.
To build, open a Windows command prompt and run:
"C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Auxiliary\Build\vcvars32.bat"
to set the MSVC Environment initialized for: 'x86'
Next, run these MASM commands
ml.exe /c /coff HelloWorld.asm
link.exe /SUBSYSTEM:console HelloWorld.obj
The program displays
Hello World!:-)
Your error message says that it can't find the exported symbol (i.e. function) "_main". I expect renaming your start function to _main would get it to compile.
.386
.model flat, c
.stack 100h
printf PROTO arg1:Ptr Byte
.data
msg1 byte "Hello World!", 0Ah, 0
.code
main proc
INVOKE printf, ADDR msg1
ret
main endp
end main
Hi, I am getting the below errors:
I searched around and found someone said that it can be fixed by linking the microsoft runtime library
Can anyone teach me how can I exactly fix it?
Thanks
Severity Code Description Project File Line Suppression State
Error LNK2019 unresolved external symbol _printf referenced in function _main testing C:\Users\Kin\Desktop\assembly\testing\testing\Source.obj 1
Error LNK1120 1 unresolved externals testing C:\Users\Kin\Desktop\assembly\testing\Debug\testing.exe 1
I don't have VS 2017 installed to try this. Important: Make sure you create a Console Application and not a Windows Application. Once you create this project make sure MASM is added to the build customizations. Add an .ASM file to your project.
Take your code and insert the following lines at the top:
includelib libcmt.lib
includelib libvcruntime.lib
includelib libucrt.lib
includelib legacy_stdio_definitions.lib
An explanation as to why these lines are needed in Visual Studio later than 2013 can be found in this Stackoverflow Answer.
You want the C runtime to be the entry point to your console application (which in turn will call your main). Because of this you MUST remove main from the last line that says end main. When you do end main it bypasses the C runtime startup startup. Failure to properly initialize the C runtime will likely lead to the program crashing when you make calls like printf. It should simply be end and not end main.
The final code you should test is:
includelib libcmt.lib
includelib libvcruntime.lib
includelib libucrt.lib
includelib legacy_stdio_definitions.lib
.386
.model flat, c
.stack 100h
printf PROTO arg1:Ptr Byte
.data
msg1 byte "Hello World!", 0Ah, 0
.code
main proc
INVOKE printf, ADDR msg1
ret
main endp
end
Since Visual Studio 2015, printf is now "inlined" into C code. The assembly code to get around this would be complicated. I ended up including a small C source file in the project with a unused call to printf to get around this problem. I don't recall if the generated printf code is parameter count dependent. I just use the same or more parameters in the dummy C source code call to printf than what I use in the assembly code.
I was trying writing a simple command line program in assembly using the Win32 API. I wrote the following, got it to compile and link with zero errors or warnings, and started it from a command line, but nothing appeared at the command prompt. Can anyone see what's wrong or what would make it say "Hello World!" at the command line? The program:
; Block 1
.386
.model flat,stdcall
option casemap:none
; Block 2
include windows.inc
include user32.inc
includelib user32.lib
include kernel32.inc
includelib kernel32.lib
; Block 3
.data
szMsg db "Hello World!",0
nNumToWrite dd 12
; Block 4
.data?
numwritten dd ?
CommandLine LPSTR ?
; Block 5
.code
start:
invoke GetCommandLine
mov CommandLine,eax
invoke WriteConsole,CommandLine,addr szMsg,nNumToWrite,numwritten,NULL
xor eax,eax
invoke ExitProcess,eax
end start
Are you linking it as a console program or as a GUI program? That's a property of an executable in Win32.
I'm running some MASM32 examples (from www.masm32.com) and I notice that the console output is blank in my command line box (program compiles, links and runs but no output.
.486 ; create 32 bit code
.model flat, stdcall ; 32 bit memory model
option casemap :none ; case sensitive
include \masm32\include\windows.inc ; always first
include \masm32\macros\macros.asm ; MASM support macros
include \masm32\include\masm32.inc
include \masm32\include\gdi32.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
.code ; Tell MASM where the code starts
start: ; The CODE entry point to the program
print chr$("Hey, this actually works.",13,10)
exit
end start ; Tell MASM where the program ends
When you link a PE program for Win32, you can mark the required subsystem as either "GUI" or "Console". If you have linked this as a GUI mode program, then when you run the EXE from a command prompt Windows will not attach the console to the window you are typing into. This sounds like the symptoms you have described.
Make sure that you link your executable with the "console" subsystem flag.