flat assembler
Message board for the users of flat assembler.
Index
> Windows > Manual Win32 Programming |
Author |
|
Tukang Paip 09 Jun 2004, 05:45
I just recently experimenting building Win32 application manually (without using fasm
"format PE" directive). Here's the result. As you can see in the include file, some of the macros are not optimized and perhaps wrong. I'm not fully understand the macro facility yet. Also the constants and structs are a bit messy because I'm trying to make an include file that can ease ANSI/UNICODE programming. Currently I have no idea how to implement the resource directory builder macro set because I cannot find the actual individual resource format in PE file. Also, the base relocation directory is almost impossible to be automate by macros. I can live without base reloc info in my dll (this will be a problem for a dll intended to be loaded in every process). The include file is not perfect; I just include what actually needed to compile the code template below. I recommend you to use an editor with a syntax highlighting feature that can be customized to read the source. It really helps! Because I'm in internet cafe right now, i cannot provide more examples, in the future I will give them and also post small tuto about how fasm preprocessor really works.. (Please note, I only test all samples in Win xp and using FASM 1.52, release 03-04-2004). ENJOY!!!! Code: ;modify this according to your needs include "%finc%\mpe.inc" ;Use the PE.* macros below to change some the important fields of PE headers. ;The macros just change an already defined numerical constant (except PE.ENTRY) ;so you can only use these macros at the beginning of source file (before the header) ;and after the include. ;The value in the commented macro invocation is the default. ;PE.BASE 0x400000 ;PE.ENTRY Main ;PE.FLAG EXE NORELOC NODEBUG NOLINENUMBERINFO NOLOCALSYMSINFO BYTESHIGH BYTESLOW PE.FLAG EXE NORELOC NODEBUG ;PE.ALIGN 0x200,0x1000 ;PE.STACK 0x10000, 0x1000 PE.STACK 0,0 ;PE.HEAP 0x10000,0 PE.HEAP 0,0 ;PE.OSVER 4,1 PE.OSVER 5,1 ;PE.SUBSYSTEM GUI ;PE.SUBSYSTEMVER 4,1 ;dos header and some of nt headers (before data dir array) DOS_HEADER: dw "MZ" rb 0x3A dd NT_HEADERS NT_HEADERS: dw "PE", 0 FILE_HEADER: dw 0x014c, SectionCount dd %t, 0, 0 dw 224, Characteristics OPTIONAL_HEADER: dw 0x10b db MajorLinkerVer, MinorLinkerVer dd 0, 0, 0, EntryPoint, 0, 0, ImageBase, SectionAlignment, FileAlignment dw MajorOSVer, MinorOSVer, 0, 0, MajorSubsystemVer, MinorSubsystemVer dd 0, SizeOfImage, HeaderSize, 0 dw Subsystem, 0 dd StackReserved, StackCommitted, HeapReserved, HeapCommitted, 0, 16 ;data dir arrays. DIR.ENTRY is a macro (just to make it look nice). Basically ;the actual contents of each dir must be wrapped between ;<Name>_DIR_START and <Name>_DIR_END labels where <Name> is specified as argument ;below. For example, if you create your own import dir, wrap it between ;IMPORT_DIR_START and IMPORT_DIR_END labels. Currently I only have 3 data dir ;creation macros - import, export and tls. DIR.ENTRY EXPORT ;;;;; DIR.ENTRY IMPORT ;;;;; DIR.ENTRY RESOURCE ;;;;; DIR.ENTRY EXCEPTION DIR.ENTRY SECURITY DIR.ENTRY BASERELOC ;; DIR.ENTRY DEBUG DIR.ENTRY COPYRIGHT DIR.ENTRY GLOBALPTR DIR.ENTRY TLS ;;; DIR.ENTRY LOADCONFIG DIR.ENTRY BOUNDIMPORT DIR.ENTRY IAT DIR.ENTRY DELAYLOAD DIR.ENTRY COM DIR.ENTRY RESERVED ;the section headers area. SECTION.HEADER macro is nothing. It's just there ;to make this look nice . SECTION.ENTRY works with SECTION macro (described ;below) and it must receive a number (e.g 1,2,3,4..). It create the individual ;section header (the number is the important part in this macro as well as in ;SECTION macro). In its definition, you will see usage of label such as ;Section#Number#Name and etc.. All these labels are declared using SECTION macro ;below. ;SECTION.ENDHEADER declare the constant SectionCount (see PE headers above) SECTION.HEADER SECTION.ENTRY <1> SECTION.ENTRY <2> SECTION.ENDHEADER ;After SECTION.ENDHEADER, you can actually enlarge the size of header ;by using any method (e.g rb directive) but I think the header size cannot ;exceed the first section's rva. ;Here you should use SECTION macro to define individual section's contents. ;I cannot describe more about the SECTION, ENDSECTIOn and ENDPROGRAM macros ;because I'm not sure if they're always correct in any circumstances. ;Basically SECTION macro receives 3 types of args, A number (section number ;for generating the label to be used in SECTION.ENTRY above, section name ;(must be quoted string and can be of any length.. only 8 chars are taken) ;and the characteristics of the section. Please note there are 2 types of ;characteristic constant you can use : the one that is not preceeded with dot ;(e.g Code, Executable etc) and the one with dot in front of its name (e.g ;.IDATA, .RSRC). The dot name is given without comma, e.g ;.CODE .DATA (and not .CODE, .DATA). You can check the SECTION macro for ;more info on this. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Section 1 - code only ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; SECTION <1>, "<Achik>", .CODE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;CONSTANT, IDATA and UDATA is a data declaration macros. CONSTANT and IDATA ;are the same, it's just to hint you that you should put a constant data in ;a read only section. I make 2 version of it because maybe later I want to change their ;implementation. These macros didn't declare anything at the current offset! ;You must use DECLARE.CONSTANT, DECLARE.IDATA and DECLARE.UDATA to declare them. ;So any vars declared using these macros are group together at wherever you use ;the DECLARE.* macros. Note that the DECLARE.* macros can work multiple time, ;each time it will declare the previously define CONSTANT, IDATA (except UDATA). ;UDATA works differently and you should use it only once (per section or per program). ;If DECLARE.UDATA is used, it must be at the end of section (just before the ENDSECTION). CONSTANT MsgTitle TEXT "Template Test" CONSTANT MsgByOrd TEXT "This is a call By Ordinal" UDATA hInstance dd ? ;FUNCTION, ENTER, EXIT and ENDF works together to define a function. The first argument ;is a function name and second is function calling convention. This is only useful if it's ;called using CALL macro (not the "call"). 2 types of calling convention naming ;as argument can be used. __cdecl and CDECL. When using __cdecl no comma is needed after the ;function name (example below) but is needed when using CDECL. Supported calling conventions ;are CDECL (__cdecl), WINAPI/CALLBACK/STDCALL(__winapi, __callback, __stdcall) and PASCAL (__pascal). ;PROC and ENDP is just alias to FUNCTION and ENDF. Although it's not a requirement, you should ;call any labels defined with FUNCTION macro with CALL macro because it will take care of ;parameter pushed direction and stack cleanup for you. ;The PUSH macro can push normal pushable operand, runtime affective address, e.g ;value of ebp+8 (edx is trashed), string (single/multi-bytes), float and double constant, ;and int64 constant (see definition of PUSH macro) for more info on how to correctly ;push all these. ;Only the APICALL and IMPDATA works with IMPORT macros set. See description of import dir ;creation below. Unless you already accessed labels created in IMPORT macro using either ;of these macros, you cannot use any other instructions/methods to access them. FUNCTION Main __cdecl ENTER xor ebx, ebx APICALL KERNEL32.GetModuleHandleA, ebx mov [hInstance], eax IMPDATA eax, USER32.MessageBoxA PUSH ebx, MsgTitle, "This is a call By Name", ebx call eax CALL Foo, MsgByOrd, MsgTitle push MsgTitle MsgByOrd push @f jmp Foo @@: APICALL USER32.MessageBoxW, ebx, MsgByNameW, L "Template Test (Unicode)", ebx .Return: EXIT ENDF PROC Foo, <WINAPI>, .Msg, .Title ENTER xor eax, eax push eax [.Title] [.Msg] eax APICALL USER32.@477 push eax [.Title] [.Msg] eax call [USER32.@477] ;USER32.@477 already used in APICALL above, this instruction will compile. EXIT ENDP ;The vars defined with CONSTANT (above) will end up declared here. Please note : ;use CONSTANT macro first, then declare it with DECLARE.CONSTANT below them. DECLARE.CONSTANT ;ENDSECTION is a requirement. Although this macro can receives a number, it ;is not a requirement. ENDSECTION ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Section 2 - data r/w ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; SECTION <2>, "<Achik>", .DATA ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;DIR.IMPORT, DIR.ENDIMPORT, NODEFAULTIMPORT, LIBRARY and IMPORT macros must be used ;after all APICALL and IMPDATA usage because they use conditional preprocessing. ;The import creation macro set is complex and I think they still need to be improved. ;They just end up like that because of this reason : ;-I want to implement an import macro that can include default Win32 system API such ; as from KERNEL32,USER32,GDI32 and ADVAPI32 and I want the compilation to be fast. ; Without conditional processing, the code template took over 20 seconds to compile ; while with conditional processing, it takes less than 5 seconds. ; I also want the default import can be overridden (using NODEFAULTIMPORT) completely. ; I also want a perfect import dir that have the original first thunk and first thunk, ; and I want to be able to call a function by ordinal. Then I want to be able to add ; more function to an already imported library (such as the default library) and so ; on.... ;To make this simple :- To create the import dir, you need to ;-wrap it in DIR.IMPORT and DIR.ENDIMPORT ;-between them, you can override the default import using NODEFAULTIMPORT macro ; (as demonstrated below). ;-use LIBRARY to import new dll function ;-use IMPORT to import new function in dll defined with LIBRARY (any LIBRARY ; usage must lead its IMPORT equivalent). You can use IMPORT many times over ; the same dll name (as shown below) but you cannot import the same function ; name more than once. ;-use NODEFAULTIMPORT only to removes default functions list included in the include file. DIR.IMPORT NODEFAULTIMPORT GDI32,ADVAPI32,SHELL32,SHLWAPI,COMCTL32,COMDLG32 IMPORT USER32,\ 477 DIR.ENDIMPORT ;you can safely use the DECLARE.* macros even if no corresponding * macro ;was used, e.g IDATA macro never used in this source, DECLARE.IDATA will ;do nothing. DECLARE.IDATA DECLARE.UDATA ENDSECTION ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ENDPROGRAM ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|||||||||||
09 Jun 2004, 05:45 |
|
Vortex 09 Jun 2004, 10:01
What's the use of all this stuff? Creating PEs from scratch had beed discussed before:
http://board.flatassembler.net/topic.php?t=1309 _________________ Code it... That's all... |
|||
09 Jun 2004, 10:01 |
|
Tukang Paip 12 Jun 2004, 03:08
Quote: What's the use of all this stuff? Creating PEs from scratch had beed discussed before: I know.. its just to show you the power of fasm's macroinstruction facilities. resource macros in std fasm include is good... but i'm still trying to make a better macros. Currently i still use them with some modification. and here is the include files I used in my manual programming (edited version). (to do) : -base reloc dir creation. -complete resource dir creation. -easy production of ANSI/UNICODE version of program. -data structures and constants related to win32 versioning. -a better way to manipulate imported data and the creation of import dir (current implementation make compilaion really slow). -better UDATA macro. http://www26.brinkster.com/paipx/inc.html and also more examples : http://www26.brinkster.com/paipx/ex.html My first attempt to explain about fasm preprocessor (please forgive my bad english). This is far from complete. I will post a new doc (it should be a complete doc) next week. http://www26.brinkster.com/paipx/pphowto.txt |
|||
12 Jun 2004, 03:08 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.