.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
.data
output db "Hello World!", 0ah, 0h
.code
start:
MyFunc proc param1: WORD
invoke WriteConsole, eax, addr output, param1, ebx, NULL
;ret
MyFunc EndP
invoke GetStdHandle, STD_OUTPUT_HANDLE
invoke MyFunc,13d
;invoke ExitProcess, 0 ;comment out to keep process from returning to windows immediately
end start
I'm trying to figure out how to implement functions with Assembly and I'm having some strange problems.
If I run this code, MyFunc gets invoked and it works properly, so that param1 deteremines how many characters of the "Hello world" string get printed.
Except, I have to comment out the "ret" command, because if I don't, nothing prints to the screen and the program crashes after a few seconds.
I'm very new to Assembly and I'm just trying to get the basics down. But I'm stuck here. Every tutorial clearly lays out that all you need to do is invoke and return and you're good. I thought maybe I was missing a prototype, so I used call, ret instead but that again prints nothing and crashes. Any help is appreciated.
I'm using WinAsm and MASM32 from this 'site.
The program entry point (start) is placed before the procedure MyFunc, thus it is called with invalid arguments.
WriteConsole's third parameter must be a DWORD and not a WORD. The fourth parameter must be pointer to DWORD variable.
(Also: for the MASM version that comes with the MASM32 SDK, there is a bug in the INVOKE directive that produce bad code for WORD or BYTE sized parameters).
include \masm32\include\masm32rt.inc ; <-- default setup
.const
output db "Hello World!", 0dh,0ah
.code
MyFunc proc hStdIn:DWORD,param1:DWORD
LOCAL NumberOfCharsWritten:DWORD
invoke WriteConsole, hStdIn, addr output, param1, ADDR NumberOfCharsWritten, NULL
mov eax,NumberOfCharsWritten
ret
MyFunc EndP
start:
invoke GetStdHandle, STD_OUTPUT_HANDLE
invoke MyFunc,eax,SIZEOF output
inkey ; <-- macro that waits for user input
invoke ExitProcess, 0
;comment out to keep process from returning to windows immediately <-- very bad idea
end start
the last line in the file...
end start
tells the assembler where the program entry point is
this is where execution begins when you run the program
you don't want that to point to your MyFunc PROC
also, it is sometimes nice to be able to move things around
i.e., you might like the INVOKE to appear before the PROC
in order for that to work, the assembler needs a PROTO type
and, this is 32-bit world
we want the parameter to be a dword to keep the stack aligned
when you run the program, open a console window, then type in the name
not using ExitProcess is not a good idea - lol
there are ways to make it wait for a keypress before exiting
but, let's get you started, first :P
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
MyFunc PROTO :DWORD
.data
output db "Hello World!", 0ah, 0h
.data?
hStdOut HANDLE ?
.code
start:
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov hStdOut,eax
invoke MyFunc,13d
invoke ExitProcess, 0 ;comment out to keep process from returning to windows immediately
MyFunc proc param1:DWORD
LOCAL bytesWritten :DWORD
invoke WriteConsole, hStdOut, addr output, param1, addr bytesWritten, NULL
mov eax,bytesWritten ;return the byte count in EAX
ret
MyFunc EndP
end start
I wonder why do none of these examples work on windows 10? Any console examples that work? Thanks. I'd appreciate it
Quote from: xandaz on November 21, 2021, 06:12:17 AM
I wonder why do none of these examples work on windows 10?
No problem with examples.
Hi xandaz,
If you cannot build or run simple console apps, there must be something wrong with your setup. I have attached this simple test piece in a zip file. Run the EXE file in the zip file first, then try and build it with the enclosed batch file. If it will not build, there is something wrong with your build setup.
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
include \masm32\include\masm32rt.inc
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
.data
txt db "Howdy All",13,10,0
.code
start:
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
call main
inkey
exit
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
main proc
invoke StdOut,ADDR txt
ret
main endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
end start
hucth. your example works fine, but the examples that were posted didn't. Thanks y'all.
The problem: /SUBSYSTEM:CONSOLE
Hi. Is it possible to have an applicatinon both WIN32 and CONSOLE?
Hi xandaz,
A console application can displays GUIs. The simplest example is a console displaying a message to inform the user.
Hi xandaz,
The basic distinction is this under win32, you can make either UI (user interface), or console, its only the linker option "subsystem" that is different. This determines what the start app is. From a console app you can also run a UI window and likewise from a UI app you can code a console window.
Yeah Hutch. I tried that but console window pops up at startup. I'd like it to ECHO some stuff from application but am still going around that. Thanks
If you want a UI startup, create the UI app like normal then use AllocConsole() to create a console window.
Thanks a lot Hutch. I was already on that function but hadn't tried it yet. Thanks