Twitter Delicious Facebook Digg Stumbleupon Favorites More

Thứ Năm

Ngôn ngữ lập trình assembly

1. Khởi động debug

Chương trình Debug chạy trong chế độ dòng lệnh của DOS

Khởi động chế độ gõ lệnh trong Windows 9.x:

[Start][Run][Open:]command[OK]

Hoặc

[Start][Run][Programs][Accessories][MS-DOS Prompt]

Hoặc kích đúp vào

C:\Windows\Command.com



Xem hướng dẫn đơn giản:

PROMPT> DEBUG /? <enter>



Các lệnh của Debug bao gồm:

assemble A [địa_chỉ]

compare C phạm_vi địa_chỉ

dump D [phạm_vi]

enter E address [danh_sách]

fill F phạm_vi danh_sách

go G [=địa_chỉ] [địa_chỉ]

hex H giá_trị_1 giá_trị_2

input I số_hiệu_cổng

load L [địa_chỉ] [ổ_đĩa] [séc_tơ_đầu] [số_lượng]

move M phạm_vi địa_chỉ

name N [tên_đường_dẫn] [danh_sách_tham_số]

output O số_hiệu_cổng giá_trị

proceed P [=địa_chỉ] [số_lượng]

quit Q

register R [số_hiệu_thanh_ghi]

search S phạm_vi danh_sách

trace T [=địa_chỉ] [giá_trị]

unassemble U [phạm_vi]

write W [địa_chỉ] [ổ_đĩa] [séc_tơ_đầu] [số_lượng]

allocate expanded memory XA [#số_trang]

deallocate expanded memory XD [handle]

map expanded memory pages XM [Lpage] [Ppage] [handle]

display expanded memory status XS



Ý nghĩa của một vài lệnh:



- D Viết ra màn hình nội dung của một vùng nhớ

- Q Thoát khỏi chương trình

- S Tìm kiếm

- H Phép toán số học dưới dạng cơ số 16

- R Viết ra màn hình hoặc thay đổi giá trị của các thanh ghi

- E Nhập dữ liệu vào bộ nhớ

- G Thực hiện một chương trình trong bộ nhớ

- U Thể hiện mã máy dưới dạng mã từ gợi nhớ

- T Thực hiện một chỉ thị

- P Thực hiện nhiều chỉ thị

- A Nhập dữ liệu vào bộ nhớ dưới dạng mã từ gợi nhớ

- N Tên của chương trình

- W Viết một chương trình đã được đặt tên vào bộ nhớ

- L Tải một chương trình từ đĩa vào bộ nhớ



1) Viết ra màn hình ngày tháng của BIOS trong bộ nhớ RAM:



PROMPT> DEBUG<enter>

-D FFFF:0006 L 8<enter> (Hiện FFFFh, offset 6h, ðộ dài 8 byte)

In my case, the result reported was "1/10/96."

-Q<enter> (Thoát khỏi debug)



2) Tìm dòng chữ "IBM" trong file nhị command.com trong bộ nhớ RAM:



PROMPT> DEBUG C:\Win95\Command.com<enter>

-S 0 L FFFF "IBM"<enter>(Tìm từ "IBM" từ ðịa chỉ 0 với ðộ dài tìm kiếm FFFFh)

-Q<enter> (Thoát khỏi debug)

(Chú ý: Việc tìm kiếm này là phân biệt hoa thýờng!)



3) Thử phép toán số học cho số cơ số 16:



PROMPT> DEBUG<enter>

-H 9 1<enter> (Thực hiện cộng và trừ hai số dưới dạng cơ số 16, 9h+1h=Ah và 9h-1h=8h)

Kết quả trả về: 000A 0008

-Q<enter> (Thoát khỏi debug)

4) Xem các thanh ghi của x86:



PROMPT> DEBUG<enter>

-R<enter> (Liệt kê các thanh ghi và giá trị của các cờ)

-Q<enter> (Thoát khỏi debug)



Ý nghĩa của các thanh ghi:

AX Thanh ghi tổng

BX Thanh ghi cơ sở

CX Thanh ghi đếm

DX Thanh ghi dữ liệu

DS Thanh ghi đoạn dữ liệu

ES Thanh ghi đoạn bổ sung (Extra)

SS Thanh ghi đoạn công cụ (Battery)

CS Thanh ghi đoạn mã lệnh

BP Thanh ghi con trỏ cơ sở

SI Thanh ghi chỉ mục nguồn

DI Thanh ghi chỉ mục đích

SP Thanh ghi con trỏ công cụ (Battery)

IP Thanh ghi con trỏ của chỉ thị tiếp theo

F Thanh ghi cờ



5) Viết chương trình bằng ngôn ngữ máy In một ký tự:



PROMPT> DEBUG<enter>

-E 100<enter> (Nhập một chương trình mới bắt đầu từ địa chỉ 100h - có cùng giá trị với thanh ghi IP)

B4<space>02<space> (Gán giá trị 02 thanh ghi AH )

B2<space>41<space> (Gán giá trị 41h ( ký tự A) vào thanh ghi DL)

CD<space>21<space> (Gọi ngắt 21 DOS để in ký tự đặt trong DL)

CD<space>20<enter> (Chấm dứt chương trình bằng ngắt 20)

-G<enter> (Thực hiện chương trình in ký tự "A" ra màn hình)

Sau ðó, bạn sẽ thấy "Program terminated normally".

-U 100<enter> (Xem chỉ thị lệnh dýới dạng gợi nhớ)

:0100 B402 MOV AH,02

:0102 B2 MOV DL,41

:0104 CD21 INT 21

:0106 CD20 INT 20)



-R<enter> (Liệt kê giá trị các thanh ghi; IP=100h, AX=0000h, DX=0000h)

-T<enter> (Thực hiện býớc 1: IP=>102h, AX=>0200h,

-T<enter> (Thực hiện býớc 2: IP=>104h, , DX=>00h

-P<enter> (Thực hiện ngắt 21 - chứa nhiều chỉ thị: IP=>106h, AX=>02h)

-P<enter> (Thực hiện ngắt 20 - chứa nhiều chỉ thị)

-Q<enter> (Thoát khỏi debug)

(Chú ý: Hãy cẩn thận với việc chạy từng býớc - Nếu bạn thực hiện nhiều quá, bạn sẽ thực hiện các chỉ thị thuộc vùng nhớ nháp, ðiều này có thể dẫn ðến treo máy)



6) Viết một chýõng trình týõng tự bằng ngôn ngữ assembly của x86:



PROMPT> DEBUG<enter>

-A 100<enter> (Nhập chýõng trình bắt ðầu từ 100h)

MOV AH, 02<enter> (Chọn hàm số 2 của DOS, viết 1 ký tự ra màn hình)

MOV DL, 41<enter> (Đặt giá trị 41 (ký tự A) vào thanh ghi DL)

INT 21<enter> (Thực hiện ngắt 21 của DOS)

INT 20<enter> (Kết thúc chýõng trình bằng ngắt 20 của DOS)

<enter> (Kết thúc việc nhập lệnh)

-G =100<enter> (Thực hiện chýõng trình)

-Q<enter> (Thoát khỏi debug)



7) Viết một chýõng trình và ghi nó xuống ðĩa:

(Chýõng trình sau phức tạp hõn - in chuỗi ABC.)



PROMPT> DEBUG<enter>(Start the debug program; sets the IP default to 100h)

-A 100<enter>

MOV AH,02<enter>

MOV DL,41<enter> (Ðặt giá trị 41 (ký tự A) vào thanh ghi DL)

INT 21<enter>

MOV DL,42<enter> (Đặt giá trị 42 (ký tự B) vào thanh ghi DL)

INT 21<enter>

MOV DL,43<enter> (Ðặt giá trị 43 (ký tự C) vào thanh ghi DL)

INT 21<enter>

INT 20<enter>

<enter>

-R BX<enter> (Xem giá trị thanh ghi BX)

:0000<enter> (Ðặt BX = 0000h, vì ðộ dài ðặt trong BX:CX)

(Khi BX = 0000, kích thýớc của file < 64K)

-R CX<enter> (Ðặt CX = Fh, chỉ ra rằng chýõng trình dài 16 bytes)

:0010<enter> (Bây giờ bạn có thể ghi file dài 16 byte xuống ðĩa)

-N printabc.com<enter>(Ðặt tên của file sẽ ðýợc ghi xuống ðĩa)

-W<enter> (Viết file xuống ðĩa)

-Q<enter> (Thoát khỏi debug)



PROMPT> DIR printabc.com<enter>

Nếu các thao tác trýớc ðúng, bạn sẽ thấy file này có kích thýớc 16 byte



PROMPT> printabc.com<enter>

Xuất hiện dòng chữ "ABC"



8) Tải một chýõng trình vào bộ nhớ:



PROMPT> DEBUG<enter>

-N printabc.com<enter>(Tên của chýõng trình ðýợc tải vào)

-L<enter> (Tải chýõng trình vào bộ nhớ)

-U 100 L 10<enter> (Xem nội dung chýõng trình dýới dạng mã lệnh assembly)

-R<enter> (Xem giá trị các thanh ghi)

-G (Thực hiện chýõng trình)



9) Note you can calculate the program's length using debug's hex-arithmatic:



Vị trí ðầu tiên của chýõng trình printabc bắt ðầu tại 0100h:

107F:0100 MOV AH,02

Và dòng cuối cùng của chýõng trình ở 010Eh:

44107F:010E INT 20

Dòng sau dòng cuối cùng của chýõng trình có ðịa chỉ 0110h:

107F:0110

Do ðó, trừ 110h cho 100h ta ðýợc ðộ dài của file chýõng trình là 10h byte.



PROMPT> DEBUG<enter>

-H 110 100<enter>

0210 0010<enter>

-Q<enter> (Thoát khỏi debug)



10) Can thiệp trực tiếp mã hex vào RAM:

Lưu ý: Khi nhập dữ liệu, gõ ký tự nối (-) sẽ cho phép bạn xóa ký tự trước (backspace)

PROMPT> DEBUG<enter>

-E 200<enter> ( Bắt đầu soạn thảo các giá trị trong RAM (bộ nhớ ) từ vị trí 200)

48<space>65<space> (Đặt giá trị 48h (H) và 65h (e) từ vị trí đó)

6C<space>6C<space> (Đặt giá trị 6Ch (l) và 6Ch (l) tiếp đó)

6F<space>2C<space> (Đặt giá trị 6Fh (o) và 2C (,) tiếp đó)

57<space>6F<space> (Đặt giá trị 57h (W) và 6Fh (o) tiếp đó)

72<space>6C<space> (Đặt giá trị 72h ® và 6Ch (l) tiếp đó)

64<space>24<space> (Đặt giá trị 64h (d) và 24h ($) tiếp đó)

<enter> (Dừng việc nhập giá trị dữ liệu "Hello,World" vào bộ nhớ)

-D 200<enter> (Hiện thị những gì bạn vừa nhập vào RAM của máy,

...48 65 6C 6C 6F 2C 57 6F-72 6C 64 24 ... HELLO,WORLD$...)

-A 100<enter> (Nhập chương trình mã Assembly mới vào địa chỉ 100h, IP là 100h)

MOV AH,09<enter> (Chọn chức năng 09 của DOS, in ra một xâu)

MOV DX,0200<enter> (Đặt vị trí xâu (200h) vào thanh ghi DX)

INT 21<enter> (DOS thực hiện lệnh in xâu, xâu hiện thời là "Hello,World")

INT 20<enter> (Gọi kết thúc chương trình bằng lệnh thoát của DOS)

<enter> (Kết thúc việc nhập mã Assembly đưa vào và trở về Debug)

-G<enter> (Chạy chương trình từ CS:IP, bây giờ là 0B5A:0100h nếu CS là 0B5A)



Bây giờ hãy lưu nội dung chương trình và dữ liệu vào đĩa:

-D 100<enter> (Lưu ý rằng chương trình bắt đầu ở vị trí 100h)

-D 200<enter> (Lưu ý rằng vị trí của ký hiệu $ của dữ liệu là 020Bh)

-H 20B 100<enter> (Lấy giá trị 20Bh-100h=10Bh; độ dài chương trình là 267-byte)

-R BX<enter> (Truy nhập giá trị của thanh ghi BX)

:0000<enter> (Đặt 0000h vào BX vì độ dài chương trình là BX:CX)

-R CX<enter> (Truy nhập giá trị thanh ghi CX, với độ dài chương trình là 010Bh byte)

:010B<enter> (Bây giờ bạn có thể lưu 0000:010Bh byte, tức 267 byte vào 1 file)

-N printhw.com<enter> (Tên của file được lưu vào đĩa)

-W<enter> (Viết 10Bh byte này vào file)

-Q<enter> (Thoát khỏi Debug)



PROMPT> DIR printhw.com<enter>

Kích cỡ của fìle sẽ phải là 267 byte (10Bh byte).



PROMPT> printhw.com<enter>

Chạy chương trình - Nó sẽ in xâu "Hello,World" ra màn hình:



11) Phýõng pháp khác ðể lýu và xuất xâu ký là sử dụng ASCII và các vòng lặp:



PROMPT> DEBUG<enter>

-A 100<enter> (Nạp chýõng trình mã Assembly mới vào vị trí 100h, IP là 100h)

JMP 125<enter> (Nhảy qua dữ liệu tại 102 ðến lệnh 125H)

<enter> (Kết thúc nhập mã Assembly, tiếp ðó nhập xâu ký tự)

-E 102 'Hello World' 0d 0a '$'<enter> (Nhập xâu ký tự vào bộ nhớ tại vị trí 102)

-A 125<enter> (Nạp chýõng trình thực của bạn tại 125h)

MOV DX,0102<enter> (Ðặt vị trí xâu (102h) vào thanh ghi DX)

MOV CX,0005<enter> (Xác ðịnh rằng xâu ðýợc hiển thị 5 lần)

MOV AH,09<enter> (Chọn chức nãng 09 của DOS, in một xâu)

INT 21<enter> (DOS thực hiện in xâu, hiện tại là xâu "Hello, World")

DEC CX<enter> (Giảm số ðýợc hiện thị ði 1)

JCXZ 0134<enter> (Nếu bộ ðếm CX tiến ðến 0 thì nhảy tới vị trí 134)

JMP 012D<enter> (Ngýợc lại nhảy tới lệnh tại vị trí 012D)

INT 20<enter> (Gọi kết thúc chýõng trình bằng lệnh thoát của DOS)

<enter> (Kết thúc nhập mã Assembly và trở lại Debug)

-U 100<enter> (Dịch ngýợc sang mã Assembly từ vị trí 100h)

-U<enter> (Tiếp tục dịch ngýợc mã Assembly cho ðến lệnh cuối cùng)

-H 0136 100<enter> (Lấy giá trị 0136h-100h ðể có ðộ dài chýõng trình là 36h bytes)

-U 100 L 36<enter> (Dịch ngýợc mã Assembly từ 100h ðến 136h)

-R BX<enter> (Truy nhập giá trị của thanh ghi BX)

:0000<enter> (Ðặt 0000h vào thanh ghi BX, vì ðộ dài là BX:CX)

-R CX<enter> (Ðặt 36h vào CX, do ðộ dài chýõng trình là 36h bytes)

:0036<enter> (Bây giờ bạn có thể viết 36h byte này vào một file)

-N printhw5.com<enter> (Tên của file ðýợc viết là printhw5.com)

-W<enter> (Lýu 36h byte này vào file mới ðó trên ðĩa)

-G<enter> (Chạy chýõng trình ðể in xâu Hello-World 5 lần)

-Q<enter> (Thoát khỏi Debug)



PROMPT> DIR printhw5.com<enter>

Kích thýớc của file sẽ phải là 54 bytes (36h bytes).



PROMPT> printhw5.com<enter>

Sẽ in 5 dòng "Hello World" ra màn hình.



12) Khi thực hành, hãy cố gắng kết hợp hai chýõng trình bạn vừa mới tạo ra:



Hãy gắn printhw.com vào printhw5.com, do ðó, thay cho chỉ riêng printhw5 chạy, thực hiện phiên bản ðýợc gắn kết của printhw5 có thể dẫn ðến printhw chạy trýớc rồi ðến printhw5.



PROMPT> COPY printhw5.com printhw5.bak<enter>

Sao lưu bản gốc printhw5.com nhằm để mục đích so sánh.



PROMPT> DIR printhw5.com<enter>

Kích cỡ file của bản gốc sẽ phải là 54 byte (36h byte).



PROMPT> DEBUG printhw5.com<enter>

-R<enter> (Thông báo kích cỡ file là BX:CX=0000 0036h byte)

-U 100<enter> (Cho biết lệnh đầu tiên là EB 23 (JMP 0125))

-H 100 36<enter> (Cho biết lệnh cuối là tại 100h+36h=136h)

-H 136 1<enter> (Cho biết vị trí RAM sẵn có tiếp theo là 136h+1h=137h)

Bây giờ bạn có đủ thông tin để gắn vào một chương trình.



-E 110<enter> (Thêm các giá trị bạn muốn tại bất kỳ vị trí nào)

48<space>65<space> (Đặt giá trị 48h (H) và 65h (e) từ vị trí đó)

6C<space>6C<space> (Đặt giá trị 6Ch (l) và 6Ch (l) tiếp đó)

6F<space>2C<space> (Đặt giá trị 6Fh (o) và 2C (,) tiếp đó)

57<space>6F<space> (Đặt giá trị 57h (W) và 6Fh (o) tiếp đó)

72<space>6C<space> (Đặt giá trị 72h ® và 6Ch (l) tiếp đó)

64<space>24<space> (Đặt giá trị 64h (d) và 24h ($) tiếp đó)

<enter> (Dừng việc nhập giá trị dữ liệu "Hello,World" vào bộ nhớ)

-D 110<enter> (Hiện thị những gì bạn vừa nhập vào RAM của máy,…,

48 65 6C 6C 6F 2C 57 6F-72 6C 64 24 ... HELLO,WORLD$...)



-A 100<enter> (Sửa điều khiển chương trình gốc tại vị trí IP bắt đầu)

JMP 137<enter> (Thay cho chạy chương trình gốc-- Chạy phần gắn thêm của bạn)

<enter> (Kết thúc nhập mã Assembly để quay lại Debug)



-A 137<enter> (Nhập mã Assemble cho phần gắn vào tại vị trí sẵn có tiếp theo)

MOV AH,09<enter> (Chọn chức năng 09 của DOS, in ra một xâu)

MOV DX,110<enter> (Đặt vị trí của xâu (110h) vào thanh ghi DX)

INT 21<enter> (DOS thực hiện in, xâu hiện thời là "Hello,World")

JMP 0125<enter> (Thay cho lệnh thoát (INT 20), trả điều khiển cho printhw5)

<enter> (Kết thúc nhập mã Assembly, quay lại Debug)





-U 125<enter> (Lưu ý chúng ta vẫn chưa sửa đổi chương trình gốc...)

-U 100 L 1<enter> (Ngoại trừ việc gắn điểm bắt đầu của chúng ta là 137h…)

-D 110 L C<enter> (Và chia (không thay đổi kích cỡ) dữ liệu mới tại 110h)

-U 137<enter> (Và chúng ta gắn vào (thay đổi kích thước) các lệnh mới tại 137h)



Bây giờ, hãy lưu chương trình đã được gắn vào lên đĩa:

(Lưu ý rằng địa chỉ đầu tiên sau lệnh "JMP 0125" là tại 0140h)

-H 0140h 100<enter> (Lấy giá trị 140h-100h=40h,…; độ dài mới gồm 64-byte)

-RBX<enter> (Truy nhập giá trị thanh ghi BX)

:<enter> (Giữ BX là 0000 vì segment không thay đổi)

-RCX<enter> (Đặt 40h vào CX là độ dài của chương trình mới ; 64 byte)

:40<enter> (Bây giờ chúng ta có thể viết 0000:0040h byte này lên đĩa)

-W<enter> (Ghi đè file gốc bằng file đã được gắn thêm)

-G<enter> (Kiểm tra chương trình mới đã được gắn thêm)

-Q<enter> (Thoát khỏi Debug)









PROMPT> DIR printhw5.com<enter>

Bây giờ hiện ra kích thước mới, không phải 54 byte, mà là 64 byte.



PROMPT> printhw5.com<enter>

Bây giờ trước hết là in xâu "Hello,World" ra màn hình sau đó in xâu "Hello,World" 5 lần.



PROMPT> DIR printhw5.com<enter>

Hiển thị kích thước mới của file không phải là 54 byte nữa mà là 64 byte.

PROMPT> printhw5.com<enter>

In "Hello,World" ra màn hình trước khi in "Hello,World" 5 lần nữa.



13) Hãy theo dõi sự thực hiện của chýõng trình bằng lệnh T (theo vết):



PROMPT> DEBUG printhw5.com<enter>

-R<enter> (Traces býớc 0: Ðịa chỉ 0100h chứa giá trị EB35, ðó là mã của lệnh "JMP 0137")

-T<enter> (Traces býớc 1: Ðịa chỉ 0137h chứa giá trị B409, ðó là mã của lệnh "MOV AH,09")

-T<enter> (Traces býớc 2: Ðịa chỉ 0139h chứa giá trị BA1001, ðó là mã của lệnh "MOV DX,0110")

-T<enter> (Traces býớc 3: Ðịa chỉ 013Ch chứa giá trị CD21, ðó là mã của lệnh "INT 21")

-P<enter> (Process býớc 4: in ra chuỗi "Hello,World")

Ðịa chỉ 013Eh chứa giá trị EBE5, là mã của lệnh "JMP 0125"



-T<enter> (Tại ðây, ðiều khiển ðýợc trả về chýõng trình gốc.)



Nhớ rằng khi muốn thực hiện lệnh "T" thực hiện từng býớc chýõng trình của mình, nhớ là bạn chỉ thực hiện lệnh "T" cho ðến khi gặp một lệnh gọi ngắt (INT). Ðến khi gặp lệnh gọi ngắt, bạn cần thực hiện lệnh "P" ðể ði qua cả tiến trình. Sau ðó bạn lại thực hiện lệnh "T" nhý bình thýờng.



14) Bạn vẫn có thể chuyển ðiều khiển thậm chí nếu sự thay thế không phải là týõng ứng 1-1:



Ví dụ, bạn muốn chèn vào chýõng trình printw một ðoạn printabc. Nghĩa là ðầu tiên printabc giữ ðiều khiển, sau ðó nó sẽ chuyển ðiều khiển cho printhw. Trong trýờng hợp này, printhw bắt ðầu tại ðịa chỉ 100h với 2 byte chỉ lệnh, sẽ không ðõn giản nhý cách thay thế týõng ứng 1-1 bằng cách JMP chỉ lệnh trýớc khi thực hiện. Giải pháp ở ðây là sử dụng lệnh NOPs ðể bổ sung cho những lệnh ðã bị sửa ðổi cho tới khi có thể thực hiện ðýợc lệnh nhảy (JMP)



PROMPT> DIR printhw.com<enter>

Cho ra thông báo kích thýớc file là 267 byte (10Bh byte)



PROMPT> DEBUG printhw.com<enter>



-R<enter> (chú ý thanh ghi IP=100h và kích thýớc của printhw = BX:CX=0000:010Bh)

-U 100<enter> (Lệnh ðầu tiên có mã B4 09 (MOV AH,09) có kích thýớc 2 byte)

(Và lệnh thứ 2 có kích thýớc 3 byte BA 00 02 (MOV DX,0200))

-H 100 10B<enter> (Con trỏ sau khi kết thúc printhw sẽ nằm tại ðịa chỉ 100h+10Bh=20Bh)

(Chỉ lệnh INT 21 bắt ðầu tại ðịa chỉ 105h)



Bây giờ chúng ta ðã có ðầy ðủ thông tin ðể chèn vào chýõng trình:

-A 100<enter> (Bắt ðầu soạn chýõng trình tại ðịa chỉ mà thanh ghi IP trỏ ðến)

JMP 20B<enter> (Nhảy tới vị trí kết thúc các lệnh cần thiết của chýõng trình printhw)

NOP<enter> (Lấp vào chỗ trống cho ðến khi có lệnh tiếp theo)

NOP<enter> (Thêm vào nhý là một lệnh có kích thýớc 1 byte khi mà bạn muốn xoá những lệnh trýớc)

<enter> (Kết thúc soạn lệnh Assemble và trả ðiều khiển về cho debug)

-U 100<enter> (Xem lại ðoạn lệnh mà bạn vừa nhập vào vùng nhớ bắt ðầu từ ðịa chỉ 100)

(Chỉ lệnh ngắt INT 21 vẫn sẽ bắt ðầu tại ðịa chỉ 105h)

-A 20B<enter> (Bây giờ hãy thêm chýõng trình cũ của bạn vào ðoạn cuối)

MOV AH,02<enter> (Gọi dịch vụ 2 của ngắt 21, in ký tự)

MOV DL,<enter> (Gán giá trị 41h (A) cho thanh ghi DL )

INT 21<enter> (Gọi ngắt của DOS để in ký tự, đó là chữ "A")

MOV DL,42<enter> (Gán giá trị 41h (B) cho thanh ghi DL )

INT 21<enter> (Gọi ngắt của DOS để in ký tự, đó là chữ "B")

MOV DL,43<enter> (Gán giá trị 42h © cho thanh ghi DL)

INT 21<enter> (Gọi ngắt của DOS ðể in ký tự, đó là chữ "C")

MOV AH,09<enter> (Bây giờ hãy ðặt ðoạn lệnh trên vào vùng nhớ bắt ðầu từ ðịa chỉ 100h)

MOV DX,0200<enter>

JMP 105<enter> (Nhảy tới ðịa chỉ 105h ðể gọi chỉ thị ngắt 21)

<enter> (Con trỏ sẽ nằm tại ðịa chỉ cuối cùng sau khi gọi ngắt 21)

-H 221 100<enter> (Ðýa ra thông báo 221h-100h=121h; ví dụ: chýõng trình có kích thýớc 289-byte)

-R CX<enter> (Ðặt CX bằng 121h, là kích thýớc của chýõng trình mới)

:0121<enter> (Bây giờ hãy ghi ðè lên chýõng trình cũ xxx bytes bằng 289 byte này)

-W<enter> (Ghi 289 byte này vào file nguồn)

-Q<enter> (Thoát khỏi Debug)



PROMPT> DIR printhw.com<enter>

Cho ra thông báo kích thýớc mới của file không còn là 267 byte nữa mà là 289 byte.

Và sẽ in ra 3 ký tự ABC trýớc khi in ra chữ "Hello, World".



15) Xem cách tổ chức của một ðĩa mềm (ðýờng kính 3 ½ và dung lýợng 1.44 MB):

Thật ðõn giản, chúng ta chỉ việc phân tích ðĩa mềm MSDOS 1.44 Mbyte 3.1/2.



Chúng ta ðã biết ðĩa mềm 3 1/2" DSHD 1.44Mbyte gồm:



- 2 mặt x 80 rãnh(track)x 18cung (sectors)x 512 bytes = 1.44Mbytes

- Trên mỗi mặt của ðĩa từ:

o Có các "Boot" sectors

o Sau ðó là bảng FAT (File Allocation Table)

o Rồi ðến bảng thý mục ("Directory")

o Và cuối cùng là vùng lýu trữ dữ liệu ("Data")



- Trýớc khi chúng ta khôi phục lại (un-erasing) các file bị xoá, hãy xem cấu trúc của các file MSDOS:

a) Gồm 32 byte ðầu vào

b) Cộng thêm một khoảng trắng(một clusters)

c) Sau ðó là dữ liệu thật của file



Từng býớc một, ta sẽ nghiên cứu chi tiết các vùng dữ liệu trên ðĩa mềm.



16) Phân tích chi tiết từng bit trên boot sector của một ðĩa mềm 1.44Mbyte:



Chú ý là tất cả các sector ðầu tiên của ðĩa từ MSDOS luôn là boot record

Nó thýờng gồm:

- Một lệnh nhảy tới mã khởi động

- Tên của version OEM

- Khối tham số của BIOS

- Thông tin định dạng

- Mã khởi động và thông tin về các partition



Tạo một DSHD 3 1/2" 1.44Mbyte disk

PROMPT> FORMAT A:<enter>

Chú ý: Một word có giá trị 34 12 là 1234h

1234h = 1x4096d + 2x256d + 3x16d + 4x1d = 4096 + 512 + 16 + 4 = 4660d



PROMPT> debug<enter>

-L 0 0 0 1<enter> (Tải tới địa chỉ 0 của RAM , đĩa thứ 0 {A},từ sector 0 {0 to 1})

-U 00 L 3<enter> (Dịch sang assemble 3-byte jump past 27bytes of disk-format info)

Kết quả: JMP 0040 ;Nhảy tới đoạn mã tại địa chỉ 40h NOP ;Chỉ có DOS 2.x sử dụng byte này

-D 03 L 8<enter> (Hiện 8-byte chứa tên OEM và thông tin version)

Kết quả: "(MC;ZIHC" for an IBM Thinkpad 760C



-D 0B L 2<enter> (Số lượng word trên một sector)

Kết quả:00 02

(0200h = 2x256=512 bytes trên một sector)

-D 0D L 1<enter> (Hiện số lượng sector trên một cluster)

Kết quả:01

(01h = 1 sector trên một cluster)

Hỏi: có thực hiện lệnh này nếu có 2 sector trên một cluster không?

-D 0E L 2<enter> (Hiện sector dành riêng)

Kết quả:01 00

(0001h = 1 sector dành riêng)

Hỏi: Hmmm...Sector dành riêng là gì?

-D 10 L 1<enter> (Đưa ra 1 byte chỉ số lượng các bảng FAT)

Kết quả: 02

-D 11 L 2<enter> (Đưa ra 1 word chỉ số lượng các phần tử thư mục gốc)

Kết quả: E0 00

Tính toán: 00 E0h = 15*16 = 240 phần tử thư mục

-D 13 L 2<enter> (Đưa ra 1 word chỉ số lượng các sector logic)

Kết quả: 40 0B

Tính toán: 0B 40h = 11*256 + 4*16 = 2280 sector logic

-D 15 L 1<enter> (Đưa ra 1 byte mô tả Media; chỉ đúng trước DOS 2.00)

Kết quả: F0

-D 16 L 2<enter> (Đưa ra 1 word chỉ số lượng sector của FAT)

Kết quả: 09 00h

Tính toán: 0009 = 9 FAT sector

-D 18 L 2<enter> (Đưa ra 1 word chỉ số lượng sector trên 1 track)

Kết quả: 12 00h

Tính toán: 0012 = 1*16 + 2*1 =18 sector trên 1 track

Đây là phần tử cuối cùng trong BIOS PARAMETER BLOCK

-D 1A L 2<enter> (Đưa ra 1 word chỉ số lượng các đầu)

Kết quả: 02 00

Tính toán: 0002h =2 đầu

-D 1C L 2<enter> (Đưa ra 1 word chỉ số lượng các sector ẩn)

Kết quả: 00 00 sector ẩn

Câu hỏi: Tôi không biết mục đích của sector ẩn

-U 1E L 01A0<enter> (đưa ra mã Assembly của mã khởi động - 416 byte)

Kết quả: Mã khởi động

-D 1BE L 10<enter> (16 byte của thông tin phân vùng trên bất kỳ đĩa cứng nào)

Kết quả: Thông tin phân vùng không đặt trên các đĩa mềm

-U 1CE L 32<enter> (đưa ra mã Assembly của 50 byte cuối của mã khởi động)

Kết quả: Mã khởi động

Phần trên dành cho bản ghi gốc (boot record)

-D 200 (chú ý FAT bắt đầu từ đây, phụ thuộc vào các sector được lạp)

-Q<enter> (Thoát khỏi debug)



17. Phân tích chi tiết các bit của sector chứa bảng FAT của một đĩa bằng debug

Trước hết tạo thử 1 file trong ổ A tên là FILE1.TXT chứa nội dung là ABC từ dấu nhắc

PROMPT> ECHO ABC > A:\FILE1.TXT<enter>

Sau đó chạy chương trình DEBUG từ dấu nhắc

PROMPT> DEBUG<enter>

-L 0 0 1 2<enter> (Nạp vào địa chỉ 0 của RAM , đĩa 0 {A}, sector logic 1 {1to2})

-D 0 L 2<enter> (Phần tử 0 của FAT chỉ định dạng của đĩa)

Kết quả: F0 FF. Nhưng các đĩa mềm chỉ sử dụng 12 bit = F0 F

Đảo ngược cho kết quả: F F0

F F0 chỉ định dạng của đĩa mềm 3 1/2" 1.44Mbyte

-D 1 L 2<enter> (phần tử 1 của FAT luôn được thiết lập là FFF )

Kết quả là FF FF. Nhưng các đĩa mềm chỉ sử dụng 12 bit = FF F

F FF là giữa phần tử 0 và 2 của bảng FAT

Lưu ý: Do phần đầu tiên của file nằm trong cluster 2 nên số hiệu cluster đầu tiên của điểm vào thư mục cho FILE1 chỉ phần tử 2 của bảng FAT (do MSDOS đặt tên các cluster tương tự các phần tử của bảng FAT và 2 phần tử đầu tiên của FAT đã được sử dụng như đã nói ở trên)

-D 3 L 2<enter> (Phần tử 2 của FAT chỉ phần tiếp theo của file1)

Kết quả : FF 0F, nhưng các đĩa mềm chỉ sử dụng 12 bit = FF 0

Đảo ngược: 0 FF

Phần tử tiếp theo của file1 chỉ tới phần tử/cluster 0 FF



Phân tích các sector Thư mục của một đĩa MSDOS

Khi bạn gõ lệnh DIR trong thư mục gốc, thông tin sẽ được lấy ra từ các sector Thư mục. Mỗi điểm vào thư mục của file có độ dài 32 byte

PROMPT> FORMAT A:<enter>

PROMPT> ECHO ABC > A:\FILE1.TXT

Xem chúng ta có gì trong đĩa 1

PROMPT> DIR A:<enter>

PROMPT> TYPE A:\FILE1.TXT<enter>

Quan sát 32 byte của điểm vào thư mục ta thấy

Byte 0: ký tự thứ nhất của tên file = 46 -> Mã ASCII F

Byte 1: ký tự thứ hai của tên file = 49 -> Mã ASCII I

Byte 2: ký tự thứ ba của tên file = 4C -> Mã ASCII L

Byte 3: ký tự thứ tư của tên file = 45 -> Mã ASCII E

Byte 4: ký tự thứ năm của tên file = 31 -> Mã ASCII 1

Byte 5: ký tự thứ sáu của tên file = 20 -> không được sử dụng ở đây

Byte 6: ký tự thứ bảy của tên file = 20 -> không được sử dụng ở đây



Byte 7: ký tự thứ tám của tên file = 20 -> không được sử dụng ở đây

Byte 8: ký tự thứ nhất của phần mở rộng =54 -> Mã ASCII T

Byte 9: ký tự thứ hai của phần mở rộng =58 -> Mã ASCII X

Byte 10: ký tự thứ ba của phần mở rộng =54 -> Mã ASCII T

Byte 11: byte chỉ thuộc tính của file (xem bảng) = 20 -> bít lưu (archive bit)

Byte 12-15: cho MSDOS 00 B7 77 17 = để giành bởi MSDOS

Byte 16-21: cho MSDOS 8D 23 8D 23 00 00 = để giành bởi MSDOS

Byte 22-23: Giờ tạo lập = 78 17

Dạng của giờ tạo lập là: hhhhh mmmmmm sssss

1778h = 00010 111011 11000 = 2:59:48

Byte 24-25: Ngày tạo lập = 8D 23

Dạng của ngày tạo lập là yyyyyyy mmmm ddddd

23 8D = 0010001 1100 01101 = 17/12/13 (thực tế là 97/12/13, tính tương đối so với năm 1980)

Byte 26-27: Số hiệu cluster đầu tiên = 02 00 -> cluster 2

Byte 28-31 Kích thước file (tính bằng byte) = 06 00 00 -> 6 byte (ABC)

1 nhận xét:

Nặc danh nói...

bài viết hay và bổ ích cho tôi, thank

Đăng nhận xét

 
Design by Free WordPress Themes | Bloggerized by Lasantha - Premium Blogger Themes | Blogger Templates