Reputation: 217
I'm attempting to display "Hello, world!" with FASM on a 64-bit Windows 7 machine without using the crutches that modern assemblers seem to provide in abundance.
This rather simple task proved to be surprisingly frustrating since every example and tutorial I could find insists on resorting to macros, including prewritten code, or importing libraries from high-level languages. I thought that the kind of people who want to learn assembly typically do so to develop a direct and intimate understanding of how computers work. All these abstractions and obfuscations seem to detract from that purpose.
Rant aside, I'm looking for code that can display "Hello, world!" on a console without reusing, including, and importing anything except to directly access the Windows API. Although I'm aware that many assemblers come packaged with files that provide access to the Windows API, I'd rather not rely on them.
Also, if you have any suggestions as to what assemblers or tutorials I can use to better facilitate my approach to learning, I'd greatly appreciate it.
Upvotes: 3
Views: 1849
Reputation: 40972
; Example of 64-bit PE program
format PE64 GUI
entry start
section '.text' code readable executable
start:
sub rsp,8*5 ; reserve stack for API use and make stack dqword aligned
mov r9d,0
lea r8,[_caption]
lea rdx,[_message]
mov rcx,0
call [MessageBoxA]
mov ecx,eax
call [ExitProcess]
section '.data' data readable writeable
_caption db 'Win64 assembly program',0
_message db 'Hello World!',0
section '.idata' import data readable writeable
dd 0,0,0,RVA kernel_name,RVA kernel_table
dd 0,0,0,RVA user_name,RVA user_table
dd 0,0,0,0,0
kernel_table:
ExitProcess dq RVA _ExitProcess
dq 0
user_table:
MessageBoxA dq RVA _MessageBoxA
dq 0
kernel_name db 'KERNEL32.DLL',0
user_name db 'USER32.DLL',0
_ExitProcess dw 0
db 'ExitProcess',0
_MessageBoxA dw 0
db 'MessageBoxA',0
Using nasm to compile this hello world (16 bit) code taken from here:
.model tiny
.code
org 100h
main proc
mov ah,9 ; Display String Service
mov dx,offset hello_message ; Offset of message (Segment DS is the right segment in .COM files)
int 21h ; call DOS int 21h service to display message at ptr ds:dx
retn ; returns to address 0000 off the stack
; which points to bytes which make int 20h (exit program)
hello_message db 'Hello, world!$'
main endp
end main
Upvotes: 1
Reputation:
I managed to link to one library only (kernel32.dll
) and make reference to 3 functions:
GetStdHandle
WriteConsole
ExitProcess
The code below is the result of my exhaustive Google search, and my own reference to MS documentation.
format PE console
entry start
include 'include\win32a.inc'
section '.data' data readable writable
msg db 'Hello World!',13,10,0
len = $-msg
dummy dd ?
section '.code' readable writable executable
start:
push STD_OUTPUT_HANDLE
call [GetStdHandle] ;STD_OUTPUT_HANDLE (DWORD)-11
push 0 ;LPVOID lpReserved
push dummy ;LPDWORD lpNumberOfCharsWritten
push len ;DWORD nNumberOfCharsToWrite
push msg ;VOID *lpBuffer;
push eax ;HANDLE hConsoleOutput
call [WriteConsole]
push 0
call [ExitProcess]
section '.idata' data import readable writable
library kernel32,'KERNEL32.DLL'
include 'include\api\kernel32.inc'
Upvotes: 1
Reputation: 26171
Every running process under windows gets either kernel32 or kernalbase loaded into its address space, using this fact and the PEB internals, you can easily access any windows function (provided you have the right access privileges).
This blog entry details how to go about doing this to display a message with MessageBoxA
.
In all honesty, unless you have some extreme reason for doing this, you are going to just end up wasting time, rather use the tools provided (in this case, a linker, so you can access any windows API without going through 10000 hurdles and loops).
Upvotes: 2
Reputation: 7051
The big problem with "pure" windows programming is that Windows require that the program contains import section, about what functions from the system DLLs have to be provided to the program - so called import table.
This table is not a part of the program and has nothing to do with assembly programming itself. Besides, the import table has complex structure, not very convenient to be manually build. That is why FASM provides some standard way for the user to build these import tables.
The proper approach to you, if you goal is to learn assembly, is to read the FASM manuals, where these macros are described, then to read the example code provided in any FASM distribution and then to start using them and concentrate to the assembly programming.
The moderate use of macros does not make your program less assembly written!
The FASM message board is good place to ask questions and to get help, but you have to make your homework after all.
Upvotes: 3