Hellooow everybody! ;-)
Today I will give you a short guide on how to use windows API in ASM programming! (at least in programs compiled with NASM because this is the one I'm using and as I'm quite noob about the different versions of asm, I prefer not risk to tell wrong things) This is because I wanted to learn some asm stuff and make little programs on windows, and quickly realized that windows was too protected to use pure asm and that we need to use the windows C++ API, including console I/O.
What is the windows API?
It's a library of C++ functions. You have to use it if you want to make any program on windows. So that means you will have to call these functions in your asm code.
It's called kernel32.dll for 32bits systems, and normally it's in the path :-)
Here is the official documentation:
Here is the documentation for console stuff:
How to call a windows API function in asm?
1) Don't forget the header!
You have to declare any function you want to use in your code by specifying them as external functions. Basically at this point all you have to do is to put a line like this in the begining of your file:
extern Function1Name, Function2Name, FunctionNName
example (console I/O):
extern ExitProcess, GetStdHandle, WriteConsoleA, ReadConsoleInputA
/!\ If you want to use any windows constant in the function calls, you also have to declare those.
For example for the GetStdHandle, these can come in handy :
STD_OUTPUT_HANDLE equ -11
STD_INPUT_HANDLE equ -10
STD_INPUT_HANDLE equ -10
But of course you can directly pass the constant value as an argument (if you wanna do it in the hardcore way :p)
2) Function calls in asm
Function calls in asm aren't really more complicated than in any other language. You just have to pass the arguments the function needs and call the function's name.
In asm your pass the arguments by pushing them on top of the stack:
push arg
(more info about the stack: http://en.wikipedia.org/wiki/Stack_%28abstract_data_type%29)
/!\ Always remember that as the stack goes decreasing, (unlike a stack of papers) you have to pass the arguments in the reverse order:
push arg3
push arg2
push arg1
Once all the arguments are sent to the stack, you can call the function:
call function
Example: WriteConsole call
push NULL
push buffer_out
push msg.len
push msg
push dword[handleOut]
call WriteConsoleA
How to compile and link a program that uses win API functions? (using nasm and golink)
This is the easy part! Just open a console and eventually cd in the right directory.
To compile, type something like:
>> nasm -f win32 yourProgram.asm -o yourProgram.obj
and to link the library using golink:
>> GoLink.exe /console /entry starting_point_of_your_asm_program yourProgram.obj kernell32.dll
Or, you can do a makefile:
yourProgram: yourProgram.obj
GoLink.exe /console /entry starting_point_of_your_asm_program yourProgram.obj kernell32.dll
yourProgram.obj: yourProgram.asm
nasm -f win32 yourProgram.asm -o yourProgram.obj
NB:
If you don't already know GoLink, it's a linker, which means it's able to link your file with the libraries you want. (in this case the kernel32.dll file)
You can download it here: (direct download of last version)
Manual:
NB2:
In order to use these commands, the source folders for nasm and GoLink.exe have to be in the path. So when you install them don't forget to add these at the end of the path variable. (right click on computer => advanced system parameters => environment variables... => find "path" in the system variables table, hit "modify" and add your new paths at the end, separated by a ';')
Working example: system("pause")
STD_OUTPUT_HANDLE equ -11
STD_INPUT_HANDLE equ -10
NULL equ 0 global start
extern ExitProcess, GetStdHandle, WriteConsoleA, ReadConsoleInputA
section .data ;message we want to display on console
msg db "Press a key to continue...", 13, 10, 0
msg.len equ $ - msg
consoleInHandle dd 1
section .bss ;buffers declaration
buffer_out resd 2
buffer_in resb 32
section .text
start: ;starting point of our program
push STD_OUTPUT_HANDLE
call GetStdHandle ;call to get a handle to the
push NULL ;specified mode (input, output...)
push buffer_out
push msg.len
push msg
push eax ;contains the GetStdHandle result
call WriteConsoleA ;call to print our msg in console
read:
push STD_INPUT_HANDLE
call GetStdHandle ;new call to get input handle
push NULL
push 1
push buffer_in
push eax
call ReadConsoleInputA ;call to detect user input
;this function will wait til
exit: ;it detects enough keypresses
NULL equ 0 global start
extern ExitProcess, GetStdHandle, WriteConsoleA, ReadConsoleInputA
section .data ;message we want to display on console
msg db "Press a key to continue...", 13, 10, 0
msg.len equ $ - msg
consoleInHandle dd 1
section .bss ;buffers declaration
buffer_out resd 2
buffer_in resb 32
section .text
start: ;starting point of our program
push STD_OUTPUT_HANDLE
call GetStdHandle ;call to get a handle to the
push NULL ;specified mode (input, output...)
push buffer_out
push msg.len
push msg
push eax ;contains the GetStdHandle result
call WriteConsoleA ;call to print our msg in console
read:
push STD_INPUT_HANDLE
call GetStdHandle ;new call to get input handle
push NULL
push 1
push buffer_in
push eax
call ReadConsoleInputA ;call to detect user input
;this function will wait til
exit: ;it detects enough keypresses
push NULL ;(in this case, 1)
call ExitProcess
call ExitProcess
Manual pages for the functions used in this code:
- ExitProcess
- GetStdHandle
- WriteConsole (A stands for ANSI version)
- ReadConsoleInput (A stands for ANSI version)
I hope this helped some of you! See ya around and have fun coding ;-)
Additional source for this article:
This thread I posted on stackoverflow.com when I was having a hard time understanding all this: ;-p