Chương 3Nhập môn ASM Khoat Nguyen Ngôn ngữ Assembly { Chương trình Assembly được dịch ra mã máy bằng một trình biên dịch, vì thế chúng cần được viết sao cho phù hợp với các khuôn mẫu của
Trang 1Chương 3
Nhập môn ASM
Khoat Nguyen
Ngôn ngữ Assembly
{ Chương trình Assembly được dịch ra mã máy bằng
một trình biên dịch, vì thế chúng cần được viết sao
cho phù hợp với các khuôn mẫu của trình biên dịch
Trong chương này chúng ta sẽ sử dụng trình biên
dịch của Microsoft Marco Assembler(MASM)
{ Mã lệnh Assembly không phân biệt chữ hoa hay chữ
thường như trong ngôn ngữ C(C++)
{ Các dòng lệnh: Cũng giống như các ngôn ngữ lập
trình bậc cao khác, chương trình bao gồm các dòng
lệnh, tuy nhiên ở ngôn ngữ này mỗi dòng lệnh chỉ
được viết trên một dòng Một dòng lệnh là một lệnh
mà trình biên dịch sẽ dịch ra mã máy, hay là một
hướng dẫn biên dịch để trình biên dịch thực hiện
một số thao tác đặc biệt nào đó Mỗi lệnh trong
Trang 2{ Các trường phải được phân cách nhau bằng ít nhất
một ký tự trống hay TAB
tự
{ Trong Vd trên, trường tên là nhãn DCH, toán tử là
MOV, toán hạng là AH và 2, chú thích là “Hàm hiển
thị ký tự” MAIN là tên, và toán hạng là PROC Dẫn
hướng biên dịch này khai báo một chương trình con
có tên là PROC
{ Trường tên
z Trường tên được sử dụng làm nhãn lệnh,
tên các hàm, thủ tục, và tên các
biến.Trình biên dịch sẽ chuyển các tên
này thành các địa chỉ trong bộ nhớ
z Các tên có chiều dài 1÷ 31 ký tự bao
gồm cả chữ số, chữ cái và các ký tự đặc
biệt (Các tên không được bắt đầu bằng
một chữ số).
Trang 3{ Trường toán tử
z Chứa mã lệnh dạng tượng trưng (symbolic) Trình
biên dịch sẽ chuyển mã lệnh tượng trưng sang
mã lệnh của ngôn ngữ máy
{ Trường toán hạng
z Trường toán hạng xác định dữ liệu sẽ được các
thao tác động đến đối với lệnh có một toán hạng,
đối với lệnh hai toán hạng, toán hạng đầu tiên là
một thanh ghi hoặc một ô nhớ, đây có thể là nơi
lưu trữ dữ liệu, toán hạng thứ hai là toán hạng
nguồn, toán hạng này không bị thay đổi nội
dung
{ Trường chú thích
z được sử dụng để giải thích xem tại dòng
lệnh đó người viết chương trình định làm
gì Mở đầu trường phải là một dấu “;”, khi
đó trình biên dịch sẽ bỏ qua mọi thứ được
viết đằng sau dấu “;”.
Trang 4Dữ liệu
{ Bộ VXL làm việc với dữ liệu nhị phân, vì thế trình biên dịch
sẽ chuyển tất cả các dạng dữ liệu khác nhau thành dữ liệu
nhị phân
{ Các cách biểu diễn số liệu trong MASM:
z Một số nhị phân biểu diễn bằng chuỗi các bit kết thúc
bằng chữ cái “b” (01010b)
z Một số thập phân biểu diễn bằng chuỗi các chữ số thập
phân kết thúc bằng chữ cái “d”
z Một số hexa biểu diễn luôn bắt đầu bằng một chữ số
thập phân và kết thúc bằng chữ cái “h”
z Các ký tự và chuỗi được biểu diễn trong dấu nháy đơn ‘ ‘
hoặc nháy kép “”
{ Một số toán tử giả định nghĩa các kiểu số liệu:
Định nghĩa 10 byte DT
Định nghĩa 4 word DQ
Định nghĩa từ kép DD
Định nghĩa word DW
Định nghĩa byte DB
Biểu diễn kiểu số liệu Toán tử
Trang 5Các biến
{ Các biến trong ngôn ngữ Assembly có
vai trò giống như các biến sử dụng
trong các ngôn ngữ lập trình bậc cao
khác (C,C++, Pascal…)
{ Mỗi biến có một kiểu dữ liệu, và được
gán một địa chỉ trong bộ nhớ
{ Các biến kiểu byte
z Khai báo có dạng:
Tên DB giá trị khởi tạo
Vd:
Count_1 DB 10 ; Sẽ báo cho trình
biên dịch gán cho tên Count_1 một ô nhớ có
độ dài là 1 byte, với giá trị thiết lập ban đầu
là 10
Nếu không muốn thiết lập giá trị ban đầu thì
ta có thể khai báo:
Trang 6{ Các biến kiểu word
Khai báo có dạng:
Tên DW giá trị khởi tạo
Vd: Count_2 DW 10 ; Sẽ báo
cho trình biên dịch gán cho tên
Count_2 một ô nhớ có độ dài là 1 word
, với giá trị thiết lập ban đầu là 10
Nếu không muốn thiết lập giá trị ban
đầu thì ta có thể khai báo:
Count_2 DW ?
{ Mảng
z Là một chuỗi các byte, hay word nhớ
Khai báo có dạng:
Tên DB arr1, arr2,… , arrn
Vd:
String_b DB 12h, 13h, 14h ; Sẽ báo cho trình
biên dịch gán cho tên String_b byte nhớ đầu tiên,
String_b+1 byte nhớ thứ hai, String_b+2 byte nhớ
thứ ba
Khai báo có dạng:
Tên DW arr1, arr2,…… arrn
Vd: String_ w DW 12Ah, 13Bh, 14Ch ; Sẽ
báo cho trình biên dịch gán cho tên String_ w word
nhớ đầu tiên, String_ w+2 word nhớ thứ hai, String_
w+4 word nhớ thứ ba
Trang 7{ Phần tử Địa chỉ Nôi dung
String_b+1 113h 13h
String_b+2 114h 14h
String_w+2 114h 13Bh
String_w+4 116h 14Ch
{ Khai báo hằng
z Khai báo có dạng:
EQUATES
Vd:First equ 0Dh ; Gán tên First
cho 0Dh, là mã Ascii của ký tự trở về đầu
dòng, và tên First sẽ được sử dụng trong
chương trình
MOV DL, First.
Trang 8Cấu trúc chương trình
{ Các chương trình bằng ngôn ngữ máy gồm
có mã , dữ liệu, và ngăn xếp Mỗi phần này
chiếm một đoạn bộ nhớ, đây cũng chính là
tổ chức chương trình của ngôn ngữ
Assembly Mã,dữ liệu, và ngăn xếp được
cấu trúc như các đoạn chương trình Mỗi
đoạn chương trình sẽ được dịch thành một
đoạn bộ nhớ bởi trình biên dịch
{ Các chế độ bộ nhớ
z Kích thước của mã và dữ liệu trong một
chương trình được xác định bằng cách
chỉ ra chế độ bộ nhớ nhờ sử dụng cú
pháp:
{.MODEL kiểu bộ nhớ
z Các kiểu bộ nhớ thường dùng:
Trang 9Mã lệnh chiếm nhiều hơn một đoạn, dữ liệu chiếm
nhiều hơn một đoạn
Các mảng có thể >64K
HUGE
Mã lệnh chiếm nhiều hơn một đoạn, dữ liệu chiếm
nhiều hơn một đoạn
Các mảng <64K
LARGE
Mã lệnh trong một đoạn, dữ liệu chiếm nhiều hơn
một đoạn
COMPACT
Mã lệnh chiếm nhiều hơn một đoạn, dữ liệu trong
một đoạn
MEDIUM
Mã lệnh trong một đoạn, dữ liệu trong một đoạn
SMALL
Mô tả Kiểu
{Các chế độ bộ nhớ thường được sử dụng
là: SMALL, MEDIUM, COMPACT, và
LARGE Trừ khi có nhiều mã lệnh hay số
liệu, thì kiểu thích hợp nhất là SMALL.
{Chú ý: MODEL phải được khai báo vào
trước bất kỳ một định nghĩa đoạn nào.
Trang 10Đoạn dữ liệu
{ Đoạn dữ liệu của một chương trình chứa
các định nghĩa biến, hằng.
Cú pháp: DATA
MSG DB ‘This is a Message’
{ Đoạn ngăn xếp
z Dùng để tạo một khối bộ nhớ để chứa ngăn xếp
z Cú pháp: STACK kích thước
z Kích thước: một số tuỳ ý xác định vùng kích
thước ngăn xếp được tính theo byte.Chú ý: Trình
biên dịch mặc định kích thước nếu không khai
báo là: 1Kb
z Vd:
.STACK 100h ;Tạo ra 100h byte vùng ngăn xếp
Trang 11{ Đoạn mã
z Chứa các lệnh của chương trình
z Tên: Đây là một tên đoạn, có thể có hoặc không
z Bên trong một đoạn mã, các lệnh được tổ chức
các thủ tục: Khai báo một thủ tục trong ngôn ngữ
Assembly là:
z Tên_thủ_tục PROC
{; thân thủ tục
z Tên_thủ_tục ENDP
; Các lệnh của chương trình
;Các thủ tục khác
Trang 12{ Khuôn mẫu chương trình
.DATA
; Các định nghĩa có các biến
.CODE
MAIN PROC
;Các lệnh người dùng
; Các thủ tục khác
{ Kết thúc một chương trình chính luôn luôn phải có
END
Xây dựng chương trình
{ Tìm hiểu một số lệnh vào ra
z Lệnh INT: Lệnh này đựơc dùng để gọi các hàm
của DOS và BIOS
{ Cú pháp: INT Số_hiệu_ngắt ;Số hiệu
ngắt xác định hàm mà DOS, BIOS cung cấp,
trong phần này chúng ta sẽ xem qua ngắt 21
của DOS
{ Ngắt 21: được dùng để gọi rất nhiều hàm của
DOS, mỗi hàm được gọi bằng cách đặt số hàm
vào trong thanh ghi AH, ở đây ta sử dụng các
hàm có số hiệu: 1, 2, 9.Trong đó hàm có số
hiệu 1 là hàm vào một ký tự từ bàn phím, số
hiệu 2 là hàm đưa một ký tự ra màn hình, và
số hiệu 9 là hàm đưa một chuỗi ký tự ra màn
hình
Trang 13AH=9 DX: địa chỉ tương đối của chuỗi
Kết thúc chuỗi bằng
‘$’.
AL= Mã Ascii của
ký tự hiển thị hay ký
tự điều khiển
AH=2 DL=Mã Ascii của
ký tự hiển thị hay ký
tự điều khiển
AL=0:
phím
điều
khiển
=1;Mã
Ascii
AH=1
Ra Vào
Ra Vào
Ra
Vào
Hàm 9 Hàm 2
Hàm 1
z Khi kết thúc một chương trình cần trả lại quyền
điều khiển cho DOS, chúng ta thực hiện điều này
bằng cách gọi hàm 4Ch của ngắt 21.
z Chương trình
{ Xây dựng một chương trình để đọc một ký tự
từ bàn phím và hiển thị
Trang 14.MODEL SMALL
.STACK 100h
.CODE
MAIN PROC
;Hiển thị dấu ‘?’
MOV AH, 2
;Hàm hiển thị ký tự
MOV DL, ’?’
;Ký tự hiển thị ‘?’
INT 21h
;Hiển thị ký tự
; Đọc một ký tự từ bàn phím
MOV AH,1 ;Hàm đọc một
ký tự
INT 21h
MOV BL, AL
;Cất ký tự vào trong BL
;Xuống dòng MOV AH, 2 MOV DL, 0Dh ;Ký tự điều khiển
INT 21h MOV DL, 0Ah ;Ký tự điều khiển
INT 21h
;Hiển thị ký tự MOV AX,BL INT 21h
;Trả quyền điều khiển về DOS
MOV AX, 4C00h INT 21h
MAIN ENDP END MAIN
{ Biên dịch và chạy chương trình
z Sau khi dùng một chương trình soạn thảo văn bẳn tạo ra
một tệp (File) chương trình nguồn với tên là *.asm
(Phần mở rộng luôn phải là asm, đây là quy ước của
trình biên dịch Assembly), với ví dụ ở trên giả sử sau
soạn thảo ta đặt tên là Prog_in.asm.
z Sử dụng trình biên dịch MASM để dịch tệp nguồn
Prog_in asm sang tệp ngôn ngữ máy Prog_in.obj Cú
pháp biên dịch là: C:\ MASM Prog_in asm; ↵, dấu ‘;’
theo sau câu lệnh có nghĩa là ta chỉ muốn trình biên dịch
tạo ra một tệp biên dịch duy nhất Nếu không có dấu ‘;’,
trình biên dịch sẽ tạo ra thêm tệp có tên là *.lst, và tệp
*.crf MASM sẽ kiểm tra lỗi cú pháp của tệp *.asm, nếu
tìm thấy lỗi nó sẽ hiển thị dòng của lệnh hay cú pháp
gây lỗi và nguyên nhân gây lỗi, nếu không thấy lỗi nào,
MASM sẽ dịch mã ngôn ngữ Assembly thành tệp đối
tượng ngôn ngữ máy với tên *.obj mà cụ thể ở đây là
Prog_in.obj
Trang 15z Sau khi có tệp Prog_in.obj ta cần dịch
chúng ra tệp Prog_in.exe để thực hiện
chương trình Cú pháp: C:\Link
Prog_in.obj;↵
z Sau đó chạy tệp *.exe vừa dịch, cụ thể ở
đây là: C:\Prog_in.exe
Soạn thảo Tệp *.asm Trình biên dịch
Tệp *.obj Trình liên kết
Trang 16Ví dụ
{ Hiển thị chuỗi ký tự “Chao mưng ban den voi ngon
ngu Assembly” Trong chương trình này ta sẽ sử
dụng hàm 9 của ngắt 21
{ Hàm 9 của ngắt 21: Hàm này yêu cầu địa chỉ tương
đối của chuỗi ký tự chứa trong DX
{ Sử dụng lệnh LEA(Load Effective Adress, nạp địa chỉ
thực)
z Cú pháp : LEA dest, source
z dest:là một thanh ghi công dụng chung
z source là một ô nhớ
z lệnh thực hiện copy địa chỉ tương đối của source(nguồn)
sang dest(đích)
z tại sao ta lại phải sử dụng câu lệnh này?
Do ở ví dụ này chúng ta sử dụng đoạn dữ liệu là chuỗi ký
tự mà khi một chương trình được nạp vào bộ nhớ, DOS sẽ
dành 256 byte đoạn mở đầu chương trình (Program
Segment Prefix, PSP), PSP chứa các thông tin về chương
trình vì thế chương trình có thể truy nhập vùng nhớ này
DOS sẽ đưa địa chỉ của PSP vào trong DS lẫn ES trước khi
chạy chương trình do đó DS sẽ không chứa địa chỉ đoạn
dữ liệu mà ta viết trong chương trình ví dụ.
Trang 17.MODEL SMALL
.DATA
Assembly”
.CODE
;Khỏi tạo DS
MOV AX, @DATA ;Tên của đoạn dữ liệu được định nghĩa
; bởi DATA, trình biên dịch sẽ dịch @DATA
; thành địa chỉ MOV DS, AX
;Hiển thị thông báo
INT 21h
;Trở về DOS
MOV AH, 4Ch
INT 21h
END MAIN
Bài tập
{ Viết chương trình thực hiện các công việc sau:
z Hiển thị ký tự “!”
z Đọc hai chứ số thập phân có tổng nhỏ hơn 10
z Hiển thị các số đó và thông báo tổng của hai số đó
{ Viết chương trình thực hiện các công việc sau:
z Hiển thị thông báo nhập số liệu
z Nhập vào 3 chữ cái đầu tương ứng với :Họ, Tên đệm,
Tên
z Hiển thị lên màn hình
{ Viết một chương trình đọc một chữ số Hex rồi hiển thị
chúng dưới dạng nhị phân