; *** The shortest HelloWorld! MessageBox ***
;   by TomCat/Abaddon [tomcat@szif.hu] 1998
;
; nasmw hellowmb.asm -o hellowmb.exe

IMAGEBASE EQU 400000H

;for Win95 - 596 bytes
;SECTIONALIGN EQU 4096
;FILEALIGN EQU 512
;ENTRYPOINT EQU SECTIONALIGN

;for WinNT - 436 bytes
SECTIONALIGN EQU 32
FILEALIGN EQU 32
ENTRYPOINT EQU 160H

DOS_HEADER:
.e_magic        DW 'MZ'
.e_cblp         DW 0
.e_cp           DW 2
.e_crlc         DW 0
.e_cparhdr      DW 2
.e_minalloc     DW 30
.e_maxalloc     DW 30
.e_ss           DW 0
.e_sp           DW 200H
.e_csum         DW 0
.e_ip           DW 0
.e_cs           DW 0
.e_lfarlc       DW 0
.e_ovno         DW 0
.e_res          DW 0,0

                PUSH    CS
                POP     DS
                MOV     DX,0EH
                MOV     AH,9
                INT     21H
                MOV     AX,4C01H
                INT     21H
                DB 'Win32 EXE!',7,13,10,'$'

.e_lfanew       DD 40H

NT_SIGNATURE:
                DB 'PE',0,0

FILE_HEADER:
.Machine                DW 14cH                ; i386
.NumberOfSections       DW 1                   ; only one
.TimeDateStamp          DD 0                   ; who cares?
.PointerToSymbolTable   DD 0                   ; unused
.NumberOfSymbols        DD 0                   ; unused
.SizeOfOptionalHeader   DW 0e0H                ; constant
.Characteristics        DW 102H                ; executable on 32-bit-machine

OPTIONAL_HEADER:
.Magic                  DW 10bH                ; constant
.MajorLinkerVersion     DB 000H                ; I'm version 0.0 :-)
.MinorLinkerVersion     DB 000H                ;
.SizeOfCode             DD 000H                ; unused
.SizeOfInitializedData  DD 000H                ; we don't have a data section
.SizeOfUninitializedData DD 0                  ; we don't have a BSS
.AddressOfEntryPoint    DD ENTRYPOINT          ; beginning of code section
.BaseOfCode             DD 0                   ; RVA to code section: unused
.BaseOfData             DD 0                   ; RVA to data section: unused
.ImageBase              DD IMAGEBASE           ; 4 MB, chosen arbitrarily
.SectionAlignment       DD SECTIONALIGN        ; 4096-bytes-alignment
.FileAlignment          DD FILEALIGN           ; 32-bytes-alignment
.MajorOperatingSystemVersion DW 4              ; NT 4.0
.MinorOperatingSystemVersion DW 0              ;
.MajorImageVersion      DW 0                   ; version 0.0
.MinorImageVersion      DW 0                   ;
.MajorSubsystemVersion  DW 4                   ; Win32 4.0
.MinorSubsystemVersion  DW 0                   ;
.Win32VersionValue      DD 0                   ; unused?
.SizeOfImage            DD END_SECTION-START_SECTION ; sum of all section sizes
.SizeOfHeaders          DD START_SECTION       ; offset to 1st section
.CheckSum               DD 0                   ; not used for non-drivers
.Subsystem              DW 2                   ; Win32 console (3), gui (2)
.DllCharacteristics     DW 0                   ; unused (not a DLL)
.SizeOfStackReserve     DD 100000H             ; 1 MB stack
.SizeOfStackCommit      DD 1000H               ; 4 KB to start with
.SizeOfHeapReserve      DD 100000H             ; 1 MB heap
.SizeOfHeapCommit       DD 1000H               ; 4 KB to start with
.LoaderFlags            DD 0                   ; unknown
.NumberOfRvaAndSizes    DD 010H                ; constant

DATA_DIRECTORY:
DIRECTORY_ENTRY_EXPORT       DD 0,0             ; 0
DIRECTORY_ENTRY_IMPORT       DD ENTRYPOINT+IMPORT_DESCRIPTOR-START_SECTION
                             DD END_SECTION-IMPORT_DESCRIPTOR ; 1
DIRECTORY_ENTRY_RESOURCE     DD 0,0             ; 2
DIRECTORY_ENTRY_EXCEPTION    DD 0,0             ; 3

DIRECTORY_ENTRY_SECURITY     DD 0,0             ; 4
DIRECTORY_ENTRY_BASERELOC    DD 0,0             ; 5
DIRECTORY_ENTRY_DEBUG        DD 0,0             ; 6
DIRECTORY_ENTRY_COPYRIGHT    DD 0,0             ; 7

DIRECTORY_ENTRY_GLOBALPTR    DD 0,0             ; 8
DIRECTORY_ENTRY_TLS          DD 0,0             ; 9
DIRECTORY_ENTRY_LOAD_CONFIG  DD 0,0             ; 10
DIRECTORY_ENTRY_BOUND_IMPORT DD 0,0             ; 11

DIRECTORY_ENTRY_IAT          DD 0,0             ; 12
                             DD 0,0             ; 13
                             DD 0,0             ; 14
                             DD 0,0             ; 15

SECTION_HEADER:
.Name                   DB '.text',0,0,0        ; ".text"
.VirtualSize            DD 0                    ; unused
.VirtualAddress         DD ENTRYPOINT           ; RVA to code section
.SizeOfRawData          DD END_SECTION-START_SECTION ; size of code
.PointerToRawData       DD START_SECTION        ; file offset to code section
.PointerToRelocations   DD 0                    ; unused
.PointerToLinenumbers   DD 0                    ; unused
.NumberOfRelocations    DW 0                    ; unused
.NumberOfLinenumbers    DW 0                    ; unused
.Characteristics        DB 060H,000H,000H,0e0H  ; code, executable, readable
                                                ; initialized data, writeable
ALIGN FILEALIGN,DB 0
START_SECTION:
[BITS 32]

MOV EAX,IMAGEBASE+ENTRYPOINT+string-START_SECTION
CDQ
PUSH EDX
PUSH EAX
PUSH EAX
PUSH EDX
DB 0FFH,015H ; CALL DWORD [__imp__MessageBoxA]
DD IMAGEBASE+ENTRYPOINT+__imp__MessageBoxA-START_SECTION
RETN

IMPORT_DESCRIPTOR:
.OriginalFirstThunk     DD ENTRYPOINT+FIRST_THUNK-START_SECTION ; RVA to orig. 1st thunk
.TimeDateStamp          DD 0                    ; unbound
.ForwarderChain         DD 0ffffffffH           ; no forwarders
.Name                   DD ENTRYPOINT+DLLNAME-START_SECTION ; RVA to DLL name
.FirstThunk             DD ENTRYPOINT+FIRST_THUNK-START_SECTION ; RVA to 1st thunk

TERMINATOR:
string: DB 'Hello world!'
.Name                   DD 0

DLLNAME:
                DB 'user32.dll',0

FIRST_THUNK:
__imp__MessageBoxA:
.AddressOfData  DD ENTRYPOINT+IMPORT_BY_NAME-START_SECTION ; RVA to function name "MessageBoxA"
                DW 0                    ; terminator

IMPORT_BY_NAME:
                DW 0                    ; ordinal, need not be correct
                DB 'MessageBoxA',0      ; (NT:392, 95:386)
END_SECTION:
