flat assembler
Message board for the users of flat assembler.

Index > Main > format binary as "EXE"

Author
Thread Post new topic Reply to topic
DOS386



Joined: 08 Dec 2006
Posts: 1905
DOS386 22 Feb 2007, 04:53
I created some example executables (based also on work of "babyboy10777" Smile ),

see also ( BB's PE ) : http://board.flatassembler.net/topic.php?t=5616

and ( my LE ) : http://board.flatassembler.net/topic.php?t=7122

and ( late 2009-06 derivative work by Borsuc based on my PE ) http://board.flatassembler.net/topic.php?t=10288

MZ:
Code:
;
; FASM example of writing simple EXE program
; using "format MZ"
;

format MZ

stack $3000   ; Very generous
heap 0        ; No memory here

        push    cs
        pop     ds

        mov     ah,9
        mov     dx,txhello
        int     $21        ; Print to screen

        mov     ax,$4C00
        int     $21        ; Exit from EXE

txhello: db 'Hello world !',$0D,$0A,$24

        rb $5000    ; Additional memory here, can be also 0
                    ; or omitted for this "Hello" program

;END.
    

Code:
;*****************************************************************
;
; FASM example of writing a simple DOS EXE 
; program using "format binary"
;
; Limitations:
; Single-segment, no relocs, < 64 KiB EXE size, no "heap"
;
; Documentation below from www.delorie.com, some additions 
;
;*****************************************************************
;
;00-01  0x4d, 0x5a. This is the "magic number" of an EXE file. 
;The first byte of the file is 0x4d and the second is 0x5a.
;[HINT: it is "MZ"]
;
;02-03  The number of bytes in the last block of the program 
;[SILLY: refers to the "complete" >> file << size (header + 
;program, but excl. possible overlay), not the program code]
;that are actually used. If this value is zero, that means the
;entire last block is used (i.e. the effective value is 512).
;
;04-05  Number of blocks in the file that are part of 
;the EXE file. If [02-03] is non-zero, only that much 
;of the last block is used. [HINT: "block"=512 bytes]
;
;06-07  Number of relocation entries stored after the header. 
;May be zero. [HINT: should be, relocs are a bad hack]
;
;08-09  Number of paragraphs in the header. The program's data 
;begins just after the header, and this field can be used to 
;calculate the appropriate file offset. The header includes 
;the relocation entries. [SILLY: Note that some OSs and/or 
;programs may fail if the header is not a multiple of 512 
;bytes.] [HINT: minimum header size is $20, resulting in 2 here]
;
;0A-0B  Number of paragraphs of additional memory that the 
;program will need. [SILLY: This is the equivalent of the BSS 
;size in a Unix program.] The program can't be loaded if there 
;isn't at least this much memory available to it.
;
;0C-0D  Maximum number of paragraphs of additional memory. 
;Normally, the OS reserves all the remaining conventional 
;memory for your program [SILLY: suppress this with 
;"heap 0"], but you can limit it with this field. 
;
;0E-0F  Relative value of the stack segment. This value is 
;added to the segment the program was loaded at, 
;and the result is used to initialize the SS register. 
;[HINT: it is the size of the executable + reserved area, 
;in 16-byte units]
;
;10-11  Initial value of the SP register. 
;[HINT: stack size, equal to / comes from "stack" directive]
;
;12-13  Word checksum. If set properly, the 16-bit sum of 
;all words in the file should be zero. Usually, 
;this isn't filled in. [SILLY: this is useless & always ZERO]
;
;14-15  Initial value of the IP register. [HINT: it is ZERO]
;
;16-17  Initial value of the CS register, relative to the segment 
;the program was loaded at. [HINT: it is ZERO]
;
;18-19  Offset of the first relocation item in the file. 
;[HINT: it is mostly $1C, even if no relocs present at all Very Happy]
;
;1A-1B  Overlay number. Normally zero, meaning that it's the 
;main program. [HINT: one more useless ZERO]
;
;$1C...$1F: Theoretically "relocs", in fact empty if relocs not used,
;space for garbage Very Happy
;
;$3C...$3F: This $3C is hardcoded (!), optional 32-bit offset to NE, 
;LE or PE, DOS itself ignores it, may be for example $40, $80,
;$200 (PESTUB), in worst case 2 ( "MZPE",0,0, ... , used by 
;some virii and extreme examples) !!! 
;
;*******************************************************************
;

format binary as "EXE"  ; FASM 1.67.22 required Wink

creserve = $5000         ; Could be also 0 for this "Hello"
cstack =   $3000         ; Generous, could be less

codesize = llcodeend
temp1 = (codesize shr 4) shl 4
if codesize = temp1
  codesizeali = temp1
else
  codesizeali = temp1 + $10
end if

filesize = codesize + $20

temp2 = (filesize shr 9) shl 9  
if filesize = temp2
  mzblocks = temp2 shr 9
  mzlast = 0
else
  mzblocks = (temp2 shr 9) + 1
  mzlast = filesize - temp2  
end if

org 0

 db "MZ"
 dw mzlast
 dw mzblocks
 db 0,0           ; No relocs
 db 2,0           ; Header size
 dw (creserve+cstack) shr 4       ; Min
 dw (creserve+cstack) shr 4       ; Max
 dw (codesizeali+creserve) shr 4  ; Stack segment
 dw cstack                        ; Stack size / pointer in bytes !!!
 db 0,0,0,0,0,0   ; CHK, IP, CS 
 dw $1C           ; Useless reloc offset
 db 0,0           ; Useless "overlay"
 db 0,0,0,0       ; Padding / empty reloc

org 0 ; Again Very Happy

        push    cs
        pop     ds

        mov     ah,9
        mov     dx,txhello
        int     $21            ; Print to screen

        mov     ax,$4C00
        int     $21            ; Exit from EXE

txhello: db 'Hello world !',$0D,$0A,$24

llcodeend:

;END.
    


Both sources compile into exactly same executables Shocked

MZ stub for PE:

Code:
;
; FASM Stub for PE executables
;

format binary as "EXE"  ; FASM 1.67.22 required Wink

org 0

 db "MZ"
 db $60,0       ; Last block usage
 db 1,0         ; Number of blocks
 db 0,0         ; No relocs
 db 2,0         ; Header size
 db 0,2         ; Min: 8 KiB
 db 0,2         ; Max: 8 KiB
 db 4,1         ; Stack segment $0104, $1040
 db 0,$10       ; Stack size / pointer in bytes !!!
 db 0,0,0,0,0,0 ; CHK, IP, CS
 db $1C,0       ; Useless reloc offset
 db 0,0         ; Useless "overlay"
 db 0,0,0,0     ; Padding / empty reloc

; org = $20 , should be 0 but irrelevant Very Happy

 db $0E,$1F         ; push cs // pop ds
 db $B4,9,$BA,$20,0 ; mov ah,9 // mov dx,$0020
 db $CD,$21         ; int $21
 db $B8,1,$4C       ; mov ax,$4C01
 db $CD,$21         ; int $21
 db 0,0             ; Wasting 2 bytes

; org = $30

 db 0,0,0,0,0,0,0,0,0,0,0,0 ; Wasting 12 bytes
 db $60,0,0,0               ; PE begins here

; org = $40, should be $20

 db 'Need HX-DOS Extender to run !',$0D,$0A,$24

; org = $60

;END.
    


PE:

Code:
;
; http://board.flatassembler.net/topic.php?t=5616
; Manual PE .EXE template
; Win32/HX-DOS GUI "Hello world", std imports
;

ccbase     = $400000 ; 4 Mi
ccstartrva = $1000   ; 4 Ki

format binary as "EXE"  ; FASM 1.67.22 required Wink
use32
org 0

; *** MZ-Header, stub (0,$60) ***

 db "MZ"
 db $60,0       ; Last block usage
 db 1,0         ; Number of blocks
 db 0,0         ; No relocs
 db 2,0         ; Header size
 db 0,2         ; Min: 8 KiB
 db 0,2         ; Max: 8 KiB
 db 4,1         ; Stack segment $0104, $1040
 db 0,$10       ; Stack size / pointer in bytes !!!
 db 0,0,0,0,0,0 ; CHK, IP, CS
 db $1C,0       ; Useless reloc offset
 db 0,0         ; Useless "overlay"
 db 0,0,0,0     ; Padding / empty reloc

; org = $20 , should be 0 but irrelevant Very Happy

 db $0E,$1F         ; push cs // pop ds
 db $B4,9,$BA,$20,0 ; mov ah,9 // mov dx,$0020
 db $CD,$21         ; int $21
 db $B8,1,$4C       ; mov ax,$4C01
 db $CD,$21         ; int $21
 db 0,0             ; Wasting 2 bytes

; org = $30

 db 0,0,0,0,0,0,0,0,0,0,0,0 ; Wasting 12 bytes
 db $60,0,0,0               ; PE begins here

; org = $40, should be $20

 db 'Need HX-DOS Extender to run !',$0D,$0A,$24

; org = $60, content moved by +$20 bytes

; *** PE-Header ($60,$18 ) ***

db 'PE', 0, 0             ; Signature

dw $014C                  ; CPU: 80386 or compat
dw 1                      ; Number of sections
dd 0                      ; Useless "timestamp" Sad
dd 0, 0                   ; Useless "symbols" Sad
dw $00E0                  ; Size of Optional header
dw $010F                  ; Characteristics : "image", 32-bit, low garbage

; *** "portable" Optional header ($78,$1C ) ***

dw $010B                  ; "magic"
dw 0                      ; Useless "linker version" Sad
dd 0, 0, 0                ; Useless .code/.idata/.data sizes Sad
dd $1000                  ; Entry
dd 0, 0                   ; Useless .code/.data offsets Sad

; *** NT-specific Optional header extension ($94,$44 ) ***

dd ccbase                 ; Base address
dd $1000, $0200           ; Section alignment in memory and file: 4KB/512B
dd 1                      ; OS version ( "NT 1.0" !!!??? )
dd 0                      ; Image version
dd 4                      ; "subsystem" version
dd 0                      ; Reserved

dd ((($1000 +\            ; image size = (rva + section size) aligned to $1000
xxitend-xxmainbeg) shr 12) + 1) shl 12

dd $0200                  ; Header size (MS-DOG + PE + Optional + Sectional), section offset
dd 0                      ; Useless "checksum" Sad
dw 2                      ; "subsystem": 2:GUI 3:Console
dw 0                      ; Useless DLL stuff

dd $1000, $1000, $1000, 0 ; stack/heap reserve/commit
dd 0                      ; Obsolete/reserved Sad
dd 16                     ; "directories" : 16 entries of 8 bytes : 128 = $80 bytes

; *** Directories ($D8,$80) ***

dq 0                              ; Useless "exports" Sad
dd xxitbeg-ccbase,xxitend-xxitbeg ; Useful imports  Wink
dq 14 dup(0)                      ; 14 empty entries Very Happy

; *** Sectional header ($158,$28 ) ***

db '.abcdefg'                ; Section name, 8 Bytes

dd xxitend-xxmainbeg, ccstartrva ; Exact size, "rva"
dd xxpadend-xxmainbeg            ; Size rounded to $0200
dd $0200, 0, 0, 0                ; File offset, no relocations/linenumber crap

dd $0E0000020                    ; Attributes: readable, writable, executable

; *** Padding ($180,$80) ***

db ($0200-$) dup(0)              ; proceed to $0200/$1000
org $401000

; *** Our main section begins here ***

xxmainbeg:

   pushd 0          ; Type of MB: 0:OK 1:OK&Can $10:Error etc ...
   pushd xxtext
   pushd xxtext
   pushd 0          ; Owner "win", useless Sad
   call  dword [MessageBox]

   pushd 0
   call  dword [ExitProcess]

xxtext: db 'Hello world !!!', 0

; *** Import table just follows code & data ***

xxitbeg:

dd 0,0,0, kernel_name - ccbase , kernel_table - ccbase
dd 0,0,0, user_name - ccbase   , user_table - ccbase

dd 0,0,0,0,0

kernel_name: db 'KERNEL32.DLL', 0
kernel_table:
ExitProcess: dd _ExitProcess - ccbase
dd 0
_ExitProcess: db 0, 0, 'ExitProcess', 0

user_name: db 'USER32.DLL', 0
user_table:
MessageBox: dd _MessageBox - ccbase
dd 0
_MessageBox: db 0, 0, 'MessageBoxA', 0

; *** Padding ***

xxitend:

if ($ mod $0200) > 0
  db (($1FF)-($+$1FF) mod $0200) dup(0)
  ; Align to $0200 // this ^^^ line fails if already aligned
end if

xxpadend:

;END.
    


3 additional codes (besides those above) are inside package available
for download Shocked , console and GUI, also system version detection Laughing

Improvements against "babyboy10777"'s version:

- Removed mysterious $0E00 constant (was $1000-$0200, diff of
mem/file alignement)
- Eliminated the silly need to add $400E00 to EVERY label
- Provided working DOS stub giving useful hint to the user
- Better commenting
- Fixed alignement bug occurring if already aligned (one of my codes exposes it)

The PE executables are verified to work in XP, 98, and DOS.

Please test and post comments (bugs, possible optimizations, ...) Smile

EDIT : added link


Description: Download it - no virii inside :-D
Download
Filename: FASM.ZIP
Filesize: 5.71 KB
Downloaded: 2073 Time(s)


_________________
Bug Nr.: 12345

Title: Hello World program compiles to 100 KB !!!

Status: Closed: NOT a Bug


Last edited by DOS386 on 16 Jun 2009, 11:10; edited 4 times in total
Post 22 Feb 2007, 04:53
View user's profile Send private message Reply with quote
rugxulo



Joined: 09 Aug 2005
Posts: 2341
Location: Usono (aka, USA)
rugxulo 22 Feb 2007, 17:58
Suggestions:


  • rename FASM.ZIP to FASMmzPE.ZIP (or something more descriptive)
  • don't use .ZIP and .TAR but instead use only ZIP -9r *or* tar w/ gzip *or* ZIP -0 inside a ZIP -9 (same effect) *or* use 7-ZIP/DOS (or Win32's 7ZA.EXE w/ HXRT) *or* one of the following:

  • use AdvanceComp (advzip or advdef) to further compress the .ZIP or .TGZ


EDIT: Not everybody has both tar and zip, believe it or not (although they should ... or at least DJTAR, heh).


Last edited by rugxulo on 22 Feb 2007, 18:52; edited 1 time in total
Post 22 Feb 2007, 17:58
View user's profile Send private message Visit poster's website Reply with quote
bubach



Joined: 17 Sep 2004
Posts: 341
Location: Trollhättan, Sweden
bubach 22 Feb 2007, 18:08
It's 5kb, who cares about compressing more? ZIP can be opened on most platforms without downloading anything.
Post 22 Feb 2007, 18:08
View user's profile Send private message Reply with quote
rugxulo



Joined: 09 Aug 2005
Posts: 2341
Location: Usono (aka, USA)
rugxulo 22 Feb 2007, 18:51
bubach, it's 5k because he put a .tar in the .ZIP itself, which currently needs both an unzipper (inflater) and an untar program to extract individual files from the embedded .tar file. In other words, why archive with .tar and compess with .ZIP when .ZIP does both archiving and compressing? (Like I said, not everyone already has or uses both tar and zip).
Post 22 Feb 2007, 18:51
View user's profile Send private message Visit poster's website Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1905
DOS386 23 Feb 2007, 02:11
Quote:
Suggestions


I meant about the code Confused

Quote:
don't use .ZIP and .TAR but instead use only ZIP -9r *or* tar w/ gzip


This is intentional, not a random failure Shocked

Quote:
ZIP -0 inside a ZIP -9 (same effect)


OK ...

Quote:
* use AdvanceComp (advzip or advdef) to further compress the .ZIP or .TGZ


No need - used KZIP Shocked

My ZIP: 5'845
PKZIP -exx instead KZIP: 6'049
No TAR: 13'531 Shocked
InfoZIP: ??? 15 KB maybe
PKARC: ??? 20 KB ???

There are reasons why I did how I did Laughing

_________________
Bug Nr.: 12345

Title: Hello World program compiles to 100 KB !!!

Status: Closed: NOT a Bug
Post 23 Feb 2007, 02:11
View user's profile Send private message Reply with quote
rugxulo



Joined: 09 Aug 2005
Posts: 2341
Location: Usono (aka, USA)
rugxulo 23 Feb 2007, 21:17
Suggestion about the code? Well, the only one I have is: change the DOS stub to say "Get HXRT at http://www.japheth.de if Win32 ain't available!". (At least they'd know where to get it from.)

Sorry, I don't mess with PEs much, so I can't really help much regarding that. Razz

BTW, here's what I was suggesting (in case it wasn't obvious, although you can do it your way if you really wanted, but why?):

Code:
[ WinXP ] Fri 02/23/2007>av /l! fasmmzpe.zip

FASMMZPE.ZIP

mzpe.zip       5,929         (29,732)          Feb,22,2007  12:23:36p  [Deflat]

[ WinXP ] Fri 02/23/2007>v /z;lv fasmmzpe.zip

fasmmzpe zip       6,043              Feb,22,2007   12:23:36pm   A...

[ WinXP ] Fri 02/23/2007>scrndump
    
Post 23 Feb 2007, 21:17
View user's profile Send private message Visit poster's website Reply with quote
TheRaven



Joined: 22 Apr 2008
Posts: 91
Location: U.S.A.
TheRaven 24 Apr 2008, 02:56
Zip-Genius.

Freeware utility suite, Italian design by nature, awesome by all virtue.

Handles: .tar, .rar, .zip, .gz styles, 7zip, and too many others from one interface. AWESOME!

I wouldn't be caught dead without it.

_________________
Nothing so sought and avoided more than the truth.
I'm not insane, I know the voices in my head aren't real!
Post 24 Apr 2008, 02:56
View user's profile Send private message Reply with quote
daniel.lewis



Joined: 28 Jan 2008
Posts: 92
daniel.lewis 30 Apr 2008, 07:01
7-zip is good enough for me.

PS: I'll have to take a look at your program when I get home, or if things get busy, this weekend.

Thanks for sharing.
Post 30 Apr 2008, 07:01
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.