Tải bản đầy đủ (.pdf) (4 trang)

Căn bản về lập trình ASM trên Windows

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (232.96 KB, 4 trang )

Iczelion’s Tutorial Win32 ASM Tutorial 1 : The Basic
Căn bản về lập trình ASM trên Windows

Tổng quan về hệ thống

Các ứng dụng c
hạy trên nền tảng hệ điều hành Windows 32-bit, nó được chạy dưới
chế độ bảo vệ mà chế độ này được sử dụng từ thế hệ bộ vi xử lý 80286. Nhưng bây giờ
80286 không còn được sử dụng nữa. Vì vậy, chúng ta chỉ quan tâm đến các thế hệ từ bộ
vi xử lý 80386 trở về sau. Hệ điều hành thực thi mỗi ứng dụng trong một vùng nhớ ảo
đư
ợc định sẵn. Điều này có nghĩa là mỗi chương trình Win32 sẽ có riêng cho mình một
vùng nhớ địa chỉ đến 4GB. Tuy nhiên điều này không có nghĩa là mỗi một chương trình
đều được cấp 4GB vùng nhớ vật lý, mà chỉ có nghĩa là chương trình có thể định địa chỉ
trên bộ nhớ trong vùng 4GB này thôi mà thôi. Hệ điều hành sẽ làm điều gì đó để chương
trình có thể tham chiếu đến các giá trị trong vùng nhớ trên. Dĩ nhiên là chương trình sẽ
phải bám vào các qui tắc mà hệ điều hành đã qui định, nếu khác nó sẽ gây ra lỗi
protection. Mỗi chương trình là “độc quyền” trong vùng địa chỉ của nó. Điều nà
y trái
ngược với các chương trình chạy trên nền tảng Windows 16-bit. Tất cả các chương trình
trong Windows 16-bit có thể “nhìn” thấy nhau. Nhưng dưới chế độ 32-bit. Điều này sẽ
giảm bớt việc thay đổi một chương trình viết đè lên CO
DE hay DATA của một chương
trình khác.

Mô hì
nh bộ nhớ cũng khác xa 16-bit. Dưới chế độ 32-bit chúng ta không cần quan
tâm đến mô hình bộ nhớ hay khái niệm đoạn (segment) trong 16-bit. Chỉ có một kiểu bộ
nhớ là kiểu bộ nhớ phẳng (Flat memory). Không có khái niệm “mỗi segment chứa
không quá 64KB” trong 16-bit. Bộ nhớ trong chế độ 32-bit là một vùng liên tục 4GB.
Điều đó cũng có nghĩa là bạn không phải quan tâm đến những tha


nh ghi đoạn. Bạn có thể
dùng bất kỳ thanh ghi đoạn nào để định một địa chỉ bất kỳ trên vùng nhớ. Điều này giúp
ích cho các lập trình viên rất nhiều. Đây cũng là những gì giúp cho việc lập trình trên hợp
ngữ 32-bit dễ dàng hơn lập trình trong C.

Khi bạn lập trình hợp ngữ tr
ong chế độ 32-bit, bạn phải biết vài quy tắc quan
trọng. Một trong những quy tắc đó là :

Hệ điều hành dùng các thanh ghi ESI, EDI, EBP, và EBX khi đang xử lý một tác
vụ nào đó và nó sẽ không cho phép thay đổi giá trị của các thanh ghi đó. Vì vậy hãy nhớ
quy tắc đầu tiên như sau : Nếu bạn dùng một trong 4 thanh ghi đó trong các hàm có thuộc
tính callback, thì đừng quên phục hồi lại giá trị trước đó của các thanh ghi đó trước khi
trả lại điều kiển cho hệ điều hành xử lý. Một hàm có thuộc tính callback thì cũng đồng
nghĩa rằng hàm
đó được gọi bởi hệ điều hành. Hiển nhiên đó là một thủ tục của Windows,
gọi là Windows Procedure. Điều này không có nghĩa là bạn không được dùng một trong
4 thanh ghi trên, bạn vẫn có thể sử dụng nhưng chắc rằng bạn sẽ phục hồi lại giá trị cho
nó trước khi bạn chuyển quyền điều khiển chương trình cho hệ điều hành.

Người dịch: Benina (REA TEAM) Trang 1
Tổng hợp và hiệu chỉnh: NhatPhuongLe (VNCERT TEAM)
Iczelion’s Tutorial Win32 ASM Tutorial 1 : The Basic
Lập trình ASM 32-bit

Đây là phát họa của một chương trình hợp ngữ trên nền 32-bit. Nếu bạn không
hiểu những gì sau đây bạn đừng quá bối rối. Tôi sẽ giải thích cặn kẽ ở các bài viết sau.




Chúng ta hãy cùng nhau phân tích ý nghĩa của các dòng lệnh trên!


.386  Đây là một chỉ thị nhằm nói cho MASM biết rằng chương trình của bạn đang sử
dụng cấu trúc bộ lệnh 80386. Bạn có thể dùng .486 hay .586 nhưng an tòan nhất hãy bám
vào cấu trúc .386. Trong thực tế có hai cấu trúc gần giống nhau về hình thức cho mỗi kiểu
CPU. .386/.386p, .486/.486p. Chữ “p”(viết tắc của từ privileged : có nghĩa là được ưu
tiên), có nghĩa là chỉ khi nào cần thiết thì chương trình của bạn đư
ợc ưu tiên sử dụng một
số chỉ thị của bộ lệnh này. Những chỉ thị đó là những chỉ thị được dịch ngược lại bởi CPU
khi nó đang họat động chế độ bảo vệ. Phần lớn các chương trình của bạn làm việc trong
chế độ Non-p vì vậy để an tòan hãy dùng phiên bản Non-p.

.MODEL FLAT, STDCALL
.MODEL chỉ rõ kiểu bộ nhớ đang sử dụng c
ho chương trình. Lưu ý rằng chỉ có duy nhất
một kiểu bộ nhớ trên nền Win32 đó là flat memory, kiểu bộ nhớ này nó không phụ thuộc
vào loại ứng dụng mà bạn đang phát triển (Standard EXE, DLL, static library, console, ..).
Điều này cũng nói cho chúng ta biết rằng, bạn không cần quan tâm đến kiểu bộ nhớ hoặc
phân đoạn giống như chúng ta đã từng làm
ngày trước trên nền 16bit.
STDCALL sẽ thông báo cho MASM biết cách truyền các tham số cho các hàm là như thế
nào. Quy ước truyền tham số chỉ ra thứ tự của tham số được truyền là từ trái qua phải hay
từ phải qua trái và cũng chính nó cân bằng trạng thái (thứ tự) ngăn xếp khi hàm được gọi.
Người dịch: Benina (REA TEAM) Trang 2
Tổng hợp và hiệu chỉnh: NhatPhuongLe (VNCERT TEAM)
Iczelion’s Tutorial Win32 ASM Tutorial 1 : The Basic
Dưới chế độ 16-bit, 2 ngôn ngữ C và Pascal có quy ước truyền tham số như sau :

 Qui ước trong C : truyền tham số từ phải sang trái, điều này có nghĩa tham số bên

phải ngoài cùng sẽ được PUSH vào STACK trước tiên. Hàm gọi thủ tục (caller)
phải chịu trách nhiệm cân bằng cấu trúc STACK sau khi gọi.
Ví dụ, để gọi một hàm có tên là :
Tên_hàm (<kiểu dữ liệu> tham số thứ 1, <kiểu dữ liệu> tham số thứ 2,
<kiểu dữ liệu> tham số thứ 3)
theo qui ước trong C, thì code asm sẽ như sau:
push [tham số thứ 3] ; Đẩy tham số thứ 3 vào ngăn xếp đầu tiên
push [tham số thứ 2] ; Kế tiếp đến tham số thứ 3
push [tham số thứ 1] ; Sau cùng là tham số thứ 1
call Tên_hàm ; Lời gọi hàm thực thi
add sp, 12 ; Cân bằng trạng thái của ngăn xếp

 Qui ước trong Pascal : ngược lại quy ước trong C. Nó truyền tham số từ trái sang
phải. Và hàm bị gọi (Callee) có nhiệm vụ cân bằng STACK sau khi gọi.

Win-
16bit chấp nhận quy ước trong Pascal bởi vì nó phát sinh ra những đoạn code nhỏ.
Quy ước trong C thì thường dùng khi bạn không biết bao nhiêu tham số được truyền cho
hàm như trong trường hợp hàm wsprintf(). Trong trường hợp này, hàm sẽ không có cách
nào xác định được có bao nhiêu tham số sẵn sàng để đẩy (PUSH) vào ngăn xếp
(STACK), vì vậy nó không thể nà
o làm chức năng cân bằng STACK.

STDCALL là quy ước “n
goại lai” của hai quy ước gọi hàm trong C và Pascal. Nó truyền
tham số từ phải sang trái, nhưng hàm bị gọi (Callee) sẽ chịu trách nhiệm cân bằng
STACK sau khi gọi. Win32 platform dùng độc quyền STDCALL. Ngọai trừ 1 trường
hợp: wsprintf(). Bạn phải dùng quy ước gọi hàm trong C với hàm wsprintf().

.DATA

.DATA?
.CONST
.CODE

Tất cả 4 chỉ thị trên được gọi là Section (đoạn). Bạn không có khái niệm segments trong
Win32 (
khái niệm này chỉ có trong Win16), hãy nhớ kỹ điều đó. Nhưng bạn có thể chia
toàn bộ vùng địa chỉ của bạn thành những Logical Section. Đầu của một section là đích
của một section kế tiếp. Có 2 nhóm section : data và code.

Người dịch: Benina (REA TEAM) Trang 3
Tổng hợp và hiệu chỉnh: NhatPhuongLe (VNCERT TEAM)
Iczelion’s Tutorial Win32 ASM Tutorial 1 : The Basic
Người dịch: Benina (REA TEAM) Trang 4
Tổng hợp và hiệu chỉnh: NhatPhuongLe (VNCERT TEAM)
Data sections được chia ra làm 3 lọai :
.DATA – chỉ rõ đây là section dành cho dữ liệu và dữ liệu (cụ thể là các biến) được gán
giá trị khởi tạo ngay từ đầu chương trình của bạn.
.DATA? – chỉ rõ đây là section chứa dữ liệu không được gán giá trị khởi tạo. Đôi khi bạn
muốn chỉ định vài vùng nhớ nhưng không muốn cho nó chứa giá trị nào lúc khởi tạo.
Section này dành cho mục đích đó. Lợi thế của chỉ thị này là : không c
hiếm khoảng trống
trong file thực thi (hay nói cách khác kích thước của file trên đĩa không tăng khi sử dụng
chỉ thị này để chứa dữ liệu).
Ví dụ
: Nếu bạn chỉ định 10.000 Bytes (10 KB) trong khai báo .DATA? section, file exe
của bạn sẽ không tăng thêm 10.000 Bytes. Kích thước của nó sẽ không nhiều như vậy. Ở
đây bạn chỉ nói cho asm biết khoảng trống bao nhiêu bạn cần khi chương trình được load
vào bộ nhớ.
.CONST – chỉ rõ đây là section chứa hằng số đư

ợc dùng trong chương trình của bạn.
Những hằng số trong section này sẽ không thay đổi.

Chú ý : Bạn không phải sử dụng cả 3 section trên trong chương trình của bạn.
Chỉ khai báo những section nào bạn muốn dùng.

Chỉ có 1 section cho code đó là .C
ODE . Đây là nơi chứa code chương trình của bạn.
<label> :
end <l
abel>

Ở đây
<label> là một nhãn bất kỳ được dùng để chỉ định khỏang rộng của code bạn. Hai
nhãn <label> trên , dưới phải giống nhau. Tất cả các code của bạn phải được đặt trong
<label> và end <l
abel>.

01 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
02 ; Hello.asm
03 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
04 .386
05 .model flat,stdcall
06 option casemap:none
07 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
08 include windows.inc
09 include user32.inc
10 includelib user32.lib
11 include kernel32.inc
12 includelib kernel32.lib

13 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
14 .data
15 szCaption db 'A MessageBox !',0
16 szText db 'Hello, World !',0
17 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
18 .code
19 start:
20 invoke MessageBox,NULL,offset szText,offset szCaption,MB_OK
21 invoke ExitProcess,NULL
22 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
23 end start

×