Ancient One 3 Report post Posted July 3, 2004 FASM Macros Kepada pengguna fasm (http://www.flatassembler.net), kat sini korang bleh lashare macros yang korang rase berguna untuk kita semer. Kalau ader soalan relatedto fasm pun bleh gak letak kat sini. Kalau nak kutuk fasm pun bleh letak kat sini.Pendek kata aper menatang yang related to fasm korang bleh buang kat sini.Note all macros apply to 32-bit code only.1. _TEXT macro - Untuk define C-style string constant. It recognizes "\" escapecharacter in the string constant (lebih kurang cam C laa). Aku cuma support"\n" (newline, dos crlf), "\t" (tab), "\\", dan "\0" (null). Actually kita tak gunakan _TEXTmacro tu sendiri tapi aliasnya seperti TEXT (for ASCII), TEXTW (for UNICODE).Saiz (in bytes, including null) dan Panjang (characters count, not including null)juga disertakan sekali (lihat contoh).ASCII fix _ASCII, WIDE fix _WIDE, struc _TEXT Enc,[String] { common local ..start ..start: virtual at 0 db String Len=$ end virtual Current=0 PutWord=0 Chars=0 repeat Len DontPutChar=0 if Current < Len virtual at 0 db String load char from Current end virtual if char='\' Current=Current+1 if Current < Len virtual at 0 db String load char from Current end virtual Current=Current+1 if char='n' if Enc eq _WIDE Chars=0x000A000D else Chars=0x0A0D end if PutWord=1 else PutWord=0 if char='t' Chars=0x09 else if char='\' Chars='\' else if char='0' Chars=0 else DontPutChar=1 end if end if else DontPutChar=1 end if else PutWord=0 Chars=char Current=Current+1 end if if ~DontPutChar if PutWord if Enc eq _WIDE dd Chars else dw Chars end if else if Enc eq _WIDE du Chars else db Chars end if end if end if end if end repeat if Enc eq _WIDE du 0 else db 0 end if .SIZE=($-..start) if Enc eq _WIDE .LEN=.SIZE/2-1 else .LEN=.SIZE-1 end if } CSTR fix _TEXT ASCII TEXT fix _TEXT ASCII CSTRW fix _TEXT WIDE TEXTW fix _TEXT WIDE Contoh: foo CSTR "Simple ASCII String." foobar _TEXT WIDE "This is a UNICODE string." c_string TEXT "C style ascii string.\n After new line.\t After tab." another_sample TEXT "\\WINDOWS\\SYSTEM32\\USER32.DLL" c_string2 TEXTW "C style unicode string." ;getting the length and size foo_length dd foo.LEN foobar_size dd foobar.SIZE Korang boleh gantikan struc dengan macro kalau korang nak gunakannya seperti CSTR "Simple ASCII String" 2. PUSH macro - Seperti yang kita tau, dalam fasm (atau most assembler yang lain), kita takleh push mcm2 benda, contohnya string constant (pointer to string) yang maner string tersebut sebagai parameter kepada push instruction. Even nak push floating point constant pun takleh gak. Payah! Dengan universal PUSH instruction nih, kita bleh push mcm2 benda. Korang bleh extend kalau korang perlukan push yang lain, contohnya address to constant array dan sebagainya. Please note korang perlukan "macro" version of _TEXT macro kat atas (just make a copy of the _TEXT struc and change the "struc" to "macro"). DOUBLE equ double equ DOUBLENEG equ doubleneg equ FLOAT equ float equ L equ l equ ADDR equ addr equ INT64 equ int64 equ NEG equ neg equ macro PUSH [Operand] { forward if Operand eqtype 1.0 if _#Operand in <_DOUBLE Operand, _double Operand> virtual at 0 dq Operand load ..Oper dword from 0 load ..Oper1 dword from 4 end virtual push dword ..Oper1 push dword ..Oper else if _#Operand in <_DOUBLENEG Operand, _doubleneg Operand> virtual at 0 dq -Operand load ..Oper dword from 0 load ..Oper1 dword from 4 end virtual push dword ..Oper1 push dword ..Oper else virtual at 0 if _#Operand in <_NEG Operand, _neg Operand> dd -Operand else dd Operand end if load ..Oper dword from 0 end virtual push dword ..Oper end if else if Operand eqtype '' local ..l1 call ..l1 if _#Operand in <_L Operand, _l Operand> _TEXT WIDE Operand else _TEXT ASCII Operand end if ..l1: else if _#Operand in <_ADDR Operand, _addr Operand> lea edx, Operand push edx else if _#Operand in <_INT64 Operand, _int64 Operand> virtual at 0 dq Operand load ..Oper dword from 0 load ..Oper1 dword from 4 end virtual push ..Oper1 push ..Oper else push Operand end if end if } Contoh : ;normal push PUSH ebx, esi, edi ;push string constant (you need to use L to push unicode string) PUSH "ascii string", L "unicode string" ;push floating point constant (single prec, 4 bytes; double prec, 8 bytes; fp values are supported) PUSH 0.07 ;single prec fp constant PUSH neg 0.07 ;single prec negative fp constant PUSH double 1.4235e10 ;double prec fp constant PUSH doubleneg 0.07e100 ;double prec negative fp constant ;push int64 constant PUSH int64 0x123456789ABCDEF0 ;push runtime effective address (e.g address of local vars) PUSH addr [ebp+4] Korang blehla gunakan PUSH macro di dlaam invoke/call macro korang untuk dapatkan code seperti : invoke MessageBox, NULL, "Hello World", "Test", MB_ICONINFORMATION .. invoke gluPerspective, double 45.0, double 2.0, double 0.1, double 100.0 dan sebagainya. Tak nampak cam assembly language kan (at least tak nampak asm instructions ). 3. IDATA macro - FASM adalah flat assembler. Maknanya dia assemble source korang ikut aper yang korang tulis. Kita takleh define data relative to some section. Data yang korang define dalam code akan tetap kat situ. Dengan IDATA macro (it's actually a macro set), kita leh kumpul data kat satu kawasan (e.g .data section). macro IDATA [DataDeclaration] { common macro IDATA_DATA _m DataDeclaration m_ DECLARE_IDATA_ARG fix DECLARE_IDATA_ARG, } macro @DECLARE_IDATA Dummy1, [Dummies] { forward macro REVERSE_IDATA_DATA _m IDATA_DATA purge IDATA_DATA align 4 m_ forward REVERSE_IDATA_DATA purge REVERSE_IDATA_DATA common DECLARE_IDATA_ARG fix } macro DECLARE.IDATA { IDATA @DECLARE_IDATA DECLARE_IDATA_ARG } DECLARE_IDATA_ARG fix _m fix { m_ fix } Gunakan IDATA untuk define initialized data. Ia takkan letakkan data tu kat maner korangdefine unless korang gunakan DECLARE.IDATA (korang blehla gantikan nama macro ni ikutnama yang korang suker). DECLARE.IDATA declare semua data yang korang define dengan IDATA.Contohnya :format PE GUIenrty Mulasection "ancient1" code executable readableMula :;data dalam IDATA ni cuma akan dihasilkan dengan menggunakan DECLARE.IDATAIDATA MsgText db "String using ""db"" directive", 0IDATA MsgTitle TEXT "String using ""TEXT"" macro" push 0 push MsgTitle push MsgText push 0 call [MessageBox] retsection "ancient2" data readable writeableDECLARE.IDATA ;all data declared using IDATA will be placed here.;import dir and thunk kat siniMessageBox dd ?Cukup laa kot 3 macros untuk hari ni. Esok lusa aku tambah lagi. Korang bleh tengok sendiricamne macros bleh mencantikkan (atau memburukan) dan memudahkan (atau menyusahkan) keje2pengaturcaraan korang . ENJOY!!!! Quote Share this post Link to post Share on other sites
encik pot pet 0 Report post Posted July 3, 2004 soalan:1. mcm mana nak declare local variable dalam satu function?2. cmp [wparam], BN_CLICK shl 16 + IDOK shl tuh internal assembler ke atau macro? Quote Share this post Link to post Share on other sites
Ancient One 3 Report post Posted July 4, 2004 1. mcm mana nak declare local variable dalam satu function?Kalau guna default includes kat fasm (1.52, aku rase 1.53 nyer proc macro dah lain sikit, aku tak test lagi). Jangan risau pasal esp tak align kepada dword. macroakan align untuk kiter : proc MyProc, arg1, arg2 local1 dd ? ;ni local local2 MSG ;ni local (struct) local3 db ? ;ni local gak enter mov eax, [local1] ;access local1 local var .. .. endp actually aku tak penah guna fasm nyer default proc macro. aku guna aku nyer sendiri. minggu depan aku post (basically sama je). 2. cmp [wparam], BN_CLICK shl 16 + IDOK shl tuh internal assembler ke atau macro? shl tu fasm nyer operator untuk constant expression. As long as BN_CLICK shl 16 + IDOK menghasilkan constant then it will compiled. note : shl tu assembly instruction gak : mov eax, BN_CLICK shl eax, 16 add eax, IDOK Quote Share this post Link to post Share on other sites
encik pot pet 0 Report post Posted July 6, 2004 #include <windows.h>struct account{char name[33];char account_no[10];};struct account p_array[10];main(){int i;char nama[] = "nama awak";char no_acc[] = "532821-A";for (i = 0; i <10; i++){wsprintf(p_array.name, "%s",nama );wsprintf(p_array.account_no, "%s", no_acc);}return 0;}------------------------------------------------aku nak buat small database program.. and dbase tuakan diencrypt guna blowfish, aes, etc..and of course aku akan gunakan dynamic memory allocationsoalannya...macam mana nak buat uninitialize array of structuremenggunakan macro dalam fasm.. jadikita boleh pakai structure lebih kurang syntax C.takpun sekurang2nya sptinvoke GetDlgItemText, [hwnd], IDC_NAMA,esi+MyData.nama,30dimana esi adalah index..aku dah ada cara iaitu guna table indexing..truly in asmtapi nak cari cara yg senang sketdata aku lebih kurang gini..struc MyData{.nama rb 30.no_acc rb 30.alamat rb 50}p/s:dah 2 hari fikir..tak jumpa solutioniq aku rendah jer..tak boleh fikir banyak2plus aku tak boleh buang masa banyak sangat utk benda nimintak tolong yerrr.. Quote Share this post Link to post Share on other sites
Ancient One 3 Report post Posted July 10, 2004 #include <windows.h>struct account{char name[33];char account_no[10];};struct account p_array[10];main(){int i;char nama[] = "nama awak";char no_acc[] = "532821-A";for (i = 0; i <10; i++){wsprintf(p_array.name, "%s",nama );wsprintf(p_array.account_no, "%s", no_acc);}return 0;}------------------------------------------------aku nak buat small database program.. and dbase tuakan diencrypt guna blowfish, aes, etc..and of course aku akan gunakan dynamic memory allocationsoalannya...macam mana nak buat uninitialize array of structuremenggunakan macro dalam fasm.. jadikita boleh pakai structure lebih kurang syntax C.takpun sekurang2nya sptinvoke GetDlgItemText, [hwnd], IDC_NAMA,esi+MyData.nama,30dimana esi adalah index..aku dah ada cara iaitu guna table indexing..truly in asmtapi nak cari cara yg senang sketdata aku lebih kurang gini..struc MyData{.nama rb 30.no_acc rb 30.alamat rb 50}p/s:dah 2 hari fikir..tak jumpa solutioniq aku rendah jer..tak boleh fikir banyak2plus aku tak boleh buang masa banyak sangat utk benda nimintak tolong yerrr..kalau kiter guna struct macro dalam default include files, ia ader define offset to fields. So, bila kiter define some struc, lets say struc MyData { .nama rb 30 .no_acc rb 30 .alamat rb 50 } struct MyData ;tambahan seperti yang hang tulis, kita leh refer offset dengan MyData.<fieldname> so let say kita declare MyData struc : ;data foo MyData ;code somelabel : mov esi, foo ;address of the structure lea esi, [esi+MyData.alamat] ;address of .alamat field in foo (Mydata) structure kalau hang nak refer structure fields dengan expression yang complex sebagai index (e.g wsprintf(p_array[i+j*2].name, ....)), takde cara yang mudah dalam assembly, hang kena kire sendiri la (lagipun ni kan bahasa aras rendah). Tapikalau setakat index yang normal je, kita tambah je saiz structure dan gunakannya sebagai pointer (in index). Quote Share this post Link to post Share on other sites
Ancient One 3 Report post Posted July 10, 2004 Kali ni aku nak berikan FUNCTION macros yang tersangatla penting sebab ia memudahkankita membina subroutines dengan mudah. Macro FUNCTION/PROC, ENTER, EXIT, ENDF/ENDPadalah satu set untuk subroutine declaration. CALL macro plak digunakan untuk callfungsi yang korang define dengan FUNCTION macro. Rules berkaitan dengan calling conventiondipatuhi secara automatik so contohnya korang tak perlu risau untuk remove params from stacklepas call fungsi yang korang declare dengan __cdecl calling convention. CALL macro bergantungkepada PUSH macro. Lihat contoh cara penggunaan kat bawah : Winapi=0 Cdecl=1 Pascal=2 Fastcall=3 __stdcall fix ,STDCALL __winapi fix __stdcall __callback fix __stdcall __cdecl fix ,CDECL __pascal fix ,PASCAL WINAPI fix STDCALL CALLBACK fix STDCALL macro FUNCTION FName, CConv, [Param] { common CurrentFunctionName fix FName if used FName label FName dword if CConv eq STDCALL ..#FName#.CC=Winapi else if CConv eq CDECL ..#FName#.CC=Cdecl else if CConv eq PASCAL ..#FName#.CC=Pascal else display "Function : "#`FName#" - Unknown Calling Convention", CRLF HALT! end if virtual at (ebp+8) forward if ~Param eq FName#.#Param dd ? Param equ FName#.#Param end if common if CConv eq STDCALL | CConv eq PASCAL ..REMOVE_FROM_STACK=$-(ebp+8) else if CConv eq CDECL ..REMOVE_FROM_STACK=0 end if end virtual local ..dyn_data,..dyn_size dyn_data equ ..dyn_data dyn_size equ ..dyn_size virtual at ebp-dyn_size dyn_data : } PROC fix FUNCTION macro ENTER { rb (4-($-dyn_data) and 11b) and 11b dyn_size=$-dyn_data end virtual enter dyn_size, 0 } macro EXIT { leave if ..REMOVE_FROM_STACK<>0 ret ..REMOVE_FROM_STACK else ret end if } macro ENDF FName { align 4 end if } ENDP fix ENDF macro CALL FName, [Arg] { common if ~Arg eq if ..#FName#.CC=Winapi reverse PUSH Arg common call FName else if ..#FName#.CC=Cdecl ..SIZE=0 reverse PUSH Arg ..SIZE=..SIZE+4 common call FName if ..SIZE <> 0 add esp, ..SIZE end if else if ..#FName#.CC=Pascal forward PUSH Arg common call FName end if else call FName end if } Korang akan dapati terdapat beberapa kelemahan, terutamanya tang argument names tu. Korang bleh improve lagi macros ni sebenarnya ikut kesesuaian korang. Aku suker camni sebab ia memaksa aku untuk gunakan local labels dalam function args, local vars dan labels inside function. format PE GUI entry mula PROC mula __cdecl ENTER CALL Funct1, 1, 2 CALL CFunc1, 1, 2 CALL PFunc1, 1, 2 EXIT ENDP ;atau FUNCTION Funct1, STDCALL, .Arg1, .Arg2 FUNCTION Funct1 __stdcall, Arg1, Arg2 .Local1 dd ? .Local2 db ? .Local3 rb 100 ENTER push ebx esi mov eax, [Arg1] xor ebx, ebx ;.. ;.. pop esi edi EXIT ENDF ;atau FUNCTION CFunc1, CDECL, .Arg1, .Arg2 FUNCTION CFunc1 __cdecl, Arg1, Arg2 ENTER push ebx esi mov eax, [Arg1] xor ebx, ebx ;.. ;.. pop esi edi EXIT ENDF ;atau PROC PFunc1, PASCAL, .Arg1, .Arg2 PROC PFunc1 __pascal, Arg1, Arg2 ENTER push ebx esi mov eax, [Arg1] xor ebx, ebx ;.. ;.. pop esi edi EXIT ENDF Quote Share this post Link to post Share on other sites
Ancient One 3 Report post Posted July 10, 2004 Tuto kecik ni explains mengenai fasm. Di sini aku akan terangkan camne fasm proseskiter punyer source file. Secara ringkasnya, kiter nyer source melalui 4 fasa - preprocessing,parsing, assembling dan formatting. Kalau nak compare ngan C compiler, preprocessing, parsingdan assembling tu dalam proses compilation laa, part formatting tu dalam proses linking laa.Preprocessing cuma berlaku SEKALI sahaja untuk setiap source file (1 pass) manakala proses assemblyboleh berlaku berulang kali (maximum 65536 passes). Ni la yang kita katakan multipass assembleryang mana antara kebaikannya adalah code optimization (i.e for jump instructions), forward referencesdan sebagainya. So katakan la aku ader kod cam kat bawah :Kod Pertama : FOO_CONSTANT=0 ;other constants mov eax, FOO_CONSTANT Kod Kedua: mov eax, FOO_CONSTANT FOO_CONSTANT=0 Dalam single pass assembler, cuma Kod pertama yang boleh dikompil. Kod kedua tidak boleh kerana semasa assemble "mov eax, FOO_CONSTANT", dia tak jumpe lagi pemalar FOO_CONSTANT. FASM boleh kompil kedua-dua jenis kod di atas. Kod di atas adalah contoh forward reference. Akan tetapi, dalam forward reference fasm, kiter takleh redefine constant. Contohnya : mov eax, FOO_CONSTANT FOO_CONSTANT=0 FOO_CONSTANT=1 akan menyebabkan error. Tapi FOO_CONSTANT=0 mov eax, FOO_CONSTANT FOO_CONSTANT=1 bleh dikompil. In this case, FOO_CONSTANT dalam "mov eax, FOO_CONSTANT" adalah 0. [General Info] Korang tak perlu ingat any command line options untuk fasm sebab ia takde command line options. Aper yang dia perlukan hanyalah fail yang mengandungi kod kiter. fasm menyokong output format flat binary (default), DOS MZ, Win32 PE, COFF (and MS COFF), dan ELF. fasm menyokong 8/16/32-bit Intel x86 general/system assembly instructions. Begitu juga dengan FPU instructions, MMX, SSE, SSE2, extension to SSE/SSE2 (Presscot), dan juga 3DNow!. Mengenai source file. Macam biasa la, fasm cuma terima source file dalam bentuk ascii/plain text. Korang kena letak hanya satu arahan/directives set dalam satu line. Simbol ; digunakan untuk single line comment (takde multiple line comment dalam fasm). Symbol \ digunakan untuk menyambungkan line seterusnya kepada line sebelumnya. Contohnya dd \ 100 akan jadi dd 100 Mengenai Nombor. Nombor dalam kod boleh ditulis dalam format binari (bin), oktal (oct), desimal (dec) dan heksadesimal (hex). Formatnya adalah : binary :- terdiri daripada 0 dan 1 dan diakhiri dengan simbol "b". Contohnya 10001b, 1111111111111b dan sebagainya. octal :- terdiri daripada 0 hingga 7 dan diakhiri dengan simbol "o". Contohnya 1234567o, 1111111111111o dan sebagainya. decimal :- normal numbers. Contohnya 1, 2, 2174681267 dan sebagainya. hex :- terdiri daripada nombor 0 hingga 9 dan huruf a-f. Terdapat 3 jenis format yang boleh digunakan iaitu dengan awalan "0x" (C style), dengan awalan "$" (Pascal style) dan juga dengan akhiran "h" (traditional style . Contohnya : 0x12345678, 1234567890ABCDEFh, $10101010 Untuk real numbers plak, ader 3 cara korang boleh tulis : (i) secara normal, yang mengandungi "." seperti 4.3142, 0.5, etc (ii) dengan akhiran "f" seperti 3f (berbeza dengan 3). (iii) scientific notation dengan "E" sebagai simbol kuasa 10 seperti 1E1, 3142E-3, etc. Mengenai String. Korang boleh letakkan (Text) string dalam source dengan menggunakan ' atau " secara berpasangan. Sebagai contoh "foo" atau 'foo' adalah sama. Kalau nak gunakan simbol ' atau " itu sendiri di dalam string, korang kena gandakan jika ia digunakan sebagai simbol untuk define string tersebut. Contohnya jika korang gunakan ' untuk define string, maka kalau korang nak letak ' dalam string tersebut, korang kena gunakan '' instead of '. Tapi kalau korang nak letakkan ", korang cuma perlu gunakan satu je. Contoh : "foo" ;string = foo 'foo''"' ;string = foo'" "foobar' ;invalid "foo"" ;invalid, should use "foo""" 'foo''""' ;string = foo'"" Mengenai constant dan label. Constant (numerical constant) dan labels basically adalah benda yang sama. Korang bleh define constant seperti : MSGF_MESSAGEBOX=1 IDOK=1 WM_MYMSG=WM_USER+123 dan sebagainya. Labels plak hanyalah alias kepada lokasi memory. Please note yang labels bukanlah nama yang merujuk kepada variable seperti yang boleh dilakukan dalam MASM dan juga all high level language. So bila nak access data in labels kita kena gunakan indirect reference la. Terdapat beberapa jenis labels. Yang pertama adalah labels yang diakhiri dengan simbol :. Ini adalah global simbol yang akan menjadi scope baru untuk local labels. Local labels adalah any labels yang dimulakan dengan single dot seperti ".foo" dan sebagainya. Kemudian kita ader gak global labels yang takkan jadi scope baru untuk local labels. Ia dimulakan dengan dua dots seperti "..foo". Kita juga bleh gunakan anonymous labels dengan simbol "@@". Labels juga bleh diikuti dengan data definition/reservation directives. Akhir sekali, kita bleh define labels dengan "label" directive. foo: .bar: ... ... ..bar: foobas dd ? .bar: ... ... label .foobas label "foo" adalah global label yang bleh diakses dari maner2 lokasi dalam source file kiter. Ia juga menjadi parent kepada local label bernama ".bar" (note that local label ".bar" wujud dalam dua scope iaitu pada "foo" scope dan pada "foobas" scope). Katakan kita berada dalam scope "foobas" (e.g under label ".foobas") dan nak akses local label ".bar" pada "foo" scope : foo: .bar: ... ... ..bar: foobas dd ? .bar: ... ... label .foobas jmp foo.bar;jmp ke address ".bar" (line kedua) jmp .bar ;jump ke address ".bar" dalam scope yang sama dengan ".foobas" (to line 7) jmp ..bar ;jump ke address "..bar" Version baru fasm melebarkan jurang perbezaan di antara constant ngan label. Version dulu2 (kalau tak silap aku laaa.. sebelum 1.50 kot), constant jugak bleh jadi new scope untuk local labels. Jadi kod kat bawah ni bleh dikompil (label ".bar" yang di bawah sekali adalah dalam scope "constant"). Tapi versi baru fasm tidak membenarkan ini dan label ".bar" yang di bawah sekali adalah dalam scope "foobas" yang akan menyebabkan error "symbol already defined" semasa compilation. foo: .bar: ... ... ..bar: foobas dd ? .bar: ... ... label .foobas constant=0 .bar: Mengenai data plak, korang boleh define/reserve data dengan data definition/reserve directives berikut : (i) 1 byte data :- Korang boleh define data atau array bersaiz 1 byte setiap satunya dengan "db" directive. Array of data boleh dipisahkan dengan koma (simbol ,). "db" directive terima satu (1 byte data) atau lebih arguments (array). Simbol ? boleh digunakan yang bermakna it's an uninitialized data. Korang boleh letakkan aper sahaja sebagai arguments kepada "db" as long as ia bersaiz byte dan menghasilkan constant semasa compilation. Kalau korang gunakan text string sebagai argument, maka ia adalah sama seperti array of bytes (untuk define ascii string). Contoh : db "foo", 0 ;null terminated string -> 0x66, 0x6f, 0x6f, 0 db 1, 2, 3, 4, 5 ;array of bytes db ? ;uninitialized 1 byte data db ?, ?, ?, ?, ? ;uninitialized array of 5 bytes data db 0xff-0x32+2 ;1 byte data = 0xCF db 256 ;invalid - 256 is out of range value. db foo foo=0 Untuk reserve data dalam unit 1 byte, korang boleh gunakan "rb". Directive "rb" cuma terima satu argument je iaitu bilangan unit yang korang hendak reserve dalam memory. Contohnya : rb 10 rb 0xffffff MAX_PATH_NAME=256 rb MAX_PATH_NAME Note that ini adalah cara yang betul kalau korang nak define uninitialized data (data yang korang akan initialized hanya semasa runtime) sebab ia tak makan ruang dalam fail (disk). Also, gunakan ? adalah sama dengan rb dengan 1 sebagai argument. rb 1 db ? Selain daripada tu, korang boleh juga include chain of bytes (raw data) daripada external file ke dalam output program korang dengan "file" directive. Basically "file" directive terima 1 argument iaitu nama fail yang mana isi kandungannya korang nak include dalam output program. Contohnya : file "encrypted_data.bin" Kadangkala korang cuma nak sedikit data daripada suatu file tersebut. Untuk kes ni, korang boleh gunakan "file" directive dengan menyatakan offset dan juga size data yang korang kehendaki daripada fail tersebut. Offset dinyatakan selepas nama fail dan didahului dengan simbol :. Selepas itu boleh diikuti dengan saiz (didahului dengan koma). Contohnya : file 'mydata.bin' :100 ;include raw data from mydata.bin starting from offset 100 to the end of the file. file 'mydata.bin' ,100 ;include raw data from mydata.bin starting from offset 0 and put 100 bytes. file 'mydata.bin' :5,5 ;include raw data from mydata.bin starting from offset 5 and put 5 bytes. file "my_data.bin" ;same as >> file "my_data.bin" :0 (ii) 2 bytes data (1 word) - Korang bleh define 1 word data/array dengan "dw" atau "du" directive. "dw" bleh digunakan dengan cara yang sama seperti "db" directive, kecuali jika argument adalah string. Walaupun "dw" directive bleh terima string sebagai argument, string ni hendaklah mempunyai saiz 1 word sahaja (maknanya 2 ascii chars). "du" plak adalah special version of "dw" di mana ia bleh proses string sama seperti "db" directive. Tapi instead of define array of bytes untuk string, ia define array of word (suitable for winnt unicode-16 string). Contohnya : dw "food" ;error dw "fo", "od" ;okies, output will be "food" dw 1, 2, 3, 4, 5 ;array of words dw ? ;uninitialized 1 word data dw ?, ?, ?, ?, ? ;uninitialized array of 5 words data dw 0xff-0x32+2 ;1 word data = 0x00CF dw 65536 ;error - 65536 is out of range dw foo foo=0 du "food" ;okies, output will be 0x66, 0, 0x6f, 0, 0x6f, 0, 0x64, 0 (iii) 4 bytes data (1 dword) - Korang bleh define 1 dword data/array dengan "dd" directive dan reserve dengan "rd" directive. Penggunaannya sama je macam "dw" directive, tapi dd juga bleh terima real numbers (single precision) : dd "food" ;okies, output will be "food" dd "a", "b", "c" ;okies, output will be 0x61,0,0,0,0x62,0,0,0,0x63,0,0,0 dd "foobar" ;error dd ?, ?, ? ;uninitialized arraty of 3 dword data _SHIFT_ = 2 foo=0x1234578 shl _SHIFT_ dd foo EPSILON=0.00001 foo dd EPSILON Memandangkan cuma ketiga-tiga directives ni yang paling banyak kita gunakan, aku cuma bincangkan yang ni je la. Actually ader lagi directives yang lain iaitu : "dp" atau "df" - define 6 bytes data (1 fword) (selector:offset address style). "rp" atau "rf" - reserve data in fword unit "dq" - define 8 bytes data (1 qword), e.g for double precision floating point numbers. "rq" - reserve data in qword unit "dt" - define 10 bytes data (1 tword) - ONLY for double extended precision fp numbers. "rt" - reserve data in tword unit Okeh.. tu je la kot pasal data declaration nih. Terdapat beberapa operators yang korang bleh gunakan dalam constant mathematical expression seperti untuk penambahan, penolakan, dan sebagainya. Operators matematik yang biasa adalah + (tambah), - (tolak), / (bahagi) dan * (darab). Selain daripada tu, operator "mod" digunakan untuk mendapatkan baki daripada pembahagian, operator "and", "or" dan "xor" melakukan operasi logikal terhadap constant, begitu juga dengan "shl" dan "shr". Aku rase korang tau ler kan aper tugas setiap operators ni? Secara amnya, layout Win32 program source file dalah seperti berikut : ;use format directive untuk specify jenis output format PE <GUI/console> <Subsystem Version> <DLL?> <at ImageBase> <on DosStub> ;use entry directive untuk specify permulaan program entry <entrypoint_symbol> ;section directive untuk bina section baru, contohnya ;section ".code" code executable readable section <section_name> <attributes> ;...section data section <section_name> <attributes> ;...section data Sebelum aku terangkan lebih lanjut mengenai fasm, meh kita bincangkan topik paling penting dalam assembler nih - preprocessor. [The preprocessor] Takde cara lain lagi untuk menggunakan fasm secara efektif selain memahami prapemproses fasm secara details. Aku tak la sure sangat aper yang aku terangkan kat sini betul belaka since aku tak penah study fasm nyer preprocessor engine dengan lebih mendalam. Preprocessor (pp) adalah stage pertama dalam source compilation by fasm. Sebelum aper2 terjadi terhadap source file korang, fasm akan preprocess dulu file ni terlebih dahulu. 2 bahagian penting dalam pp engine adalah line converter dan line pp. Setiap line dalam source file korang akan diproses oleh line converter dulu dan hasil daripada line converter diserahkan kepada line pp. Sebelum aku terangkan dengan lebih lanjut lagi, korang kena la tau beberapa perkara : 01. symbol characters recognize by fasm : null,tab,lf,cr,space,0x1A,#&()*+,-/\:<>={}|~`; -(0x1A used internally by fasm for various purpose). -"`" and "#" can only be used inside macroinstructions. -Setiap simbol blehla dikira sebagai 1 token kecuali yang dibuang daripada source (seperti tab, cr,lf dan space). Any chains of characters yang tak include salah satu symbol characters kat atas adalah dikira sebagai 1 symbol name (1 token). Contohnya : foo bar bas: ;4 tokens - foo, bar, bas dan character : macro foo arg1, arg2 {} ;7 tokens 02. preprocessor directives : macro, struc, equ, fix, purge, restore, include03. macro directives : local, common, forward, reverse...bersambung... Quote Share this post Link to post Share on other sites
encik pot pet 0 Report post Posted July 10, 2004 sambung dgn uninitialized array sekali yer Quote Share this post Link to post Share on other sites
Ancient One 3 Report post Posted July 17, 2004 Sekarang macro kiter related to export directory. Macro nih create export directorydalam program korang. It supports all features of export directory, including forwardedexport, custom ordinal dan sebagainya. Dia trime satu solo argument dan 3 arguments dalamgroup. DllName adalah quoted string yang menyatakan internal name dll korang (internaldll name sepatutnya sama dengan nama fail dll tersebut). "Name" argument adalah quoted string yang menyatakannamaa simbol (fungsi/data) yang korang nak export. Nama ni digunakan oleh program yang nak importsimbol tersebut (e.g "ExitProcess" dan sebagainya). Kalau korang tak specify quoted string (atau specify nothing)for the "Name" argument, it is assumed that you only want it to be exported by ordinal. "Ordinal" argument adalahordinal untuk fungsi tersebut (must be 0 < ordinal < 65536). Manakala "Entrypoint" argumentmenyatakan address fungsi tersebut (labels for the exported function in source). Note that kalaukorang berikan quoted string sebagai "Entrypoint" argument, it's assumed that this is a forwarded export.Korang bleh tengok contoh kat bawah. Macro ni cuma perlu digunakan dalam PE executable (format PE). macro EXPORT DllName, [Name, Ordinal, Entrypoint] { common BaseOrdinal=0xffff HighestOrdinal=0 ExpByOrdinal=0 ExpByName=0 forward if Ordinal=0 | Ordinal>65535 | Ordinal eq display "Error : [EXPORT] Invalid Ordinal - You Must Supply a Valid Ordinal.",13,10 HALT! end if if BaseOrdinal>Ordinal BaseOrdinal=Ordinal end if if HighestOrdinal<Ordinal HighestOrdinal=Ordinal end if EXPORT@#Ordinal=0 forward EXPORT@#Ordinal=EXPORT@#Ordinal+1 if EXPORT@#Ordinal>1 display "Error : [EXPORT] Duplicate Ordinal.",13,10 HALT! end if common align 4 dd 0, %t, 0, rva ExportDllName, BaseOrdinal, HighestOrdinal-BaseOrdinal+1 forward if Name eqtype "" ExpByName=ExpByName+1 else ExpByOrdinal=ExpByOrdinal+1 end if common dd ExpByName, rva ExpFunctionTable, rva ExpNameTable, rva ExpNameOrdTable ExpFunctionTable: repeat HighestOrdinal-BaseOrdinal+1 NoExpFunction=0 forward if %+BaseOrdinal-1=Ordinal if Entrypoint eqtype "" dd rva Forward@#Ordinal else dd rva Entrypoint end if else NoExpFunction=NoExpFunction+1 end if common if NoExpFunction=ExpByName+ExpByOrdinal dd 0 end if end repeat forward if Entrypoint eqtype "" Forward@#Ordinal db Entrypoint,0 end if common align 4 if ExpByName ExpNameTable: forward if Name eqtype "" local _Name dd rva _Name end if common else ExpNameTable=ImageBase end if ExpNameOrdTable: forward if Name eqtype "" dw Ordinal-BaseOrdinal end if forward if Name eqtype "" _Name db Name,0 end if common ExportDllName db DllName,0 } Contoh : format PE GUI DLL entry DllMain section ".code" code executable DllMain: ;.... mov eax, 1 ret 12 Exp1 : ;... ret Exp2 : ;... ret DataExp dd ? section ".rdata" data readable export EXPORT "MYDLL.DLL", \ "DataExp",1,DataExp,\ ;export data DataExp by name as "DataExp", ordinal = 1. "Exp1",4,Exp1,\ ;export function Exp1 by name as "Exp1", ordinal = 4. ORD, 5, Exp2,\ ;export function Exp2 by ordinal 5. "UniMsgBox", 6, "USER32.MessageBoxW",\ ;forwarded export to MessageBoxW in USER32.DLL, \ ;exported by name "UniMsgBox", ordinal = 6. ORD, 7, "USER32.#477" ;forwarded export to MessageBoxA (ordinal 477) in ;USER32.DLL (XP Pro Retail), exported by ordinal 7. Quote Share this post Link to post Share on other sites
Ancient One 3 Report post Posted July 17, 2004 sambung dgn uninitialized array sekali yer isk.. minggu ni takde tutorial la.. nanti la kot aku post 2 sekali. Quote Share this post Link to post Share on other sites
Ancient One 3 Report post Posted July 24, 2004 Biler source file kiter diproses oleh fasm preprocessor engine, ia akan diproses line byline melalui 2 peringkat iaitu line converter (lc) dan line preprocessor (lpp).The Line Converter.Tugas utama lc adalah menyediakan source line yang telah diproses untuk diproses pulak olehlpp. Ini termasuklah tokenizing, removal of garbage characters dan line concatenation. Dalam lc,semer symbol characters kat atas bertindak sebagai simbol dan juga symbol separator. Tabs dan spaceshanya bertindak sebagai symbol separator dan akan dibuang semasa ia ditemui oleh lc. Simbol ;menyebabkan semua characters (termasuk simbol ; sendiri) selepas ; to be ignoredby lc sehingga newline characters ditemui. lc menggunakan cr (0xD) atau lf (0xA) atau kombinasi kedua-duanyasebagai newline characters. They mark the end of a line and lc akan berhenti di sini. Akan tetapi, apabilalc menemui line continuation symbol \, sejurus sebelum newline characters, maka line seterusnyaakan disambung kepada line yang sedang diproses. For the concatenation to be valid, takde characters yang bolehdiletakkan selepas \ kecuali tabs, spaces dan ;. Line seterusnya must be a line,not blank. Ni bermakna, selepas \, there should be at least newline characters. Contohnya (anggapcrlf adalah newline characters) : [B]crlf[/B] [B]crlf[/B] dd 10 \[B]crlf[/B] kod di atas adalah valid sebab after \ ia temui newline characters. Contoh kod kat bawah plak tak valid (eof means end of file). [B]crlf[/B] [B]crlf[/B] dd 10 \[B]eof[/B] Bila lc temui simbol " atau ', maka ia assume characters seterusnya adalah string definition. Dalam string definition, all symbol characters are significant dan dimasukkan dalam output oleh lc. Secara ringkas, dalam string, quotation mark mesti berpasangan, kecuali ia berada di dalam string defined with different quotation mark. Sebagai contoh, kalau kiter gunakan " untuk define string, any usage of " inside the string must be paired (e.g "" mewakili satu "), tapi tidak '. Contoh : "foo" ;valid, string is "foo "foo'bar" ;valid, string is "foo'bar "foo""bar" ;valid, string is "foo"bar 'foo'bas' ;invalid, it should be 'foo''bas' 'foo''''''';valid, string is "foo''' Seperti yang kiter tengok, kecuali di dalam string definition, takde lagi spaces, tabs, cr, lf, \, dan ' characters di dalam output yang dihasilkan oleh lc. " is used to mark a symbol as string. ; is used to mark macro declaration contents. Bila source line dah diproses oleh lc, lc akan menghasilkan "line" baru dan diberikan kepada lpp untuk diproses. "Line" baru ni cuma difahami oleh lpp je. Contoh output kepada lpp (not in internal format) : foo fix\ bar fix\ foo fix\ akan menjadi foo fix bar fix foo fix ;6 symbols foo: fix bar akan jadik foo: fix bar ;3 symbol names, 1 symbol character foo equ db '"foobas"' akan menjadi foo equ db "foobas ;3 symbol names, 1 string The Line Preprocessor. Since lc dah banyak buat keje untuk lpp, tugas lpp hanyalah proses pp directives dan aper2 je la yang related to preprocessing, seperti macro invocation, symbol replacement dan sebagainya. "Line" yang dihasilkan oleh lc contains only symbols. lpp boleh membezakan jenis simbol ni sebab lc dah tandakan setiap simbol ni dengan special value, termasuklah panjang setiap symbol pada permulaan symbol. Normal symbol names are preceded with value 0x1A (byte), diikuti dengan panjangnya (1 byte - ni sebabnya korang takleh gunakan simbol lebih panjang daripada 255 characters). Kalau korang nak tengok camne output yang dihasilkan oleh lc, load fasm executable (CUI) with source file and output name as arguments. Kemudian set breakpoint pada instruction "call preprocess_line" (under "preprocess_source" label), dan dump memory pada address yang dipegang oleh register edi. Beberapa bytes sebelum address ni adalah output yang dihasilkan oleh convert_line function (lc). So, for example, kalau kiter ader source file dengan line seperti berikut : foo: fix db "foobar"\ ,0 output yang terhasil daripada lc adalah (in hex raw data format) : .. 1A 03 66 6F 6F 3A 1A 03 66 69 78 1A 02 64 62 ..foo:..fix..db 22 06 00 00 00 66 6F 6F 62 61 72 2C 1A 01 30 00 "....foobar,..0. .. As you can see, normal symbol name ditandakan dengan value 0x1A, diikuti dengan panjang (foo=3, fix=3, db=2 dan sebagainya). Special character symbols yang dikenali oleh pp (seperti yang aku dah senaraikan kat atas) tidak mempunyai aper2 marker sebab lpp akan mengenalinya. Kemudian string plak mempunyai symbol " sebagai marker diikuti oleh panjang string (4 bytes storage) dan string itu sendiri. Kalau korang perhatikan jugak, dalam preprocessor, nombor pun bleh jadik symbol gak, so kiter bleh buat benda2 pelik seperti "0 fix 1" dan sebagainya! Lpp proses output yang dihasilkan oleh lc mengikut beberapa peraturan dan turutan seperti yang akan aku bincangkan kat bawah : 1. Pertama sekali, lpp akan proses fix directive (directive ni ader la bau2 bacang dengan equ directive). Simbol kedua (dalam "line" yang sedang diproses) akan diperiksa samada ia adalah simbol fix atau tidak (semer check berkaitan dengan pp directives adalah case-sensitive). Kalau simbol kedua tersebut adalah fix, maka lpp consider "line" tersebut adalah constant definition using fix directive (high priority constant definition) atau ringkasnya fix definition. Contoh : foo fix bar ;fix definition foo fix fix bar;fix definition fix fix equ ;fix definition foo! fix if bar+0=1+6-2;fix definition, [B]![/B] bukan special symbol, so it's part of foo symbol name. foo+ fix bar ;not a fix definition (second symbol is "+", not "fix"). SatuDuaTigaEmpatLimaEnamTujuhLapanSembilanSepuluh fix 1,2,3,4,5,6,7,8,9,10 ;fix definition SomeLabel: fix bar ;not a fix definition fix bar ;not a fix definition foo fix ;fix definition Bila fix definition ditemui, sekarang makna fix definition (iaitu semer simbol selepas fix) tuh akan tertakluk kepada fix replacement (change to previously defined fix definition). Sebagai contoh, dalam source file: foo fix bar foo fix foo bar Line pertama adalah fix definition di mana simbol foo dalam line seterusnya akan ditukarkan kepada simbol bar. Then pada line kedua juga adalah fix definition. foo sebelum fix tak akan ditukar kepada bar akan tetapi foo selepas fix akan ditukar kepada bar. So, selepas preprocessing kedua-dua line tersebut, simbol foo hanya mempunyai satu makna, iaitu bar bar. Ini membolehkan kiter redefine fix definition. Contoh lagi : bignop fix times 8 nop bignop ;8 NOPs bignop fix times 4 nop bignop ;4 NOPs Tu kalau line yang diproses adalah fix definition. Jika tidak, semer symbols pada line tersebut akan tertakluk kepada fix replacement. Contoh (full preprocessing): foo fix bar fix fix equ foo: fix bar bar fix foo foo+bar Hasilnya adalah ;foo fix bar ;fix fix equ bar: equ bar ;bar fix bar bar+bar Pada line ketiga, all symbols are subjected to fix replacement (specifically foo dan fix). Bila "line" yang sedang diproses tersebut adalah fix definition, lpp berhenti di sini dan line seterusnya akan diproses oleh lc kemudian oleh lpp. Jika tidak, lpp akan teruskan proses ke bahagian 2 2. Lpp sampai kat sini hanya jika "line" yang diproses bukan fix definition. Kat sini, fix replacement dah dilakukan. Sekarang Lpp akan proses symbol character ` (name to string conversion operator) dan juga # (symbol/string concatenation operator). Note that kedua-dua symbols ni hanya bleh digunakan di dalam macro invocation (occur when you "use" a macro) sahaja, so lpp check global flag (macro_status dalam preproce.inc) untuk memastikan samada ia sedang memproses "line" yang berada dalam macro invocation atau tidak. Jika tidak, ia akan terus ke bahagian 3. Jika ya, ia akan proses dua symbol characters tersebut jika ia wujud di dalam "line" tersebut. ` digunakan untuk menukarkan nama simbol kepada string manakala # digunakan untuk concatenate 2 strings atau dua symbol names (but not mix). Bila dah abish proses, lpp terus ke bahagian 3. (iii)Here, lpp checks a global flag to see whether it is currently processing a macro declaration. If it is, skip them (find end of macro declaration, "}") and lpp ends here. otherwise, proceed to level (iv). 3. Kat sini lpp check global flag (macro_status variable) samada ia sedang process macro declaration atau sedang berada dalam macro declaration. Aper2 pun skip semernya dan lpp berhenti di sini. Jika tidak, ia akan terus ke bahagian 4. Note : Petikan kat bawah diambik daripada flat assembler message board yang menerangkan mengenai macro_status : The lower nibble (bits 0-3) contains the info related to the macroinstruction that is currently being declared, while the higher nibble (bits 4-7) contain the status of processing the macro. The values of lower nibble can be: 0 - no macro is being declared currently, default value; 1 - the declaration of macro has started, but no { - macro contents opening character has been found yet; 2 - the contents of macro declaration is being preprocessed; The higher nibble consist of flags, currently only two are defined: bit 4 (value 10h) - some macro is currently processed; bit 5 (value 20h) - internal flag of macro preprocessor, used to determine whether we are in the place where some macro directive might be used Note that both higher and lower nibble can have non-zero value at the same time, since macro can define some other macro. 4. Sekarang lpp akan check penggunaan pp directives. Directives yang akan diproses di sini adalah include, macro, purge, restore dan struc. Lpp akan check simbol pertama pada "line" ini untuk memastikan ia adalah pp directives. Jika salah satu directives ni ditemui, ia akan diproses : Untuk include directive, jika ia digunakan dengan betul (ia cuma receive quoted string yang menyatakan nama fail untuk diproses), lpp akan preprocess keseluruhan fail tersebut. Lpp berhenti di sini. Untuk purge dan restore, nama simbol yang diberikan sebagai argument akan dibuang daripada internal symbol table. Lpp berhenti di sini. Untuk macro dan struc, lpp akan define/redefine new macro dan set macro_status variable yang menyatakan ia sedang memproses macro definition (atau inside macro definition). Lpp berhenti di sini. Note: Multiline macro contents are also skipped as lpp progress through each line of macro declaration (read of level (iii) again). Note that although procedure (i) and (ii) run before (iii), nothing will affect a macro declaration except a fix replacement. Kalau takde aper2 berlaku kat sini ("line" ni takde pp directives), maka lpp akan ke bahagian 5. Penerangan seterusnya aku singkatkan.. 5. Lpp checks macro invocation yang kiter define sebelumya dengan "macro" directive jika ada. Jika ia adalah macro invocation, lpp proses dan berhenti di sini. Jika tidak ia akan teruskan ke bahagian 6. 6. Lpp preprocess label yang kiter define dengan character : dan kemudian ia akan loop semula daripada bahagian 4 di mana simbol selepas : akan menjadi simbol pertama plak. Equate replacement bleh berlaku di sini. 7. Lpp process symbolic constant definition yang kiter define dengan equ directive. Jika ia bukan equ definition maka lpp ke bahagian 8. 8. Lpp checks macro invocation yang kiter define sebelumnya dengan "struc" directive jika ada. Jika ia adalah macro (struc) invocation, lpp proses dan berhenti di sini. Jika tidak ia akan teruskan ke bahagian 9. 9. Akhir sekali lpp akan process equate replacement. Tu je la kot mengenai fasm preprocessor. Aku tak reti nak explains secara details since benda ni kompleks dan recursive. Tapi aku akan cuba explain mengenai macro dengan lebih mendalam lagi as we use them. Macro yang kiter define dengan macro dan struc directives tak banyak bezanya, cuma cara penggunaannya berbeza. Dengan macro, nama macro tersebut mestilah yang menjadi simbol pertama manakala dengan struc, macro tersebut hendaklah menjadi simbol kedua. Contohnya : macro macro : macro SZTEXT [Text] { common local _start _start: db Text, 0 .SIZE = $-_start .LEN = .SIZE-1 } SZTEXT "Hello Putera.com" .LEN dan .SIZE takde parent label. Kiter takleh invoke SZTEXT macro seperti foo SZTEXT "Hello Putera.com" Sebaliknya struc macro : struc SZTEXT [Text] { common local _start _start: db Text, 0 .SIZE = $-_start .LEN = .SIZE-1 } foo SZTEXT "Hello Putera.com" .LEN dan .SIZE will be attached to foo label. Kiter takleh invoke SZTEXT struc seperti SZTEXT "Hello Putera.com" Okeylah.. meh kiter bincangkan mengenai macro dengan lebih terperinci. Macroinstructions (macro) actually bertujuan untuk define kiter nyer instructions sendiri yang lebih kompleks. Selain daripada tu ia juga bertujuan untuk memudahkan tugas kiter (normally dalam tugas berulang) dan juga menambah keupayaan instructions yang sedia ada. Meh kiter amik contoh memindahkan variable daripada satu lokasi memory ke lokasi yang lain. The x86 asm "mov" instruction tak benarkan arahan seperti ni. So instead of writing something like : ;code .. mov eax, [ebp+0x10] mov [Somevar], eax .. ;data SomeVar dd ? kiter bleh extend "mov" instruction dengan macro : macro mov dest, src { if dest eqtype [] & src eqtype [] push dword src pop dword dest else mov dest, src end if } ;after "mov" macro is defined, semer "mov" instruction sebenarnya adalah ;macro "mov" dan bukannya internal "mov" asm instruction. mov eax, ebx mov [SomeVar], [ebp+14];now this will compiled correctly SomeVar dd ? Contoh kat atas cuma apply to 32 bit operands je. Dah tentulah korang bleh buat yang lebih baik. Ni cuma contoh je. Bila menggunakan macros, kiter perlu tau mengenai internal working of the preprocessor untuk dapatkan hasil yang lebih memuaskan hati sebab fasm nyer macro facility sangatlah berkuasa (tapi taklah sampai bleh buat aper je yang kiter nak). Terdapat beberapa operators dan directives yang hanya bleh digunakan dalam macro seperti common, local, forward, reverse, ` dan juga #. Meh kiter tengok format macro. Untuk define macro, kiter kena gunakan directive macro atau struc, diikuti oleh nama macro dan arguments yang bleh diterimanya (lebih kurang je macam kiter define function). Aper yang mandatori dalam macro definition adalah nama dan juga simbol { dan } yang menandakan permulaan dan pengakhiran suatu macro definition. Please note, macro definition contents bermula pada { yang pertama ditemui dan } yang pertama ditemui. Contoh macro : 1. no-argument macro : macro display_hello {display "hello",13,10} 2. one-argument macro : macro display_text text {display text,13,10} Setiap text yang ditemui dalam macro tersebut akan digantikan dengan argument yang korang berikan untuk text. Contohnya, jika kiter invoke macro display_text seperti : display_text "foo" maka macro tersebut akan menjadi seperti berikut display "foo",13,10 since kiter berikan string "foo" sebagai text argument. Kiter bleh define macro yang terima bilangan arguments yang tidak tetap (seperti dalam C language ...) iaitu dengan menggunakan [] seperti : macro display_text [text] { ;macro contents } Argument yang dikurungkan dengan [] cuma bleh diletakkan sebagai argument terakhir. So macro foo arg1, [argn] { } is valid, tapi tidak macro foo [argn], arg1 { } Terdapat beberapa macro directives yang kiter gunakan untuk define "block of execution". Ia cuma bleh digunakan biler kiter menerima bilangan arguments yang pelbagai. Contohnya, kiter nak suatu arahan tersebut dilaksanakan untuk semer arguments yang kiter terima, maka kiter letakkan arahan2 tersebut di bawah block "common". Bila2 masa kiter gunakan maner2 directive "common", "forward" dan "reverse", arahan di bawahnya adalah tertakluk kepada blok ini sehinggalah directive baru digunakan. Contohnya, kiter bleh gunakan feature nih untuk bina macro "stdcall" yang memanggil fungsi dengan stdcall calling convention : macro stdcall function, [args] { reverse push args common call function } ;usage example stdcall [MessageBoxA], 0, Msg, Caption, 0 ;data Msg db "test", 0 Caption db "title", 0 ;iat MessageBoxA dd ? Macro stdcall menerima dua argument, di mana argument yang kedua adalah group of arguments dan argument yang pertama adalah single argument. Apabila suatu macro menerima group of arguments, default blok jika tiada "common", "forward" atau "reverse" directive digunakan adalah "forward". Dalam stdcall macro di atas, "reverse" menyebabkan arahan di bawahnya diulang sebanyak mana bilangan argument yang diberikan dalam group of arguments, bermula daripada yang terakhir sehinggalah yang terawal. Sebagai contoh, biler kiter gunakan stdcall macro seperti : stdcall foo, a, b, c, d argument foo adalah argument pertama (yang dirujuk sebagai "function" dalam macro declaration) dan argument a, b, c dan d adalah berada dalam group of arguments (yang dirujuk sebagai "args" dalam macro declaration). Arahan "push args" dalam macro tersebut berada di antara directive "common" dan "reverse" di mana ia berada di skop "reverse". Ini bermakna, ia akan dilaksanakan sebanyak 4 kali, bermula daripada argument d, c, b dan berakhir pada argument a. So, .. reverse push args .. actually expands to push d push c push b push a Blok "reverse" berakhir apabila preprocessor menemui plak directive "common". Arahan di bawah block "common" cuma akan dilaksanakan sekali, common to all arguments. Ni bermakna, arahan "call function" di bawah "common" blok cuma akan diulang sekali, tidak kira berapa banyak argument yang diberikan dalam group arguments. So .. common call function .. will expands to call foo dalam penggunaan "stdcall foo, a, b, c, d". Dah tentulah "foo", "a", "b", "c" dan "d" must be valid operands untuk "push" dan "call" instructions. Please note, block directives ni cuma apply kepada macro yang mempunyai group arguments. Dalam macro juga kiter bleh define local symbols yang local kepada macro tersebut. Each time kiter invoke macro ni label ni akan berubah nama so kiter tak akan dapat duplicate label name setiap kali kiter gunakan macro tersebut. Ini dicapai dengan "local" directive. Contohnya : macro foo { local foobar foobar: } foo foo Setiap kali kiter invoke macro foo, label "foobar" akan berubah nama (modified internally by preprocessor) since it's local to the macro. Aku akan discuss mengenai macroinstructions lagi sepanjang tutorial nih. Sebelum tuh meh kiter tengok dulu beberapa assembler directives yang berguna. Pertama sekali adalah use16 dan use32 directives. Directives ni menyebabkan instructions selepasnya dihimpunkan dalam mode yang ditetapkan (16 bit atau 32 bit). Contohnya : use16 mov eax, ebx ;fasm insert operand size override prefix (0x66) since opers adalah 32 bit register use32 mov eax, ebx ;takde oper size override prefix use16 mov ax, bx ;takde oper size override prefix use32 mov ax, bx ;ader oper size override prefix Tanpa format directive ataupun explicit use* directive, fasm akan assume 16 bit code untuk dihasilkan (use16). Kemudian kiter ader org directive yang membolehkan kiter berikan new value untuk current address (dalam MEMORY) di maner arahan sedang dikompil. Kiter bleh dapatkan current address dengan operator $. Contohnya : use32 ;kat sini $ adalah 0. foobar db 0 mov eax, foobar;foobar = 0 --> mov eax, 0 org 10 foobas db 0 mov eax, foobas;foobas = 10 --> mov eax, 10 ...bersambung... Quote Share this post Link to post Share on other sites
Ancient One 3 Report post Posted July 31, 2004 Quote Share this post Link to post Share on other sites
Ancient One 3 Report post Posted August 7, 2004 Maser aku tulis benda alah ni, FASM 1.54 dah kluar dah. Takde feature yang baru, cumaperubahan preprocessor behaviour di maner fasm sekarang dah terima commands selepasend of macro declaration. Contohnya, sebelum version 1.54 kuar, kod macro foo {} foobas fix bar takleh pakai. Tapi dalam version 1.54 ia dah bleh dipakai dah dan foobas symbol selepas } diterima sebagai fix definition. Lain dari tu takde yang menarik, cuma perubahan kepada formatter dan MS COFF symbols. Oh yerr.. aku baru plak perasan yang kiter bleh gunakan real numbers sebagai memory address. Walaupun tak laa nampak ader kegunaannya tapi aku rase menarik gak dan ia bleh menyelesaikan beberapa masalah. Tapi biasanya kiter takkan guna feature ni. Contoh penggunaan adalah biler kiter nak push floating point constant, kiter bleh gunakan arahan seperti berikut : lea edx, [1.234] push edx hehehe.. menarik gak. Actually aku tak tau plak aper nak citer lagi. Aku ingat pas ni nak citer pasal assembler lain laa, terutama mengenai RosAsm (Assembler yang kononnya dibina khas untuk ReactOS) dan juga GoAsm. Actually dah braper tahun dah aku tak sentuh assembler lain daripada FASM. Ni baru je download latest version. RosAsm sebenarnya bleh dikatakan menarik gak tapi sayangnya penulisnya terrrrrlalu... tah la aper nak cakap. Benda pertama yang aku benci pasal RosAsm adalah IDEnya. Takde command line version. IDE plak bukannya tak cukup power.. tapi tak sesuai (dan memang tak cukup power) untuk aku. Pastu syntax yang pelik dan tah aper2. Macro facilities bagus gak, takde komen, cuma aku tak suker jenis camni.. payah nak paham biler dah buat macro yang kompleks. Namun begitu, ia membolehkan kiter buat macro yang ringkas. Contohnya STDCALL macro : [push | push #1 | #+1] [STDCALL | push #L>2 | call #1] Ringkas je kan.. Tapi aku takleh nak ingat la part symbols macro argument ni selalunya. So kalau aku nak tulis macro dalam RosAsm, selalu je kena bukak manual.. Bosan! FASM pun sebenarnya banyak gak problems. Yang pertama dia takde built-in conditional preprocessing. Kalau ader benda alah ni, aku dapat rasakan kiter bleh buat macros yang panjang dan kompleks tanpa melembabkan keseluruhan proses kompilasi program. Pastu plak kod yang simple camni if ~defined foo foo=0 end if pun dia takleh kompil. kemudian kiter takleh test constant yang belum kena define seperti if foo = 0 ;... end if Nak tak nak kena la buat camni if defined foo if foo=0 ;... end if end if At least kalau bleh buat camni pun bagus gak if defined foo & foo=0 ;... end if Kiter takleh buat camni sebab walaupun if defined foo dah salah, fasm tetap evaluate foo=0. Maknanya error (seperti yang pertama tadi). Kalau dia buat short-circuit evaluation, expression foo=0 dia tak perlu la test lagi. Part macro pun banyak gak kelemahan, contohnya dia tak fully support nested macros declaration so kiter tak perlu la buat fix constant yang pelik2. Biasanya kiter akan buat nested macro (contoh 1 level depth) camni : macro foo { macro bar { %end% } %end% fix } Kiter takleh tutup macro kat dalam dengan } kerana ia akan menyebabkan macro foo akan berakhir di situ (dan } yang kedua akan menyebabkan preprocessing error). Maknanya kalau kiter ader nested macros sehingga 2 levels, kiter kena buat camni : macro foo { macro bar { macro bas { %end01% %end% } %end01% fix %end% %end% fix } 3 levels plak : macro foo { macro bar { macro bas { macro foobar { %end02% %end01% %end% } %end02% fix %end01% %end01% fix %end% %end% fix } dan seterusnya laaa.. Begitu jugak dengan symbol characters ` dan #. Tu belum lagi kalau dah ader multiple files. Kan elok kalau fasm bleh treat nested macros camni : macro level0 { macro level1 { macro level2 { macro level3 { } } } } Satu lagi problem adalah pada macro yang ader group argument ni. Dia nyer forward atau reverse at least jalan sekali walaupun takde argument diberikan. Contohnya : macro foo [arg] { forward display "test",13,10 } foo (Actually kalau kiter fikir lagi mengenai benda ni, memang tak salah pun ... aku sajer2 je.).Aku berenti kat sini je la.. takde modal la ari ni. Tak tau nak citer aper. Lagipun aku nak createinclude files baru yang serasi dengan fasm 1.54 aku ... Enjoy! Quote Share this post Link to post Share on other sites
Ancient One 3 Report post Posted August 14, 2004 site aku sekarang didedikasikan khas untuk fasm.. so aku stop posting kat sini laaa..http://www26.brinkster.com/paipx Quote Share this post Link to post Share on other sites