in the previous example i gave you an "dumbed down" asm program. this isn't true asm. it isn't even close to what you would see in a debugger window. so in this example i will modify the previous source and show you some real asm.
I created and tested this using
FASM (http://flatassembler.net/)FORMAT PE GUI 4.0
;this is FASM specific it's a command that specify's the basic format of the file
;while it's not mandatory your os wont know how to read the direct code without it
ENTRY Main ;entry point Main
;this specify's the location to start this can be a function location or a
;regular location just dont specify a location in your data section it will
;most likely cause a crash
include 'win32a.inc'
;same as in C except that FASM uses the .inc extension.
;win32a.inc specify's the basic macros and structs used.
section '.data' data readable writeable
;specify's that we want to use the .code section and that it contains...
;well... Data. it also specifys that this section has read (readable)
;and Write (writeable) privileges
;to save space as each section in a PE file takes 1kb i will also use this
;section to store constants
hInstance dd ?
szNotice db 'Notice', 0 ;you need to add the ',0' to the end of strings in asm
;to add the null terminator.
szHello db 'Hello World of ASM', 0
;this is how you define a variable.
;<var name> <type> <initial data (if '?' then data is not initialized>
;dd is Data DoubleWord a 4 byte data type (like int on 32 bit C compilers)
;dw is Data Word a 2 byte data type (like a short)
;db is Dara Byte a 1 byte data type (like a char)
; db has some special properties that allow you to use it like a string
;you can chain data declarations by separating them with a comma
;EX: array dd 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
;will is the same as "int array[10]" and filling it with sequential variables from 0 to 9
section '.code' code readable executable
;specify's that we want to use the .code section and that it contains Code.
;it also specify's that this section has read (readable)
;and Ecexute (executable) privileges
;ok this is where the real asm comes in as proc is the first non ams instruction i included.
;insted of proc we will just place a label with the same name
;then we would initialize the stack by pushing esp onto the stack then copying esp to ebp
;in this application we don't use the stack enough to warrant such use so i will leave commented versions here
; proc Main
Main:
;uncomment the flowing 2 lines if you use need to use ebp offsets with local variables
;or just use the standard proc function prototype
; push esp
; mov ebp, esp
;Ok i hate invoke it hides too much and it doesnt allow some of the advanced nature of asm to be seen
;in asm you can modify paramiters at any point invoke even recalculate them after you placed them on the stack
; invoke GetModuleHandle, 0 ;this is the same as "GetModuleHandle(NULL);" in c
push 0 ;push the paramiter 0 onto the stack
call [GetModuleHandle] ;call the API
mov [hInstance], eax ;most api save their returns in eax this command moves
;the return from GetModuleHandle into the variable hInstance
;notice the '[ ]' around the variable if thesse were here
;FASM would assume that hInstance was a constant address.
;and would return an error. the '[ ]' tell FASM that
;hInstance is an Data Location. which allows us to save
;our Handle to this application insatance.
;invoke MessageBox, 0, szHello, szNotice, MB_OK
push MB_OK ;ok here is where it first becomes apparent that parameters are pushed onto the stack in reverse order
push szNotice ;you will need to note this to be able to use this in a debugger
push szHello
push 0
call [MessageBox]
;this calls the MessageBox function (specifyed later in the imports section)
;then passes it some parameters. The first parameter which tells MessageBox
;which window owns our messagebox in this case it's a 0 or NULL which tells
;MessageBox that this message box isn't owned by a window and to assign it
;to the desktop. the second paramiter is our message, the third is the
;messagebox caption (or window name), and the last is the type of messagebox.
ret
;last we need to return control to the OS, there are 2 ways to do this one is
;to call ExitProcess the other is to use a 'ret' or return.
;(ret only works if you kept your stack balanced properly)
;since we didn't call proc endp isn't needed any more and will just cause an error
;endp
; last is endp, endp is required to tell fasm when the function has ended
;i also like to write my own impoerts section by hand but this is much more advanced and i dont want to confuse you.
section '.idata' import data readable writeable
;this is a special section. the infamous Imports Table used by many windows hackers.
;I'll need to give you a little background for you to understand it completely.
;Every program needs to link to the outside OS. Well the the Imports table is how
;a windows based program does that. When the program first starts the OS scand
;the program for where the imports table is located. after the imports table is found
;the OS looks for all functions it recognizes if it finds one it doesn't know then it
;reports an error and exits the program. if no errors are found then the OS places the
;address of all functions found into the locations specified in the imports table
;structures. This usually all happens transparent to you the programmer (especially in
;C based languages). all you really need to know is that unlike in C and C++ you need to
;tell FASM which API you need.
;(this is not specified in win32a.inc, so win32a.inc != windows.h)
library kernel, 'KERNEL32.DLL',\
user, 'USER32.DLL'
;the "library" macro (specified in win32a.inc) tells FASM to create a list of DLL's
;to link to and assign those DLL's a variable name. this macro use a pair sequence first
;the variable name then the library's file name. the ',' separates the parameters (just
;like in c), and the '\' tells FASM to carry the macro/instruction over to the next line.
;in this case were using Kernel32.dll (no case doesn't matter but if you match the case
;of the dll it can help avoid errors) and User32.dll.
import kernel,\
GetModuleHandle,'GetModuleHandleA',\
ExitProcess, 'ExitProcess'
;the "import" macro (specified in win32a.inc) specify's the format of the imported functions
;in this case we are importing GetModuleHandleA and ExitProcess from kernel (KERNEL32.DLL)
;(Note: some API have two versions standard ASCII and Wide Char. these are specified by the
;'A' and the 'W' on the end of the function.
import user,\
MessageBox, 'MessageBoxA'