;
;       manual PE
;
include 'win32a.inc'

	image_base	EQU	0x400000
	section_align	EQU	0x1000
	file_align	EQU	0x200
	stack_reserve	EQU	0x1000
	stack_commit	EQU	0x100
	heap_reserve	EQU	0x1000
	heap_commit	EQU	0x100

macro	my_align	val*, filler
{
	local	cnt
	virtual
		align	val
		cnt = $ - $$
	end	virtual
	if cnt
	DB	cnt DUP (filler)
	end if
}

;
;       dos header
;       pe header
;       optional header
;       directory entries
;       import header
;       code directory
;       import directory
;

use32

dos_header:

	DW	'MZ'	;DOS signature
	DB	0x3A DUP (0)	;unused
	DD	0x40	;PE header address

pe_header:

	DW	'PE',0	;PE signature
	DW	0x014C	;cpu (386)
	DW	1	;number of sections
	DD	0	;timestamp
	DD	0	;symbol table address
	DD	0	;number of symbols
	DW	sizeof.header	;size of optional header
	DW	0x030F	;characteristics

optional_header:

	DW	0x010B	;magic
	DW	0	;linker version
	DD	0	;size of code section
	DD	0	;size of initialised data
	DD	0	;size of uninitialise data
	DD	code_section+adjust	;entry point address
	DD	0	;base of code
	DD	0	;base of data
	DD	image_base	;base of image
	DD	section_align	;section alignment
	DD	file_align	;file alignment
	DW	0	;os version major
	DW	0	;os version minor
	DW	0	;image version major
	DW	0	;image version minor
	DW	4	;subsystem version major
	DW	0	;subsystem version minor
	DD	0	;win32 version (reserved)
	DD	sizeof.image	;image size
	DD	code_section	;header size
	DD	0	;checksum
	DW	0x0002	;subsystem (GUI)
	DW	0	;dll characteristics
	DD	stack_reserve	;stack reserve size
	DD	stack_commit	;stack commit size
	DD	heap_reserve	;heap reserve size
	DD	heap_commit	;heap commit size
	DD	0	;loader flags (obsolete)
	DD	16	;number of directory entries

directory_entries:

	DQ	0	;export
	DD	import_directory+adjust ;import section rva
	DD	sizeof.import	;import section size
	DQ	14 DUP (0)	;the rest


import_header:

	DQ	'.section'	;name
	DD	sizeof.section	;virtual size
	DD	code_section+adjust	;rva
	DD	sizeof.section	;raw size
	DD	code_section	;raw pointer to data
	DD	0	;pointer to relocations
	DD	0	;pointer to line numbers
	DW	0	;number of relocations
	DW	0	;number of line numbers
	DD	0x0E0000020	;characteristics


	my_align	file_align,0	;align to file_align

code_section:

	push	MB_OK OR MB_ICONEXCLAMATION
	push	title
	push	message
	push	NULL
	call	DWORD [MessageBox]
	push	eax
	call	DWORD [ExitProcess]


data_section:

	_title	DB	'Small PE',0
	_message	DB	'Handmade Forever',0


import_directory:

	DD	0,0,0,kernel_name+adjust, kernel_table+adjust
	DD	0,0,0,user_name+adjust, user_table+adjust
	DD	0,0,0,0,0

; IAT
; thunks

kernel_table:
	_ExitProcess	DD	__ExitProcess+adjust
			DD	0
user_table:
	_MessageBox	DD	__MessageBox+adjust
			DD	0

	my_align	2,0		; don't know should it be aligned or not?
	kernel_name	DB	'KERNEL32.DLL',0
	my_align	2,0		; don't know should it be aligned or not?
	user_name	DB	'USER32.DLL', 0

	my_align	2,0
	__ExitProcess	DB	0,0,'ExitProcess',0
	my_align	2,0
	__MessageBox	DB	0,0,'MessageBoxA',0


;       equates

	sizeof.import = $ - import_directory
	sizeof.section = $ - code_section
	sizeof.header = import_header - optional_header
	sizeof.image = section_align + (sizeof.section + section_align-1) AND -section_align

	adjust = section_align - file_align

	title = _title + image_base + adjust
	message = _message + image_base + adjust

	ExitProcess = _ExitProcess + image_base + adjust
	MessageBox = _MessageBox + image_base + adjust