Search code examples
winapiassemblyx86masmmasm32

x86 assembly - how to use Windows API _WriteConsole@4 - masm32 syntax


In result to my post Can I use int21h on windows xp to print things?, I have seen an article about using Windows API's and in this article was a reference to using the _WriteConsole@4 API to print a message to the console. The article is at http://cs.lmu.edu/~ray/notes/x86assembly/.

Here is my code so far:

.386P
.model  flat
extern  _ExitProcess@4:near
extern  _GetStdHandle@4:near
extern  _WriteConsoleA@20:near
public  _go

.data
      msg     byte    'if you get this, it worked.', 10
      handle  dword   ?
      written dword   ?
.code 
start:
_go:    
      push    -11
      call    _GetStdHandle@4
      mov     handle, eax
      push    0
      push    offset written
      push    13
      push    offset msg
      push    handle
      call    _WriteConsoleA@20
      push    0
      call    _ExitProcess@4
end start

I am using this syntax to compile the code: ML:

ml (the file is called test.asm) test.asm /c

Link:

link test.obj C:\masm32\lib\kernel32.lib /SUBSYSTEM:CONSOLE /entry:go

I have gotten it to compile and link, but when I run the .exe that is produced, it does absolutely nothing, not even an error return. The console is just black. Why is this?

Any help would be greatly appreciated. And to the users of this forum, I apologize for bombarding stackoverflow.com every day, it is just that I have very few resources to learn with.

Thanks in advance,

Progrmr


Solution

  • First off, the link you are getting your sample code is from a NASM user and he probably never used MASM from the way he speaks of it. He also writes his MASM sample like NASM format. The fact that you want to use Assembly means you have to be an advanced computer user. You need to know how to use batch files, how to set system paths and other things. When something goes wrong, you learn by researching. So you got an error saying it can't find masm32rt.inc but you say you are using MASM32. I use batch files and an IDE for Assembly and I have my system paths pointing to various directories in MASM32.

    Add the absolute path to your masm32\include directory before masm32rt.inc. While you are at it, open masm32rt.inc in a text editor and see what is in it - error fixed.

    You start your source file with:
    .586
    .option casemap:NONE
    .model flat, stdcall
    
    include yourincludeshere and it could be a bunch
    includelib yourlibshere same here a bunch
    

    masm32rt.inc contains that already and it contains include and includelib for libs and includes that are widely used. We use it to save a bunch of typing.

    Now open any include file in \masm32\include the includes are just setting up the protos for the API calls so you can use invoke for parameter checking, it also aliases the API calls so we don't have to type WriteConsoleA instead we just write WriteConsole hell, you could even do YoConsole equ and in your code you would write YoConsole for WriteConsole.

    That being said, we don't use - extern _WriteConsoleA@20:near as NASM would nor do we need to set our entry label to public MASM knows your entry point by this:

    .code
    yourentrypointname:
    
    end yourentrypointname
    

    we also don't have to specify the libs to the linker since we use includelib in our source.

    Also, DO NOT, I repeat DO NOT get into the habit of using hard coded numbers in your parameters. Get out of that habit NOW!! Windows header files use DEFINES for a reason - code readability, We (the folks that help you) don't need to lookup what -11 means for that API call, I used the define and you know what that parameter means. Plus what if you have that WriteConsole call 40 times? If you use an equate, you need to change just the equate instead of search and replace. If you want decent MASM tutorials search for Iczelion they are old and contain a few errors but they will get you started, many of us in the early days have used those tutorials.