Iczelion’s Tutorial Win32 ASM Tutorial 2 : MessageBox
Tìm hiu v MessageBox
Trong bài viết này, chúng ta s to ra mt MessageBox vi ni dung
Win32 assembly is great
Tng quan v lp trình trên Windows
H điu hành (HĐH) cung cp cho các lp trình viên ngun tài nguyên phong phú
để h lp trình các ng dng chy trên nn tng Wins. Đáng k nht là phi nói đến là
Windows API (Application Programming Interface). Nó được xem như là tp hp hu hết
các hàm đặc trưng thường dùng, và được các ng dng Win32 s dng. Nhng hàm này
được cha trong các thư vin liên kết động (DLLs) như: kernel32.dll, user32.dll
gdi32.dll.
Kernel32.dll cha các hàm và th tc mà mt h điu hành truyn thng qun lý
như: qun lý b nh, xut nhp tp tin và qun lý tiến trình (là quá trình thc hin mt
chương trình t khi khi động đến khi kế thúc).
User32.dll qun lý giao din người dùng (the user interface aspects) , cài đặt tt
c khung ca s mc lun lý chương trình ca bn.
Gdi32.dll cung cp toàn b giao din thiết b đồ ha (Graphics Device Interface)
cho phép chương trình ng dng hin th văn bn và đồ ha trên các thiết b xut phn
cng như màn hình và máy in.
Ngoài 3 thư vin chính trên, HĐH còn cung cp nhng thư vin khác mà chương
trình ca bn có th dùng, min là bn có đầy đủ các thông tin v các “yêu cu” cho hàm
API.
Trong mt chương trình Windows, có s khác bit khi ta gi mt hàm ca thư vin
ngôn ng (chng hn C, ASM,) và mt hàm ca HĐH Windows (các hàm API) hay
thư vin liên kết động cung cp. Đó là khi biên dch thành mã máy (machine code), các
hàm thư vin ngôn ng s được liên kết thành mã chương trình (source code). Trong khi
các hàm Windows s được gi khi chương trình cn dùng đến ch không liên kết vào
chương trình. Để thc hin được các li gi này thì mt chương trình trình Windows
*.EXE luôn cha mt tham chiếu đến thư vin liên kết động khác mà nó cn dùng. Khi
đó, mt chương trình Windows được np vào b nh s to thành con tr tham chiếu đến
nhng hàm thư vin DLLs mà chương trình dùng, nếu thư vin này chưa được np vào b
nh trứơc đó thì bây gi s np
Chương trình liên kết động vi các DLLs này, nghĩa là code ca hàm API s
không được include vào trong file .EXE ca chương trình. Để chương trình ca bn biết
tìm các hàm API mà nó đang cn “ đâu” trong lúc chương trình đang thc thi, thì bn
phi gn thông tin nhn biết nó vào trong file .EXE. Thông tin này nm trong “thư vin
nhp” (import libraries) đặc bit được cung cp bi môi trường lp trình. Bn phi liên
kết chương trình vi thư vin được import mt cách chính xác, nếu không, thì nó s
không th tìm được các hàm API mà chương trình cn s dng.
Khi mt chương trình được np vào b nh, HĐH s đọc các thông tin ca
chương trình. Các thông tin này chính là tên ca các hàm (function) đưc s dng trong
chương trình và các thư vin DLLs mà các hàm s dng cha trong nó. Khi HĐH tìm
thy các thông tin như thế trong chương trình, nó s load các DLLs và thc hin vicliên
kết địa ch ca các hàm trong DLLs vào trong chương trình ca bn, vì vy các li gi
Người dch: Benina (REA TEAM) Trang 1
Tng hp và hiu chnh: NhatPhuongLe (VNCERT TEAM)
Iczelion’s Tutorial Win32 ASM Tutorial 2 : MessageBox
hàm được xem như s chuyn quyn điu khin đến đúng hàm API mà chương trình s
dng khi thc thi.
hai loi hàm API: mt cho h thng ký t ASCII (là các hàm dành cho các
HĐH t Wins 98 tr v trước, không h tr Unicode) và mt cho UNICODE (đây là do
thut ng dân lp trình gi tt, nhưng bn phi hiu là nó vn là chun ANSI; nó ch khác
ch là có b sung các hàm h tr Unicode và chun này có được h tr t HĐH Wins
2000/WinNT tr v sau này). Tên ca hàm cho ký t ASCII được gn hu tA” như
MessageBoxA. Còn tên hàm cho UNICODE có hu t là “W” (viết tt ca wide
character ký t m rng).
Chúng ta thường quen dùng nhng chui (string) ANSI, chúng là mt mng các ký
t kết thúc bng ký t NULL (\0). Các ký t ASCII có kích thước 1 byte. Chúng ta thy
rng, vi độ dài 8-bit ca mã ANSI ch đủ biu din đủ cho ngôn ng các nước thuc
Châu Âu, còn vi các ngôn ng khác thì không, vi hàng triu các ký t riêng bit. Đó
chính là khái nim sơ khi ca Unicode. UNICODE là mt h thng 16-bit đồng nht,
cho phép có kích thước 2 byte, cho phép biu din đến 65536 ký t. Điu này đủ cho tt
c các ký t và ch tượng hình trong tt c các ngôn ng viết ca thế gii, bao gm nhiu
ký hiu toán hc, biu tượng, … Sau này, UNICODE được phát trin thành h thng
32-bit.
Đa phn bn s dùng mt file include (file có phn m rng .INC) mà nó có th
xác định và chn la các hàm API thích hp cho platform ca bn. Nó ch tham chiếu đến
các tên hàm mà không có các hu t nói trên.
Cu trúc ca mt chương trình ASM 32-bit
Tôi
s trình bày cu trúc thường thy ca mt chương trình ASM. Sau đó, chúng ta
s tìm hiu tng t khóa (keyword) mt cách chi tiết hơn :
Chương trình s thc thi bt đầu t ch th sau nhãn <label> đưc ch định (nhãn
start) cho đến ch th end <label> (end start). Trong cu trúc trên, quá trình thc thi s
bt đầu t ch th đầu tiên đứng sau nhãn start. Quá trình thc thi s thc thi t ch th này
đến ch th kế cho đến khi gp ch th điu khin như jmp, je, ret … Các ch th điu
khin này s làm r nhánh lung ch th này sang lung ch th khác. Khi chương trình cn
thoát để v li Window, nó s gi API ExitProcess.
Người dch: Benina (REA TEAM) Trang 2
Tng hp và hiu chnh: NhatPhuongLe (VNCERT TEAM)
Iczelion’s Tutorial Win32 ASM Tutorial 2 : MessageBox
Dòng lnh trên đây được gi là mt prototype (khai báo tên hàm) ca hàm. Khi khai báo
mt prototype, tđịnh nghĩa các thuc tính ca hàm cho trình hp dch và trình liên kết
biết để nó có th thc hin vic kim tra cú pháp giúp bn. Cú pháp khai báo mt
prototype ca hàm như sau:
Tên_hàm PROTO Tên_tham_s_1 : <Kiu d liu> , Tên_tham_s_2 : <Kiu d liu>
Tóm li, tên hàm đứng trước t khóa PROTO và sau đó là danh sách các kiu d liu ca
các tham s, cách nhau bi du phy. Trong hàm ExitProcess như ví d trên, nó định
nghĩa hàm ExitProcess như mt hàm ch có duy nht mt tham s có kiu là DWORD.
Các prototype ca hàm rt hay dùng khi bn s dng cú pháp gi hàm cp cao là Invoke
(thc thi hàm). Bn có th nghĩ rng Invoke như là mt li gi hàm đơn gin, nó được
gi để kim tra li cú pháp. Ví d, bn mun gi gi hàm ExitProcess để thoát, bn s
viết như sau : Call ExitProcess hoc Invoke ExitProcess
Khi không đẩy mt tham s kiu DWORD vào trong ngăn xếp, thì trình hp dch và trình
liên kết s không th bt li cho bn. Bn ch nhn biết li này khi chương trình ca bn
b treo. Nhưng nếu bn dùng INVOKE ExitProcess thì trình liên kết s thông báo cho
bn biết rng “Bn ơi, bn quên đẩy mt tham s có kiu là DWORD vào trong stack
ri kìa!”, như thế s ngăn đưc li này. Tôi khuyên bn nên dùng Invoke thay cho mt
li gi hàm đơn gin. Cú pháp ca INVOKE như sau:
Invoke Biu thc [,Các đối s]
Biu thc có th là tên ca mt hàm, hay nó có th là mt con tr hàm. Các tham
s hàm ngăn cách bi du phy. Hu hết các prototype ca hàm API được khai báo trong
trong file include (file có phn m rng là .INC). Nếu bn dùng hutch’s MASM32, chúng
s nm trong thư mc MASM32/include.
Các file include có phn m rng là .INC và các prototype cho các hàm trong
mt DLL được cha trong file .INC vi cái tên ging như tên file DLL.
Ví d, hàm ExitProcess được export bi kernel32.lib vì vy các prototype cho hàm
ExitProcess được cha trong kernel32.inc.
Bn cũng có th cài đặt prototype ca hàm cho chính các hàm do chính bn lp
trình. Trong các ví d ca tôi, tôi s dùng hutch’s window.inc mà bn có th download ti
http://win32asm.cjb.net. Bây gi tr li vi hàm ExitProcess, tham s uExitCode là giá
tr mà bn mun chương trình tr v cho Windows sau khi chương trình kết thúc. Bn có
th gi ExitProcess như sau: Invoke ExitProcess, 0
Nếu bn đặt dòng lnh này (Invoke ExitProcess, 0 ) ngay dưới nhãn start, bn s
có mt chương trình Win32 ASM ch có chc năng thoát v Windows, nhưng dù sao nó
cũng là mt chương trình hoàn toàn hp l và không b crash.
Người dch: Benina (REA TEAM) Trang 3
Tng hp và hiu chnh: NhatPhuongLe (VNCERT TEAM)
Iczelion’s Tutorial Win32 ASM Tutorial 2 : MessageBox
Source code ca mt chương trình ASM. Chương trình này đơn gin là sau khi được load
lên b, ngay lp tc s được thoát ra, tr quyn kim soát v cho HĐH :
Gii thích:
option casemap:none: nói cho MASM biết rng tên các nhãn trong chương trình phân
bit ch hoa, ch thường, vì vy ExitProcess s khác vi exitprocess.
include: ch th này được theo sau là tên file (nói chính xác là tên ca thư vin nhp) mà
bn mun liên kết vào, để khi chương trình được thc thi, thì nó s tìm các hàm API nào
được s dng trong các “thư vin nhp”.
Chú ý: Tên file được cha trong đường dn tương đối hoc tuyt đối, nghĩa là nếu
bn đang mun liên kết vi các file thư vin ca trình biên dch (c th thông qua tên ca
thư vin nhp) cho chương trình bn s dng khi thc thi, và bn đã ch rõ trong lúc cu
hình rng môi trường lp trình (IDE) s dng trình biên dch này để làm trình biên dch
chính ca IDE (nếu như trên máy ca bn có nhiu trình biên dch) thì ch cn ghi đưng
dn tương đối mà thôi.
Để khai báo ch th include theo đường dn tương đối đối include
windows.inc
Ngược li, phi ghi đường dn tuyt đối để cho IDE giao nhim v tìm thư vin mà
chương trình cn cho trình biên dch, vì thế phi ghi rõ chính xác rng trình biên dch cn
phi tìm nó (thư vin nhp) nm đâu, trong thư mc nào, nếu như thư vin nhp đó
được s dng cho nhiu template khác nhau (template đây hiu theo nghĩa là có nhiu
dng ng dng trong ng dng chy trên nn Wins, thí d đối vi ngôn ng C for Wins,
cũng cùng là ng dng chy trên nn Windows, nhưng ng dng được code theo template
Win32 Application thì khác vi ng dng được code theo template MFC Application).
Để khai báo ch th include theo đường dn tuyt đối
include \masm32\include\windows.inc
Người dch: Benina (REA TEAM) Trang 4
Tng hp và hiu chnh: NhatPhuongLe (VNCERT TEAM)
Iczelion’s Tutorial Win32 ASM Tutorial 2 : MessageBox
Trong ví d trên, khi MASM thc thi dòng include \masm32\include\windows.inc, nó
s tìm file windows.inc trong thư mc \masm32\include\ và thc thi ni dng ca file
windows.inc cũng như bn copy ni dung ca window.inc vào thay thế cho câu lnh.
Thư vin windows.inc cha hu hết (không phi là bao hàm tt c) các định nghĩa ca
hng s và cu trúc mà bn cn trong chương trình Win32 ASM. Nó không cha bt k
prototype hàm nào. Có rt nhiu hng s và cu trúc, mà trong windows.inc chưa được
định nghĩa. Nó s đưc cp nht mt cách thường xuyên.
T window.inc, chương trình có được các hng s và các định nghĩa cu trúc. Đối vi
các prototypes ca hàm, bn cn phi include các file include khác. Chúng được đặt trong
thư mc \masm32\include. Trong ví d trên, chúng ta gi mt hàm được export bi
kernel32.dll, vì vy chúng ta cn phi include prototypes hàm t kernel32.dll. File đó là
kernel32.inc. Nếu bn open nó bng mt chương trình san tho editor bn s thy rng
nó cha đầy các prototyes ca hàm trong kernel32.dll. Nếu bn không include
kernel32.inc, bn vn có th gi hàm ExitProcess nhưng ch vi li gi hàm là Call
ExitProcess. Bn không th invoke hàm được.
Đim cn chú ý đây là để invoke mt hàm, bn phi đặt prototyes ca chính hàm
đâu đó trong mã ngun chương trình.
Nếu bn không include kernel32.inc, bn có th định nghĩa prototype ca hàm
bt k đâu trong mã ngun trên, lnh invoke và nó s làm vic. File include rt tin dng,
s giúp bn s dng các prototypes ca hàm do bn to ra bt c khi nào khi bn có nhu
cu tái s dng.
Bây
gi chúng ta s tìm hiu vi mt ch th mi, đó là includelib. includelib
không làm vic ging như include. Nó báo cho trình hp dch biết thư vin nhp nào mà
chương trình ca bn cn s dng. Khi trình hp dch thy ch th includelib, nó s đặt
mt lnh linker vào trong file object, để trình liên kết s biết được thư vin nhp nào mà
chương trình bn cn để liên kết. Tuy vy, không bt buc phi s dng ch th includelib.
Bn có th ch tên ca thư vin import trong dòng lnh ca linker nhưng hãy tin tôi đi, nó
rt mt mõi, đồng thi dòng lnh ch có th ti đa là 128 ký t mà thôi. Bn nên s dng
ch th includelib thì tt hơn.
Người dch: Benina (REA TEAM) Trang 5
Tng hp và hiu chnh: NhatPhuongLe (VNCERT TEAM)