Upload
nguyen-viet-dung
View
495
Download
3
Embed Size (px)
Citation preview
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
chương 3 LẬP TRÌNH ASSEMBLY................................................................................- 20 -i - khung chương trình assembly....................................................................................- 20 -
1. Bộ ký tự của Assembly..........................................................................................- 20 -2. Từ khóa..................................................................................................................- 20 -3. Tên tự đặt...............................................................................................................- 20 -4. Cấu trúc một lệnh Assembly..................................................................................- 20 -5. Các dạng hằng dùng trong Assembly....................................................................- 21 -6. Khai báo biến và hằng............................................................................................- 21 -7. Một số lệnh cơ bản...............................................................................................- 23 -8. Các lệnh vào ra.....................................................................................................- 24 -9. Khung của một chương trình Assembly................................................................- 25 -
ii – BIÊN SOẠN VÀ DỊCH CHƯƠNG TRÌNH ASSEMBLY.....................................- 29 -iii - THỰC HIỆN CÁC CẤU TRÚC ĐIỀU KHIỂN CHƯƠNG TRÌNH BẰNG
ASSEMBLY.......................................................................................................................- 31 -A. Lệnh JMP.............................................................................................................- 31 -B. Các lệnh nhảy có điều kiện.................................................................................- 31 -C. Lệnh so sánh..........................................................................................................- 33 -D. Các cấu trúc ngôn ngữ bậc cao..........................................................................- 33 -1. Cấu trúc rẽ nhánh IF-THEN..................................................................................- 33 -2. Cấu trúc lựa chọn CASE........................................................................................- 34 -3. Cấu trúc lặp với số lần xác định FOR-DO.............................................................- 35 -4. Cấu trúc lặp với số lần không xác định..................................................................- 35 -
IV CÁC LỆNH LOGIC, DỊCH VÀ QUAY. NGĂN XẾP VÀ CÁC THỦ TỤC....- 38 -A.Các lệnh logic........................................................................................................- 38 -B.Các lệnh dịch và quay..........................................................................................- 38 -C. Ngăn xếp...............................................................................................................- 40 -D. Thủ tục.................................................................................................................- 41 -E. Vào ra với số nhị phân và số hex........................................................................- 41 -
V. Các lệnh nhân và chia............................................................................................- 45 -V. Các lệnh nhân và chia.............................................................................................- 46 -
A. Các lệnh nhân......................................................................................................- 46 -B. Các lệnh chia:......................................................................................................- 46 -C.Các thủ tục vào ra với số thập phân...................................................................- 46 -
1.Việc đưa ra các số thập phân...........................................................................- 46 -2.Nhập vào số thập phân.....................................................................................- 48 -
VI. Mảng......................................................................................................................- 50 -A. Mảng một chiều...................................................................................................- 50 -II. Mảng hai chiều....................................................................................................- 54 -
VII. Các lệnh thao tác chuỗi........................................................................................- 56 -1.Cờ định hướng......................................................................................................- 56 -2.Lệnh chuyển một chuỗi........................................................................................- 56 -3.Lệnh lưu chuỗi......................................................................................................- 57 -4.Nạp một chuỗi.......................................................................................................- 58 -5. Lệnh duyệt chuỗi (Scan String)..........................................................................- 58 -6. Lệnh so sánh chuỗi...............................................................................................- 59 -
18
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
19
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
CHƯƠNG 3 LẬP TRÌNH ASSEMBLY
Trong chương này chúng ta sẽ tìm hiểu cách lập trình Assembly cho các hệ vi xử lý được xây dựng trên bộ vi xử lý 8088 (và họ vi xử lý Intel 80x86 nói chung). Sở dĩ ta dùng ngôn ngữ lập trình Assembly để viết phần mềm cho hệ vi xử lý là vì nó có các ưu điểm sau:
- Sử dụng trực tiếp tập lệnh của bộ vi xử lý nên quá trình điều hành chức năng rất sát với cấu trúc phần cứng của hệ thống, tận dụng triệt để khả năng của phần cứng mà không một ngôn ngữ lập trình bậc cao nào làm được.
- Có tốc độ thực hiện nhanh hơn nhiều so với các ngôn ngữ bậc cao. Do vậy nó rất thích hợp với các chức năng yêu cầu thời gian thực chẳng hạn như thao tác với các tín hiệu biến đổi nhanh.
Các chương trình viết bằng ngôn ngữ Assembly phải được dịch ra ngôn ngữ máy (dạng nhị phân) vì đây là dạng duy nhất mà hệ vi xử lý có thể hiểu được. Có nhiều chương trình biên dịch nhưng thông dụng nhất hiện nay Macro Assembler của hãng Microsoft và Turbo Assembler của hãng Borland. Chúng ta sẽ sử dụng Macro Assembler 6.0 để biên dịch các chương trình Assembly. Chương trình biên dịch MASM 6.0 có rất nhiều file nhưng tối thiểu cần những file sau:
20
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
- MASM.EXE để biên dịch chương trình sang ngôn ngữ máy- LINK.EXE để liên kết các chương trình và tạo ra một chương trình chạy được có đuôi exe.- EXE2BIN để chuyển chương trình đuôi exe sang đuôi com.
I - KHUNG CHƯƠNG TRÌNH ASSEMBLY
1. BỘ KÝ TỰ CỦA ASSEMBLY
Một ngôn ngữ bất kỳ từ ngôn ngữ giao tiếp của con người tới ngôn ngữ máy tính đều xây dựng trên một bộ ký tự. Các ký tự ghép lại thành các từ có nghĩa gọi là từ vựng. Các từ lại được viết thành các câu tuân theo cú pháp và ngữ pháp của ngôn ngữ để diễn tả hành động sự việc cần thực hiện. Bộ ký tự của Assembly gồm có:
- Các chữ cái latin: 26 chữ hoa A-Z, 26 chữ thường a-z.- Các chữ số thập phân: ‘0’ - ‘9’- Các ký hiệu phép toán, các dấu chấm câu và các ký hiệu đặc biệt: + - * / @ ? $ , . : [ ] ( ) <
> { } & % ! \ # v.v...- Các ký tự ngăn cách: space và tab
2. TỪ KHÓA
Từ khóa là các từ của riêng Assembly như tên các thanh ghi, tên lệnh dạng gợi nhớ của bộ vi xử lý, tên toán tử... Các từ khóa này đòi hỏi người lập trình phải dùng đúng như Assembly quy định. Các từ khóa có thể viết bằng chữ hoa hoặc chữ thường đều được.
3. TÊN TỰ ĐẶT
Tên là một dãy ký tự dùng để biểu thị tên hằng, tên biến, tên nhãn, tên chương trình con, tên đoạn nhớ... Tên do người lập trình tự đặt nhưng phải tuân theo quy tắc sau:
Quy tắc đặt tên: Tên chỉ gồm chữ cái, chữ số và một số£ ký tự đặc biệt như ? @ _ $ Chữ đầu của tên bắt buộc phải là chữ cái. Trong tên không có dấu cách. Tên có thể dài từ 1 đến 35 ký tự.
4. CẤU TRÚC MỘT LỆNH ASSEMBLY
Một chương trình Assembly bao gồm các dòng lệnh, một dòng lệnh có thể là một lệnh thật dưới dạng gợi nhớ của bộ vi xử lý hoặc một hướng dẫn cho chương trình dịch (assembler directive, đôi khi gọi là lệnh giả). Lệnh thật sẽ được dịch ra mã máy còn lệnh giả thì không được dịch, vì nó chỉ có tác dụng chỉ dẫn cho chương trình dịch thực hiện công việc. Ta có thể viết các dòng lệnh bằng chữ hoa hoặc chữ thường đều được vì chúng được coi là tương đương nhau.
Một dòng lệnh của Assembly có thể có những trường sau (không nhất thiết phải có đủ các trường):
Tên Mã lệnh Các toán hạng Chú giải
Ví dụ:LAP: MOV AH,[BX] ; Copy nội dung của ô nhớ có địa chỉ DS:BX vào AHDòng lệnh trên có đủ 4 trường. Trường tên là nhãn LAP, trường mã lệnh là lệnh MOV,
trường toán hạng là các thanh ghi AH và BX, trường chú giải đặt sau dấu chấm phẩyMAIN PROCvàMAIN ENDPHai dòng lệnh này là hai lệnh giả, ở trường tên có tên thủ tục là MAIN, ở trường mã lệnh có
lệnh giả PROC và ENDP. Đây là hai lệnh giả để bắt đầu và kết thúc một thủ tục có tên là MAIN. Trường tên
21
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
Trường tên có thể là tên nhãn, tên biến hoặc tên thủ tục (chương trình con). Các tên và nhãn này sẽ được trình biên dịch gán bằng các địa chỉ cụ thể của ô nhớ. Một nhãn kết thúc bằng dấu hai chấm (:).
Trường mã lệnhChứa các lệnh thật hoặc lệnh giả
Trường toán hạngĐối với các lệnh thật thì trường này chứa các toán hạng của lệnh. Tùy từng loại lệnh mà có thể không có, có 1 hoặc 2 toán hạng trong một lệnh.Đối với các lệnh giả thì trường này chứa các thông tin khác liên quan đến lệnh giả.
Trường chú giảiLời giải thích phải được bắt đầu bằng dấu chấm phẩy. Trường chú giải dành cho người lập trình để ghi các lời giải thích cho các lệnh của chương trình, giúp cho người đọc chương trình dễ hiểu các thao tác của chương trình lớn. Khi đọc thấy dấu chấm phẩy, chương trình dịch bỏ qua không dịch từ sau dấu chấm phẩy đến hết dòng. Người lập trình có thể lợi dụng đặc điểm này để loại bỏ một dòng lệnh nào đó trong chương trình.
5. CÁC DẠNG HẰNG DÙNG TRONG ASSEMBLY
- Hằng số nhị phân: gồm một dãy các chữ số 0 và 1, kết thúc bằng chữ B. Ví dụ: 10011101B- Hằng số hex: gồm một dãy các số từ 0 đến 9 và các chữ cái từ A đến F (a đến f), kết thúc
bằng chữ H. Đối với các số bắt đầu bằng chữ thì phải thêm 0 đằng trước để báo cho chương trình dịch biết đó là số không phải là tên. Ví dụ: 7AC5H, 0ABH
- Hằng số thập phân: gồm một dãy các số từ 0 đến 9, có hoặc không có chữ D theo sau. Ví dụ: 34 hoặc 34D.
- Hằng ký tự: là một ký tự bất kỳ đặt giữa hai dấu phẩy trên. Ví dụ: ‘A’- Hằng xâu ký tự: là một dãy ký tự bất kỳ đặt giữa hai dấu phẩy trên. Ví dụ: ‘Nhap’
6. KHAI BÁO BIẾN VÀ HẰNG
a) Khai báo biến
Biến là tên ô nhớ dùng để cất giữ dữ liệu. Khai báo biến là đặt tên cho ô nhớ và xác định ô nhớ có kích thước 1 byte, 1 từ hay 1 từ kép. Các tên biến sẽ được trình biên dịch gán cho một địa chỉ nhất định trong bộ nhớ khi dịch chương trình. Khai báo biến kiểu byte
Tên biến DB Giá trị khởi đầuVí dụ:B1 DB 4
Ví dụ trên định nghĩa biến kiểu byte có tên là B1 và dành 1 byte bộ nhớ cho nó, trong byte đó có chứa giá trị 4.
Nếu không muốn biến chứa giá trị khởi đầu ta có thể dùng toán tử ? vào vị trí giá trị khởi đầu.
Ví dụ:B2 DB ?
Ví dụ trên chỉ định nghĩa biến byte có tên là B2 và dành 1 byte bộ nhớ cho nó. Khai báo biến kiểu từ
Tên biến DW Giá trị khởi đầuVí dụ:W1 DW 42HVí dụ này định nghĩa biến từ có tên là W1 và dành 2 byte bộ nhớ cho nó, trong đó chứa giá
trị khởi đầu là 42H.Muốn biến không chứa giá trị khởi đầu ta dùng toán tử ? và vị trí giá trị khởi đầu.
22
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
Ví dụ:W2 DW ?
Khai báo biến kiểu từ képTên biến DD Giá trị khởi đầuVí dụ:DW1 DD 1000
Khai báo biến mảngBiến mảng là biến hình thành từ một dãy liên tiếp các phần tử (ô nhớ) có cùng kiểu byte từ
hoặc từ kép. Khai báo biến mảng là đặt tên cho một dãy liên tiếp các byte từ hoặc từ kép trong bộ nhớ đồng thời cung cấp các giá trị ban đầu tương ứng. Số phần tử của mảng được xác định qua số giá trị khởi đầu.
Tên biến mảng DB/DW/DD Các giá trị khởi đầu
Ví dụ:M1 DB 4,5,6,7,8,9
Ví dụ trên định nghĩa biến mảng có tên là M1 và dành 6 byte liên tiếp cho nó để chứa các giá trị khởi đầu tương ứng là 4, 5 ,6 ,7 ,8 , 9. Phần tử đầu của mảng là 4 và có địa chỉ trùng với địa chỉ của tên biến (M1), phần tử thứ hai là 5 và có địa chỉ là M1+1...
Khi chúng ta muốn khởi đầu các phần tử của mảng với cùng một giá trị chúng ta có thể dùng thêm toán tử DUP. Toán tử DUP dùng để lặp lại các dữ liệu với số lần quy định. Cú pháp: Count DUP(Các dữ liệu) -> lặp lại các dữ liệu với số lần Count.
Ví dụ:M2 DB 20 DUP(0)M3 DB 20 DUP(?)
Ví dụ trên định nghĩa một biến mảng có tên là M2 gồm 20 byte để chứa 20 giá trị khởi đầu bằng 0 và một biến mảng khác có tên là M3 gồm 20 byte nhưng không chứa giá trị khởi đầu.
Chú ý:+ Toán tử DUP có thể dùng lồng nhau để định nghĩa 1 mảngVí dụ:M4 DB 4,3,2,2 DUP(1,2 DUP(5),6)
Khai báo này tương đương với khai báo sau:M4 DB 4,3,2,1,5,5,6,1,5,5,6+ Đối với các bộ vi xử lý của Intel, khi ta lưu trữ một từ trong bộ nhớ thì byte thấp của nó sẽ
được để ở ô nhớ có địa chỉ thấp, byte cao để ở ô nhớ có địa chỉ cao.Ví dụ:W1 DW 0FFACH
khi đó byte thấp ACH sẽ được để tại địa chỉ W1, còn byte cao FFH sẽ được để tại địa chỉ tiếp theo W1+1. Khai báo biến kiểu xâu ký tự
Biến kiểu xâu ký tự là trường hợp đặc biệt của biến mảng kiểu byte, trong đó các phần tử của mảng là các ký tự. Một xâu ký tự có thể định nghĩa bằng các ký tự hoặc bằng mã ASCII của các ký tự đó.
Ví dụ:Xaukt DB ‘ABCDE’hoặcXaukt DB 41h,42h,43h,44h,45hhoặc
23
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
Xaukt DB 41h,42h,’C’,’D’,45h
b) Khai báo hằng
Các hằng trong chương trình Assembly được gán tên để làm cho chương trình dễ đọc hơn. Hằng có thể là kiểu số hoặc kiểu ký tự. Việc gán tên cho hằng được thực hiện bằng lệnh giả EQU như sau:
Tên hằng EQU Giá trị của hằngVí dụ:CR EQU 0DhLF EQU 0AhCHAO EQU ‘Hello’
Vì lệnh giả EQU không dành chỗ của bộ nhớ cho tên hằng nên ta có thể khai báo hằng ở bất kỳ đâu trong chương trình. Tuy nhiên người ta thường đặt các khai báo hằng trong đoạn dữ liệu.
7. Một số lệnh cơ bản- MOV Đích, Nguồn
Sao chép dữ liệu Nguồn vào đích Toán hạng Toán đíchhạng nguồn
Thanh ghi công dụng chung
Thanh ghi đoạn
Ô nhớ Hằng số
Thanh ghi công dụng chung
Y Y Y N
Thanh ghi đoạn Y N Y N
Ô nhớ Y Y N N
Hằng số Y N Y N
Ví dụ:Mov AH,10D ;Chuyển giá trị 10 vào AHMov AX,BX ; Chuyển giá trị thanh ghi BX vào thanh ghi AXMov [DI],CX ; Chuyển giá trị thanh ghi CX vào ô nhớ DS:DI
24
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
- XCHG Đích, NguồnHoán đổi nội dung của 2 toán hạng đích và nguồn
Toán hạng Toán đích hạng nguồn
Thanh ghi công dụng chung
Ô nhớ
Thanh ghi công dụng chung
Y Y
Ô nhớ Y NVí dụ:
XCHG AH,BL ; Hoán đổi nội dung của hai thanh ghi AH và BL- Lệnh cộng không nhớ: ADD Đích, NguồnĐích Đích + NguồnLệnh ADD được sử dụng để cộng hai thanh ghi cùng độ dài, một thanh ghi và một ô nhớ
hoặc cộng một số vào một thanh ghi hay một ô nhớ (không được đồng thời là 2 ô nhớ và không được là thanh ghi đoạn)
- Lệnh cộng có nhớ: ADC Đích, Nguồn (Add With Carry)Đích Đích + Nguồn + CF- Lệnh tăng: INC ĐíchĐích Đích + 1- Lệnh giảm: DEC ĐíchĐích Đích - 1- Lệnh trừ không mượn: SUB Đích, NguồnĐích Đích - Nguồn- Lệnh trừ có mượn: SBB Đích, NguồnĐích Đích - Nguồn - CF- NEG ĐíchĐích -Đích. Dùng để phủ định nội dung của toán hạng đích- LEA Đích, Nguồn (Load Effective Address): Nạp địa chỉ thựcTrong đó:
+ Đích thường là một trong các thanh ghi: BX, CX, DX, BP, SI, DI+ Nguồn là tên biến trong đoạn DS được chỉ rõ trong lệnh hoặc ô nhớ cụ thể
Chuyển địa chỉ lệch của ô nhớ Nguồn vào thanh ghi Đích 16 bitVí dụ
Tb1 db “Nhap so can kiem tra: $”LEA DX, Tb1
8. Các lệnh vào raCó hai loại chương trình phục vụ vào/ ra: Các chương trình của DOS và BIOS (Basic
Input Output System). Các chương trình BIOS được chứa trong ROM và tác động trực tiếp tới các cổng vào/ra. Các chương trình của DOS có thể thực hiện các công việc phức tạp hơn, ví dụ in ra một chuỗi kí tự. Thực ra chúng sử dụng các chương trình của BIOS để thực hiện các thao tác vào/ ra trực tiếp.
Lệnh INTLệnh INT được dùng để gọi các chương trình ngắt của DOS và BIOS. Dạng lệnh:INT số_hiệu_ngắt
Trong đó số_hiệu_ngắt là một con số xác định một chương trình. Ví dụ: INT 16 sẽ gọi các phục vụ bàn phím của BIOS
Ngắt INT 21hNgắt int 21h 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 và gọi ngắt INT 21hSố hiệu hàm Chương trình
25
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
1 Nhập vào từ bàn phím 1 kí tự2 Đưa 1 kí tự ra màn hình9 Đưa ra màn hình 1 chuối kí tự kết thúc bởi dấu $
Các hàm của ngắt 21h nhận dữ liệu trong các thanh ghi nào đó và trả về kết quả trong các thanh ghi khác
- Hàm 1: Vào một kí tựo Input AH=1o Ra AL= Mã ASCII nếu 1 phím kí tự được ấn = 0 Nếu 1 phím điều khiển hay chức năng được ấn
Để gọi phục vụ này ta thực hiện lệnh:MOV AH,1INT 21h
- Hàm 2: Hiển thị một kí tự hay thi hành một chức năng điều khiểno Input: AH=2
DL=Mã ASCII của kí tự hiển thị hay kí tự điều khiểno Output: AL= Mã ASCII của kí tự hiển thị hay kí tự điều khiển
Để hiển thị một kí tự, ta đặt mã ASCII của nó trong DL. Ví dụ sau sẽ hiển thị dấu “?” lên màn hình
MOV AH,2MOV DL,”?”INT 21h
Sau khi kí tự được hiển thị, con trỏ màn hình dịch sang vị trí tiếp theo của dòng (nếu ở cuối dòng, con trỏ màn hình sẽ dịch chuyển sang đầu dòng tiếp theo)
Hàm 2 cũng có thể được dùng để thực hiện một chức năng điều khiển, hàm này sẽ thi hành chức năng điều khiển đó. Các kí tự điều khiển quan trọng:
Mã ASCII (Hex) Kí hiệu Chức năng
7 BEL Phát ra tiếng bip (beep)8 BS Lùi lại một vị trí9 HT TabA LF Xuống dòngD CR Về đầu dòng
Khi thực hiện, AL nhận mã ASCII của kí tự điều khiển- Hàm 9: Hiển thị một chuỗi
o Input: DX= địa chỉ tương đối (offset) của chuỗi.Chuỗi phải kết thúc bằng kí tự “$”o Output: Hiển thị chuỗi ra màn hình
Kí tự “$” đánh dấu kết thúc chuỗi và không được hiển thị. Nếu chuỗi chứa mã ASCII của kí tự điều khiển thì các chức năng điều khiển sẽ được thi hành.
9. KHUNG CỦA MỘT CHƯƠNG TRÌNH ASSEMBLY
Một chương trình mã máy trong bộ nhớ thường bao gồm các vùng nhớ khác nhau để chứa mã lệnh, chứa dữ liệu của chương trình và một vùng nhớ được dùng làm ngăn xếp phục vụ hoạt động của chương trình. Chương trình viết bằng ngôn ngữ Assembly cũng phải có cấu trúc tương tự để khi dịch nó sẽ tạo ra mã máy có cấu trúc như trên, tức là đoạn mã lệnh sẽ được dịch và để trong vùng nhớ mã lệnh, đoạn dữ liệu sẽ được dịch và để trong vùng nhớ dữ liệu và đoạn ngăn xếp sẽ được dịch và tạo ra vùng nhớ ngăn xếp cho chương trình.
Trước khi tìm hiểu khung của một chương trình Assembly ta xem xét các khai báo có trong chương trình:
26
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
a) Khai báo quy mô sử dụng bộ nhớ
Kích thước bộ nhớ dành cho đoạn mã và đoạn dữ liệu trong một chương trình được xác định bằng lệnh giả .MODEL. Lệnh này phải được đặt trước các lệnh khác trong chương trình nhưng đặt sau lệnh giả khai báo loại CPU. Cú pháp:
.MODEL Kiểu_kích_thước_bộ_nhớKiểu kích thước bộ nhớ Mô tảTINY Mã lệnh và dữ liệu gói gọn trong một đoạn 64 KBSMALL Mã lệnh gói gọn trong một đoạn 64 KB. Dữ liệu gói gọn trong
một đoạn 64 KBMEDIUM Mã lệnh không gói gọn trong một đoạn 64 KB
Dữ liệu gói gọn trong một đoạn 64 KBCOMPACT Mã lệnh gói gọn trong một đoạn 64 KB
Dữ liệu không gói gọn trong một đoạn 64 KBLARGE Mã lệnh không gói gọn trong một đoạn 64 KB
Dữ liệu không gói gọn trong một đoạn 64 KBKhông có mảng nào lớn hơn 64 KB
HUGE Mã lệnh không gói gọn trong một đoạn 64 KBDữ liệu không gói gọn trong một đoạn 64 KBCác mảng có thể lớn hơn 64 KB
b) Khai báo đoạn ngăn xếp
Việc khai báo đoạn ngăn xếp là để dành ra một vùng nhớ đủ lớn dùng làm ngăn xếp phục vụ cho hoạt động của chương trình. Cú pháp:
.STACK Kích_thước
Kích_thước quyết định số byte dành cho ngăn xếp. Thông thường với 100 - 256 byte là đủ để làm ngăn xếp và ta có thể khai báo kích thước cho ngăn xếp như sau:
.STACK 100hoặc.STACK 100H
c) Khai báo đoạn dữ liệu
Đoạn dữ liệu chứa toàn bộ các khai báo biến và hằng của chương trình. Các khai báo trong đoạn dữ liệu đặt sau lệnh giả .DATA
Ví dụ:.DATAMSG DB ‘Hello!$’B1 DB 100CR EQU 0DHLF EQU 0AH
d) Khai báo đoạn mã
Đoạn mã chứa mã lệnh của chương trình, tức là các lệnh của chương trình sẽ viết ở đây. Để bắt đầu đoạn mã ta dùng lệnh giả .CODE
Bên trong đoạn mã, các lệnh của chương trình có thể tổ chức thành chương trình chính và chương trình con như sau:
.CODETên_CTChính PROC
;Các lệnh của chương trình chính..
27
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
CALL Tên_CTCon ;Gọi chương trình con..
Tên_CTChính ENDP;Khai báo các chương trình con ở đâyTên_CTCon PROC
;Các lệnh của chương trình con
RET ;Trở vềTên_CTCon ENDP
e) Khung chương trình Assembly để dịch ra chương trình .EXE
.MODEL SMALL
.STACK 100H
.DATA;Các khai báo biến và hằng để tại đây
.CODEMAIN PROC
;Khởi đầu cho đoạn DSMOV AX,@DATAMOV DS,AX;Các lệnh của chương trình để tại đây
......;Trở về DOS dùng hàm 4CH của INT 21HMOV AH,4CHINT 21H
MAIN ENDP;Các chương trình con (nếu có) khai báo tại đây
END MAIN ;Kết thúc toàn bộ chương trình
Dòng cuối cùng của chương trình ta dùng lệnh giả END và tiếp theo là MAIN để kết thúc toàn bộ chương trình. Ta có nhận xét rằng MAIN là tên của chương trình chính nhưng về thực chất nó là nơi bắt đầu các lệnh của chương trình trong đoạn mã lệnh.
Khi một chương trình EXE được nạp vào bộ nhớ, DOS sẽ tạo ra một mảng gồm 256 byte làm đoạn mào đầu chương trình (Program Segment Prefix, PSP) dùng để chứa các thông tin liên quan đến chương trình và đặt nó vào ngay phía trước phần bộ nhớ chứa mã lệnh của chương trình. Trong khi đưa các thông số liên quan đến chương trình vào PSP, DOS đã sử dụng đến các thanh ghi DS và ES. Do vậy DS và ES không chứa giá trị địa chỉ của đoạn dữ liệu của chương trình. Để chương trình có thể chạy đúng ta phải có các lệnh khởi tạo cho thanh ghi đoạn DS (hoặc cả ES nếu cần) để chứa địa chỉ đoạn dữ liệu của chương trình.
MOV AX,@DATAMOV DS,AX;MOV ES,AX ;Nếu cầntrong đó @DATA là địa chỉ của đoạn dữ liệu.
Ví dụ: Chương trình hiện lên màn hình dòng chữ CHAO CAC BAN
.MODEL SMALL
.STACK 100H
.DATA
28
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
CRLF DB 13,10,’$’CHAO DB ‘CHAO CAC BAN!$’
.CODEMAIN PROC;Khoi tao thanh ghi DS
MOV AX,@DATAMOV DS,AX;Xuong dong moiMOV AH,9LEA DX,CRLFINT 21H;Hien thi loi chaoMOV AH,9LEA DX,CHAOINT 21H;Xuong dong moiMOV AH,9LEA DX,CRLFINT 21H;Tro ve DOSMOV AH,4CHINT 21H
MAIN ENDPEND MAIN
f) Khung chương trình Assembly để dịch ra chương trình .COM
Chương trình đuôi .COM ngắn gọn và đơn giản hơn nhiều so với chương trình đuôi .EXE. Trong chương trình đuôi .COM, đoạn mã, đoạn dữ liệu và đoạn ngăn xếp được gộp lại trong một đoạn duy nhất là đoạn mã. Việc tạo ra tệp này không những tiết kiệm được thời gian và bộ nhớ khi chạy chương trình mà còn tiết kiệm được cả không gian nhớ khi lưu trữ chương trình trên ổ đĩa.
Khung của chương trình Assembly để dịch ra đuôi .COM như sau:
.MODEL TINY
.CODEORG 100H
START: JMP CONTINUE;Các khai báo biến và hằng để tại đây
CONTINUE:MAIN PROC
;Các lệnh của chương trình chính để tại đây
;Trở về DOSINT 20H
MAIN ENDP;Các chương trình con (nếu có) khai báo ở đây
END START
29
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
Ta nhận thấy ở ngay đầu đoạn mã là lệnh giả ORG 100H dùng để gán địa chỉ bắt đầu của chương trình tại 100h trong đoạn mã, chừa lại vùng nhớ 256 byte (từ địa chỉ 0 đến 255) cho đoạn mào đầu chương trình (PSP).
Lệnh JMP sau nhãn START dùng để nhảy qua toàn bộ phần bộ nhớ dành cho việc khai báo dữ liệu. Đích của lệnh nhảy này là đầu chương trình chính.
Khi kết thúc chương trình COM, để trở về DOS ta dùng ngắt INT 20H của DOS để làm cho chương trình gọn hơn.
Để kết thúc toàn bộ chương trình ta dùng lệnh giả END theo sau là nhãn START, vì START tương ứng với địa chỉ lệnh đầu tiên của chương trình trong đoạn mã.
Ví dụ: Chương trình hiện lên màn hình dòng chữ CHAO CAC BAN
.MODEL TINY
.CODEORG 100H
START: JMP CONTINUECRLF DB 13,10,’$’CHAO DB ‘CHAO CAC BAN!$’
CONTINUE:MAIN PROC
;Xuong dong moiMOV AH,9LEA DX,CRLFINT 21H;Hien thi loi chaoMOV AH,9LEA DX,CHAOINT 21H;Xuong dong moiMOV AH,9LEA DX,CRLFINT 21H;Tro ve DOSINT 20H
MAIN ENDPEND START
II – BIÊN SOẠN VÀ DỊCH CHƯƠNG TRÌNH ASSEMBLY
Để viết và dịch các chương trình Assembly ta theo các bước sau:Bước 1: Soạn thảo chương trìnhDùng các phần mềm soạn thảo văn bản dạng TEXT (như NC, PASCAL, C) để tạo ra tệp văn
bản chương trình Assembly. Sau đó ghi tệp chương trình Assembly ra đĩa với đuôi .ASMBước 2: Dịch chương trình sang ngôn ngữ máyDùng chương trình dịch MASM để dịch tệp chương trình đuôi .ASM sang mã máy dưới
dạng tệp đuôi .OBJ. Nếu trong bước này chương trình có lỗi về cú pháp thì chương trình dịch sẽ báo lỗi và ta phải quay lại Bước 1 để sửa.
Cách làm như sau: giả sử chương trình MASM nằm trên thư mục gốc ổ C, dấu nhắc của DOS là C:\>, khi đó từ dấu nhắc của DOS gõ
MASM Tên tệp chương trình; Dấu chấm phẩy sau tên tệp chương trình để báo cho MASM chỉ tạo tệp .OBJ, không tạo ra
các tệp khác. Tên tệp chương trình có thể gõ đủ cả đuôi .ASM hoặc không gõ cũng được.Bước 3: Liên kết các tệp đuôi .OBJ để tạo thành một tệp chương trình chạy được đuôi .EXE
30
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
Cách làm như sau: giả sử chương trình liên kết LINK nằm trên thư mục gốc ổ C, dấu nhắc của DOS là C:\>, khi đó từ dấu nhắc của DOS ta gõ lệnh
LINK Têntệp1 + Têntệp2 + …;Chương trình liên kết sẽ lấy tên tệp đầu tiên (Têntệp1) để đặt tên cho tệp đuôi .EXE cuối
cùng. Dấu chấm phẩy sau cùng để báo cho chương trình LINK không hỏi tên các tệp.Bước 4: Nếu chương trình viết để dịch ra đuôi .COM thì ta phải dùng chương trình
EXE2BIN của DOS để dịch tiếp tệp .EXE ra tệp chương trình chạy được đuôi .COMCách làm như sau: giả sử chương trình EXE2BIN nằm trên thư mục gốc ổ C, dấu nhắc của
DOS là C:\>, khi đó từ dấu nhắc của DOS ta gõ lệnhEXE2BIN Têntệp.EXE Têntệp.COM
Chú ý: Với trình biên dịch MASM phiên bản 6.x trở lên, nếu chỉ biên dịch và liên kết một tệp chương trình thì ta có thể gộp Bước 2, 3, 4 thành một bước bằng cách dùng chương trình kết hợp cả biên dịch và liên kết ML. Tại dấu nhắc của DOS gõ vào như sau:
ML Têntệp1.ASM Ví dụ 2: Viết chương trình đổi chữ thường thành chữ hoa.MODEL SMALL.STACK 100H.DATA TB1 DB "NHAP VAO KI TU THUONG $" TB2 DB 10,13,"KI TU HOA: " CHR DB ?,"$".CODEMAIN PROC MOV AX,@DATA MOV DS,AX ;IN RA THONG BAO NHAP KI TU LEA DX,TB1 MOV AH,9 INT 21H ; NHAP VAO TU BAN PHIM 1 KI TU THUONG MOV AH,1 INT 21H ;THUC HIEN DOI KI TU THUONG THANH HOA SUB AL,20H MOV CHR,AL ;IN RA MAN HINH KI TU HOA LEA DX,TB2 MOV AH,9 INT 21H ;TRO VE DOS MOV AH,4CH INT 21HMAIN ENDP END MAINBài tập:3_1: Hãy viết chương trình thực hiện các công việc sau đây:1_: Đọc 1 kí tự và hiển thị nó ở vị trí tiếp theo trên cùng một dòng2_: Đọc 1 chữ hoa (bỏ qua kiểm tra lỗi) và hiển thị nó ở vị trí tiếp theo trên cùng một dòng
dưới dạng chữ thường
31
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
3_2: Hãy viết chương trình thực hiện các công việc sau đây1_: Hiển thị dấu (?)2_: Đọc hai chữ số thập phân có tổng nhỏ hơn 103_: Hiển thị các số đó với tổng của chúng với dòng thông báoVí du: ?2 5
Tổng của 2 và 5 là 73_3: Giả thiết rằng các số liệu sau đây được nạp vào bộ nhớ bắt đầu tại vị trí offset 0000h
A DB 7B DW 1ABChC DB ‘HELLO’
1_: Hãy cho biết các địa chỉ offset của các biến A, B, C2_: Hãy cho biết nội dung của byte tại offset 0002H dưới dạng số hex3_: Hãy cho biết nội dung của byte tại offset 0004h dưới dạng số hex4_: Hãy cho biết địa chỉ offset của kí tự ‘O’ trong ‘HELLO’3_4: Hãy cho biết mỗi lệnh dưới đây là hợp lệ hay không hợp lệ, trong đó W1, W2 là các
biến WORD; B1, B2 là các biến BYTE.a. MOV DS,AXb. MOV DS,100Hc. MOV DS,ESd. MOV W1,DSe. EXCH W1,W2f. SUB 5,B1g. ADD B1,B2h. ADD AL,256i. MOV W1,B1
III - THỰC HIỆN CÁC CẤU TRÚC ĐIỀU KHIỂN CHƯƠNG TRÌNH BẰNG ASSEMBLY
A. Lệnh JMP- Lệnh nhảy không điều kiện. Cú pháp
JMP NhãnChuyển CS:IP tới vị trí được xác định bởi Nhãn
B. Các lệnh nhảy có điều kiệnLệnh nhảy có điều kiện: J<Điều kiện> NHANNếu điều kiện thỏa mãn thì nhảy tới NHAN. Lệnh nhảy có điều kiện có độ dài 2 byte, byte
đầu là mã lệnh, byte sau là địa chỉ tương đối. Do vậy khoảng cực đại mà nó nhảy được là -128 đến 127. Muốn nhảy xa hơn phải dùng lệnh nhảy không điều kiện. Điều kiện được diễn tả bằng một cụm chữ cái đặt ngay sau J. Các lệnh nhảy có điều kiện bao gồm: JA, JAE, JB, JBE, JNA, JNAE, JNB, JNBE, JG, JGE, ....
Có ba loại nhảy có điều kiện:<1> Các lệnh nhảy có dấu được dùng khi kết quả trả về là các số có dấu<2> Các lệnh nhảy không dấu dùng với các số không dấu<3> Các lệnh nhảy điều kiện đơn: điều kiện phụ thuộc vào một cờ riêng biệt.a. Các lệnh nhảy không dấu- JA/ JNBE – Jump if Above/ Jump if Not Below or Equal (Nhảy nếu lớn hơn/ Nhảy nếu
không thấp hơn hoặc bằng). Lệnh:
JA NHANJNBE NHAN
NHAN phải nằm cách xa (dịch đi 1 khoảng) -128 .. 127 byte so với lệnh tiếp theo sau lệnh JA/ JNBE. Chương trình dịch sẽ căn cứ vào vị trí Nhan để xác định giá trị dịch chuyển.
32
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
- JAE/JNB - Jump if Above or Equal/ Jump if Not Below (Nhảy nếu cao hơn hoặc bằng/ Nhảy nếu không thấp hơn)
Lệnh:JAE NHANJNB NHAN
- JB/JC/JNAE – Jump if Below/ Jump if Not Above or Equal (Nhảy nếu thấp hơn/ Nhảy nếu có nhớ/ Nhảy nếu không cao hơn hoặc bằng)
JB NHANJC NHANJNAE NHAN
- JBE/JNA – Jump if Below or Equal/ Jump if Not Above (Nhảy nếu thấp hơn hoặc bằng/ Nhảy nếu không cao hơn)
JBE NHANJNA NHAN
b. Lệnh nhảy có dấu- JG/JNLE – Jump if Greater than/ Jump if Not Less than or Equal (Nhảy nếu lớn hơn/
Nhảy nếu không bé hơn hoặc bằng)JG NHANJNLE NHAN
- JGE/JNL – Jump if Greater than or Equal/ Jump if Not Less than (Nhảy nếu lớn hơn hoặc bằng/ Nhảy nếu không nhỏ hơn)
JGE NHANJNL NHAN
-JL/ JNGE – Jump if Less than/ Jump if Not Greater than or Equal (Nhảy nếu nhỏ hơn/ Nhảy nếu không lớn hơn hoặc bằng)
JL NHANJNGE NHAN
- JLE/JNG – Jump if Less than or Equal/ Jump if Not Greater than (Nhảy nếu nhỏ hơn hoặc bằng/ Nhảy nếu không lớn hơn)
JLE NHANJNG NHAN
c. Lệnh nhảy điều kiện đơn- JCXZ – Jump if CX Register if Zero (Nhảy nếu nội dung thanh đếm rỗng)
JCXZ NHAN- JE/JZ – Jump if Equal/ Jump if Zero (Nhảy nếu bằng nhau/ Nhảy nếu kết quả bằng
không)JE NHANJZ NHAN
- JC – Jump if Carry ( Nhảy nếu có nhớ)- JNC – Jump if Not Carry (Nhảy nếu không nhớ)- JO – Jump if Overflow (Nhảy nếu tràn)- JNO – Jump if Not Overflow (Nhảy nếu không tràn)- JS – Jump if Sign (Nhảy nếu dấu âm)- JNS – Jump if Not Sign (Nhảy nếu dấu dương)Tất cả các lệnh nhảy hoặc nhảy có điều kiện đều không tác động đến cờ
d. So sánh các lệnh nhảy có dấu và không dấuMỗi lệnh nhảy có dấu đều tương ứng với một lệnh nhảy không dấu. Ví dụ lệnh nhảy có dấu
JG và lệnh nhảy không dấu JA. Dùng lệnh nhảy có dấu hay không dấu là tuỳ thuộc vào kiểu số được đưa ra. Sử dụng không đúng loại có thể đưa đến kết quả sai.
Ví dụ: AX chứa 7FFFh, BX chứa 8000h
33
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
Cmp AX,BXJa TEST ; Không nhảy đến nhãn TESTNếu coi AX, BX là các số có dấu thì AX>BX nhưng sử dụngCmp AX,BXJa TEST ; Không nhảy đến nhãn TEST vì Ja là lệnh nhảy không dấu
C. LỆNH SO SÁNH
CMP Left, RightLeft có thể là thanh ghi hoặc ô nhớ (Không được phép là hằng số), Right có thể là thanh ghi
hoặc ô nhớ hoặc hằng số. Lệnh này so sánh Left và Right bằng cách lấy toán tử Left trừ đi toán tử Right, kết quả không được lưu lại nhưng các cờ bị ảnh hưởng. Các toán hạng của lệnh Cmp không thể cùng là các ô nhớ. Chú ý: CMP giống như SUB ngoại trừ việc toán hạng đích không bị thay đổiD. Các cấu trúc ngôn ngữ bậc cao
Thông thường khi lập trình chúng ta cần đến các cấu trúc điều khiển chương trình sau:+ Cấu trúc rẽ nhánh IF-THEN+ Cấu trúc lựa chọn CASE+ Cấu trúc lặp với số lần xác định FOR-DO+ Cấu trúc lặp với số lần không xác định REPEAT-UNTIL và WHILE-DOĐể thực hiện các cấu trúc điều khiển chương trình này chúng ta sử dụng các lệnh nhảy và
lệnh lặp của bộ vi xử lý. Cụ thể như sau:
1. CẤU TRÚC RẼ NHÁNH IF-THEN
Có hai dạng(1) IF <Điều kiện> THEN <Công việc>(2) IF <Điều kiện> THEN <Công việc 1> ELSE <Công việc 2>Hoạt động của cấu trúc này có thể diễn tả bằng lưu đồ sau
Ví dụ: 1. Viết đoạn chương trình gán BX |AX|
GiảiDùng cấu trúc IF để kiểm tra nếu AX < 0 thì đổi dấu. Sau cấu trúc IF dùng lệnh MOV để
đưa AX vào BX.IF_:
CMP AX,0JAE ENDIF_NEG AX
ENDIF_:
34
Điều kiện
Công việc
Điều kiện
Công việc 1 Công việc 2
Cấu trúc IF-THEN Cấu trúc IF-THEN-ELSE
Đúng
Sai Đúng Sai
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
MOV BX,AX
2. Giả sử AL và BL chứa mã ASCII của ký tự. Kiểm tra nếu AL<=BL thì hiện ra màn hình ký tự trong AL, còn không thì hiện ký tự trong BL.
GiảiThuật giảiIF AL<=BL THEN
Hiện ký tự trong ALELSE
Hiện ký tự trong BLENDIF
Đoạn chương trình như sau:IF_:
CMP AL,BLJA ELSE_MOV AH,2MOV DL, ALINT 21HJMP ENDIF_
ELSE_:MOV AH,2MOV DL, BLINT 21H
ENDIF_:
2. CẤU TRÚC LỰA CHỌN CASE
Khác với cấu trúc rẽ nhánh IF-THEN chỉ rẽ được hai nhánh, cấu trúc lựa chọn có thể rẽ nhiều nhánh. Dạng tổng quát như sau:
CASE <Biểu thức> OFGiá_trị_1: Công_việc_1Giá_trị_2: Công_việc_2
Giá_trị_N: Công_việc_NEND_CASEHoạt động của cấu trúc này thể hiện bằng lưu đồ sau:
Ví dụ: Nếu AX chứa số âm thì đưa -1 vào BX, nếu AX chứa 0 thì đưa 0 vào BX, nếu AX chứa số dương thì đưa 1 vào BX.
GiảiĐoạn chương trình như sau:CASE_:
CMP AX,0
35
Biểu thức
Công việc 1 Công việc 2 Công việc N……..
Giá_trị_1
Giá_trị_2
Giá_trị_N
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
JL AMJE KHONGJG DUONG
AM:MOV BX,-1JMP ENDCASE_
KHONG:MOV BX,0JMP ENDCASE_
DUONG:MOV BX,1
ENDCASE_:
3. CẤU TRÚC LẶP VỚI SỐ LẦN XÁC ĐỊNH FOR-DO
Dạng tổng quátFOR <Số lần lặp> DO
<Công việc>ENDFOR
Hoạt động của cấu trúc này thể hiện bằng lưu đồ sau:
Ví dụ: Hiện thị một dòng 80 ký tự ‘$’Đoạn chương trình như sau:FOR_:
MOV CX,80MOV AH,2MOV DL,’$’INT 21HLOOP FOR_
ENDFOR_:
4. CẤU TRÚC LẶP VỚI SỐ LẦN KHÔNG XÁC ĐỊNH
a) Kiểm tra điều kiện trước
Dạng tổng quátWHILE <Điều kiện> DO <Công việc>
Hoạt động của cấu trúc này được thể hiện qua lưu đồ sau:
Ví dụ: Đếm số ký tự đọc được từ bàn phím,khi gặp ký tự CR thì thôi.Đoạn chương trình như sau:
MOV CX,-1 ;Chứa số ký tự đếm đượcMOV AL,’$’ ;Để AL khác ký tự CRWHILE_:
CMP AL,0DH ;Có khác ký tự CR không?JE ENDWHILE_ ;Không khác, tức bằng CR thì thoátINC CXMOV AH,1INT 21HJMP WHILE_
ENDWHILE_:
b) Kiểm tra điều kiện sau
Dạng tổng quát
36
Đưa số lần lặp vào bộ đếm
Công việc
Giảm bộ đếm đi 1
Bộ đếm = 0?
Đúng
Sai
Điều kiện
Công việc
Cấu trúc WHILE-DO
Đúng
Sai
Điều kiện
Công việc
Cấu trúc REPEAT-UNTIL
Đúng
Sai
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
REPEAT <Công việc> UNTIL <Điều kiện>Hoạt động của cấu trúc này được thể hiện qua lưu đồ ở trên:
Ví dụ: Đếm số ký tự đọc được từ bàn phím, khi gặp ký tự CR thì thôi.Đoạn chương trình như sau:
MOV CX,0 ;Chứa số ký tự đếm đượcREPEAT_:
MOV AH,1INT 21HCMP AL,0DH ;Có bằng ký tự CR không?JE UNTIL_ ;Bằng CRINC CXJMP REPEAT_
UNTIL_:Bài tập:
1> Viết các lệnh để thực hiện các cấu trúc sau:a. If AX <0 then AH=0FFh
Else AH=0b. Giả thiết DL chứa mã ASCII của một kí tự:
If (DL>=’A’) And (DL<=’Z’) then Hiển thị DLc. If AX<BX then
If BX<CX then AX=0Else BX=0
d. If (AX<BX) Or (BX<CX) then DX=0Else DX=1
e. If AX<BX then AX=0Else If BX<CX then BX=0
Else CX=02> Dùng cẩu trúc CASE để mã hóa công việc sau:Đọc 1 kí tự:
Nếu là ‘A’ chuyển con trỏ về đầu dòngNếu là ‘B’ chuyển con trỏ xuống dòngNếu là một ký tự khác trở về DOS
3> Viết các lệnh thực hiện các công việc sau:a. AX = 1 + 3 + 5 + …. + 99b. AX = 100 + 95 + 90 + … + 54> Thuật toán sau có thể sử dụng để chia hai số dương bằng cách lặp lại phép trừ:
Khởi động thương = 0While số bị chia >= Số chia Do
Tăng thương sốTrừ bớt số chia từ số bị chia
EndWhileHãy viết lệnh thực hiện chia AX cho BX rồi cất thương trong CX5> Thuật toán sau có thể sử dụng để nhân hai số dương M và N bằng cách lặp lại phép cộng
Khởi động tích số = 0Repeat
Cộng M vào tích sốGiảm N
Until N=0Hãy viết các lệnh thực hiện nhân AX với BX rồi cất trong CX (bỏ qua trường hợp tràn)
37
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
38
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
IV CÁC LỆNH LOGIC, DỊCH VÀ QUAY. NGĂN XẾP VÀ CÁC THỦ TỤCA. Các lệnh logic
- AND Đích, NguồnĐích Đích AND NguồnĐổi mã ASCII của một số thành số tương ứng
Khi đọc 1 kí tự từ bàn phím, AL chứa mã ASCII của kí tự đó. Điều đó cũng đúng với các kí tự biểu diễn số. Ví dụ khi ấn phím “5”, AL chứa 35h thay cho 5. Để nhận được 5 trong thanh ghi AL ta có thể làm như sau:
SUB AL,30hMột phương pháp khác là sử dụng lệnh AND để xoá nửa byte cao của AL
AND AL,0FhVì mã ASCII của các chữ số từ “0” đến “9” là từ 30h đến 39h, phương pháp này có thể dùng
để đổi mã ASCII của bất kì chữ số nào thành giá trị thập phân tương ứng.Đổi chữ thường thành chữ hoaMã ASCII của các chữ thường từ “a” đến “z” nằm từ 61h đến 7Ah, mã ASCII của các chữ
hoa từ “A” đến “Z” nằm từ 41h đến 5Ah. Nếu DL chứa mã ASCII của 1 chữ thường ta có thể đổi ra chữ hoa bằng cách thực hiện lệnh:
SUB DL,20hTa so sánh mã ASCII dạng nhị phân của chữ thường và chữ hoa tương ứng:
Kí tự Mã ASCII Kí tự Mã ASCIIa 0110 0001 A 0100 0001b 0110 0010 B 0100 0010c 0110 0011 C 0100 0011. .. .z 0111 1010 Z 0101 1010
Để đổi từ chữ thường thành chữ hoa chúng ta chỉ cần xoá bit 5, ta có thể thực hiện bằng cách dùng lệnh AND với 1101 1111 hay 0DFh. Do đó nếu muốn đổi một chữ chứa trong DL thì ta có thể đổi bằng lệnh sau:
AND DL,0DFh- OR Đích, NguồnĐích Đích OR Nguồn- XOR Đích, NguồnĐích Đích XOR Nguồn- NOT ĐíchĐích NOT Đích- TEST Đích, NguồnĐích AND NguồnToán hạng Đích không bị thay đổi. Mục đích của lệnh TEST là thiết lập các cờCác cờ bị tác động:
SF, ZF, PF phản ánh kết quảAF không xác địnhCF,OF=0
B. Các lệnh dịch và quaya. Các lệnh dịch- SHL Đích,1 Một giá trị 0 sẽ được đưa vào vị trí bên phải nhất của toán hạng đích, còn bit msb của nó sẽ
được đưa vào cờ CF - SHL Đích,CL Trong đó CL chứa N. Trường hợp này N phép dịch trái đơn được thực hiện. Giá trị CL vẫn giữ nguyên không thay đổi khi thực hiện xong lệnh.
39
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
0
CF MSB LSBCác cờ bị tác động:
+ SF, PF, ZF phản ánh kết quả, PF chỉ có ý nghĩa khi kết quả là 8 bit+ CF chứa bit cuối cùng được dịch ra khỏi toán hạng+ OF = 1 nếu kết quả bị thay đổi dấu trong lần dịch chuyển cuối cùng
Ví dụ 1:DH chứa 8Ah, CL chứa 3. Cho biết giá trị DH, CF sau khi lệnh SHL DH,CL được thực
hiệnTrả lời:
Giá trị nhị phân trong DH: 1000 1010. Sau 3 lần dịch chuyển CF chứa giá trị 0, nội dung DH nhận được bằng cách xoá đi 3 bit trái nhất của DH và thêm vào 3 bit 0 vào phải nó. Kết quả nhận được ở DH: 01010000 = 50h
Ví dụ 2:AL chứa 5d =0000 0101b. Sau khi dịch trái 1 bit ta có: 00001010=10d nghĩa là bằng 2
giá trị của nó. Tiếp tục dịch trái ta nhận được 00010100b=20d- SAL Đích,1 hoặc SAL Đích,CL: tương tự lệnh SHL- SHR Đích,1 Một giá trị 0 sẽ được đưa vào bit msb của toán hạng đích, còn bit bên phải nhất của nó lsb sẽ
được đưa vào cờ CF- SHR Đích,CL
Trong đó CL chứa N. Trường hợp này N phép dịch phải đơn được thực hiện. Giá trị CL vẫn giữ nguyên không thay đổi khi thực hiện xong lệnh.
0
MSB LSB CFCác cờ bị tác động: giống như trường hợp dịch trái.Ví dụ:
DH chứa 8Ah, CL chứa 2. Cho biết giá trị DH, CF sau khi lệnh SHR DH,CL được thực hiện
Giá trị nhị phân trong DH: 1000 1010. Sau 2 lần dịch chuyển CF chứa giá trị 1, nội dung DH nhận được bằng cách xoá đi 2 bit phải nhất của DH và thêm vào 2 bit 0 vào trái nó. Kết quả nhận được ở DH: 00100010 = 22h
- SAR Đích,1 hoặc SAR Đích,CL: tương tự SHRb. Các lệnh quay- ROL Đích,1 hoặc ROL Đích,CL: Lệnh ROL (Rotate left) dịch các bit sang bên trái. Bit msb được dịch vào bit bên phải nhất,
đồng thời được đưa vào cờ CF, bit lsm theo sau bit msb.
CF MSB LSB
- ROR Đích,1 hoặc ROR Đích,CLLệnh ROR (Rotate right) dịch các bit sang bên phải, bit bên phải nhất được dịch vào bit msb
đồng thời cũng được đưa vào cờ C.
MSB LSB CF
- RCL Đích,1 hoặc RCL Đích,CL: Lệnh quay trái qua cờ nhớ - Rotate Carry LeftLệnh RCL dịch các bit của toán hạng đích sang trái. Bit msb được đặt vào cờ CF, giá trị cũ
của CF được đưa vào bit phải nhất của toán hạng đích
40
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
CF
MSB LSB
- RCR Đích,1 hoặc RCR Đích,CL: giống như CRL nhưng các bit được quay sang phải
CF
MSB LSBC. Ngăn xếp
Đoạn ngăn xếp của chương trình dùng để lưu trữ tạm thời các dữ liệu và địa chỉ.Ngăn xếp (LIFO) là cấu trúc dữ liệu một chiều, các phần tử được cất vào sau, lấy ra
trước (Last In First Out)Mỗi chương trình phải dành ra một khối bộ nhớ để làm ngăn xếp. Chúng ta thực hiện
điều này khi khai báo đoạn ngăn xếp.STACK 100h
- PUSH NguồnCất nội dung của một thanh ghi hoặc một ô nhớ 16 bit vào ngăn xếpVí dụ: PUSH AXLệnh PUSH thực hiện các công việc sau:
+ Giảm SP đi 2+ Một bản sao của nội dung của toán hạng nguồn được chuyển vào địa chỉ xác định bởi
SS:SP. Toán hạng nguồn không bị thay đổi.Ban đầu, SP chứa địa chỉ offset của ô nhớ theo sau đoạn ngăn xếp. Lệnh PUSH đầu tiên
giảm SP đi 2 làm cho con trỏ chỉ đến từ cuối cùng của trong đoạn ngăn xếp. Bởi vì lện PUSH làm giảm SP
Offset Offset00F0 00F000F2 00F200F4 00F400F6 00F600F8 00F800FA 00FA00FC 00FE SP 00FC 5678 SP 00FC SP00FE 1234 SP 1234 AX 00FE 1234 1234 AX0100 5678 BX 0100 5678 BX
Sau lệnh PUSH AX Sau lệnh PUSH BX- PUSHF
Không có toán hạng; cất nội dung của thanh ghi cờ vào ngăn xếp- POP Đích Lệnh POP được dùng để lấy ra phần tử đỉnh ngăn xếp, trong đó phần tử đích là một thanh
ghi 16 bit (trừ IP) hoặc là 1 từ nhớ.
41
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
Ví dụ:POP BX
Lệnh POP thực hiện các công việc sau:+ Nội dung của ô nhớ SS:SP (đỉnh ngăn xếp) được chuyển tới toán tử đích+ SP tăng lên 2- POPFLệnh POPF đưa vào thanh ghi cờ nội dung của đỉnh ngăn xếpChú ý: - Các lệnh PUSH, PUSHF, POP, POPF không ảnh hưởng đến cờ- Các lệnh PUSH và POP chỉ thao tác với các WORD, vậy nên nếu dùng với các byte, các
số liệu trực tiếp là không hợp lê. - Cất một số liệu trực tiếp là được phép đối với các bộ vi xử lý 80186, 80486
PUSH DL ; Không hợp lệPUSH 2 ; Không hợp lệBài tập: Viết chương trình nhập vào một chuỗi kí tự và hiển thị chúng theo thứ tự ngược lại
trên dòng tiếp theo.D. Thủ tục
Khai báo thủ tụcName PROC type
; thân thủ tục. . .RET
Name ENDPTrong đó: Name là tên của thủ tục định nghĩa bởi người sử dụng
Type toán hạng tuỳ chọn có thể là NEAR hay FAR (NEAR được ngầm định nếu bỏ qua type). NEAR có nghĩa là dòng lệnh gọi thủ tục ở cùng đoạn với thủ tục đó, ngược lại FAR có nghĩa là dòng lệnh gọi ở trong một đoạn khác
- Gọi CTC: CALL NhãnLệnh Call thực hiện các công việc sau đây:1. Địa chỉ trở về của chương trình gọi được cất vào ngăn xếp. Địa chỉ này là offset của lệnh
ngay sau dòng Call, dạng segment:offset của nó tại thời điểm thi hành lệnh Call chứa trong CS:IP
2. IP được gán bằng địa chỉ offset lệnh đầu tiên của thủ tục. Thao tác này chuyển điều khiển cho thủ tục
- Trở về từ CTC: RETĐể trở về từ một thủ tục ta dùng lệnh:
RET pop_valueTham số nguyên pop_value là tuỳ chọn. Trong một thủ tục NEAR, lệnh RET đưa giá trị ở
đỉnh ngăn xếp vào IP. Nếu pop_value xác định bằng N thì N sẽ được cộng vào SP. Điều này tương đương với việc lấy N byte khỏi ngăn xếp CS:IP lúc này chứa địa chỉ dạng segment:offset và điều khiển được trả lại cho chương trình gọi.E. Vào ra với số nhị phân và số hex* Nhập các số nhị phânGiả thiết ta nhập các số nhị phân từ bàn phím kết thúc bằng cách nhấn phím Enter. Các số nhận được ở dạng chuỗi các chữ số 0 và 1. Khi mỗi kí tự được nhập phải đổi ra giá trị của từng bit rồi kết hợp các bit vào trong thanh ghi, kết qủa lưu trong BX
Thuật toán:Xoá BX ;BX lưu kết quảNhập một kí tự ;’0’ hoặc ‘1’While kí tự <> CR Do
Đổi kí tự ra giá trị số nhị phân
42
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
Dịch trái BXChèn giá trị nhận được vào bit lsb của BXNhập kí tự
End_while
Ví dụ: Biểu diễn với việc nhập 101Xoá BX
BX=0000 0000 0000 0000Nhập vào kí tự ‘1’ đổi nó thành 1Dịch trái BX
BX=0000 0000 0000 0000Chèn giá trị nhị phân nhận được vào bit lsb của BX
BX=0000 0000 0000 0001Nhập kí tự ‘0’ đổi nó thành 0Dịch trái BX
BX=0000 0000 0000 0010Chèn giá trị nhị phân nhận được vào bit lsb của BX
BX=0000 0000 0000 0010Nhập kí tự ‘1’ đổi nó thanh 1Dịch trái BX
BX=0000 0000 0000 0100Chèn giá trị nhị phân nhận được vào bit lsb của BX
BX=0000 0000 0000 0101BX chứa 101B
Thuật toán sau sẽ kiểm tra các kí tự nhập hợp lệ và có nhiều nhất là 16 kí tự được nhập. Khi một chữ số mới được nhập vào, các bit sẵn có trong thanh ghi BX phải được dịch trái để giành chỗ cho nó. Ta có thể dùng lệnh OR để chèn bit mới vào BX.BG: MOV AH,1 INT 21H XOR BX,BX ; BX CHUA SO NHI PHAN CAN NHAPNHAP: CMP AL,'0' JL NHAPLAI CMP AL,'1' JG NHAPLAI CMP AL,13 JE THOAT AND AL,0FH SHL BX,1 OR BL,AL INT 21H JMP NHAPNHAPLAI: JMP BGTHOAT:
Việc viết ra các số nhị phân (nội dung thanh ghi BX) cũng dùng các lệnh dịch.Thuật toán đưa ra số nhị phânFor 16 lần Do
Quay trái BX ; BX chứa giá trị cần đưa ra, bit msb đưa vào CF
43
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
If CF=1 Then Đưa ra ‘1’Else Đưa ra ‘0’End_if
End_for
MOV CX,16 MOV N,0
VIETRA: XOR AL,AL ROL BX,1 RCL AL,1 CMP AL,1 JE VIET1 MOV DL,'0' JMP VIETVIET1: MOV DL,'1'
VIET: MOV AH,2 INT 21H INC N CMP N,4 JNE LAP MOV DL,' ' MOV AH,2 INT 21H MOV N,0LAP: LOOP VIETRA
44
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
Nhập số hexNhập số hex bao gồm các chữ số ‘0’ đến ‘9’ và các chữ cái từ ‘A’ đến ‘Z’ kết thúc bằng
kí tự CR. Để đơn giản ta giả thiết- Chỉ sử dụng các chữ hoa- Chỉ nhập vào tối đa 4 chữ số hexThuật toán nhập số hexXoá BX ;BX chứa giá trị nhập vàoNhập kí tự hexWhile kí tự <> CR Do
Đổi kí tự ra số nhị phânDịch trái BX 4 lầnChèn giá trị mới vào 4 bit của BXNhập kí tự
End_While
Đoạn mã chương trình nhập số hexBG: ;NHAP SO HEX MOV AH,1 INT 21H XOR BX,BX; BX CHUA SO NHI PHAN CAN NHAP MOV CL,4TEST_: CMP AL,13 JE EXIT CMP AL,'9' JG LETTER AND AL,0FH JMP SHIFTLETTER: SUB AL,37HSHIFT: SHL BX,CL OR BL,AL INT 21H JMP TEST_EXIT: Đưa ra số hexBX chứa số 16 bit bằng giá trị của số hex 4 chữ số. Để đưa ra nội dung của BX, chúng ta bắt đầu từ bên trái, lấy ra từng nhóm bit của mỗi chữ số đổi nó thành chữ số hex tương ứng sau đó đưa raThuật toán:For 4 lần Do
Chuyển BH vào DLDịch DL về bên phải 4 lầnIf DL<10 then
Đổi thành một trong các kí tự “0”.. ”9”Else Đổi thành một trong các chữ cái “A” … “F”Đưa kí tự ra Quay BX 4 lần về bên trái
End_For
45
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
;DUA RA SO HE HEX MOV N,4 LEA DX,TB2 MOV AH,9 INT 21H XOR DX,DXBG_H: CMP N,0 JE ESCAPE MOV DL,BH SHR DL,CL
CMP DL,10 JL DIGIT ADD DL,37H JMP WRITEDIGIT: OR DL,30HWRITE: MOV AH,2 INT 21H SHL BX,CL DEC N JMP BG_HESCAPE:
46
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
V. Các lệnh nhân và chiaA. Các lệnh nhân Sự khác nhau giữa phép nhân không dấu và có dấuTrong phép nhân các số không dấu và có dấu cần đối xử khác nhau. Ví dụ: Ta muốn nhân các số 8 bit 1000 0000 và 1111 1111. Nếu coi chúng là các số không dấu chúng lần lượt bằng 128 và 255, tích bằng: 32640=0111111110000000b Nếu coi chúng là các số có dấu chúng lại bằng -128 và -1 do đó tích sẽ bằng 128=000000010000000b Phép nhân không dấu MUL Nguồn
MUL Nguồn_8bitAX AL x Nguồn_8bitKhi nhân các byte với nhau, 1số được chứa trong toán hạng nguồn và số còn lại được giả
thiết đã chứa trong AL. Toán hạng nguồn có thể là 1 thanh ghi hay 1 byte nhớ nhưng không thể là hằng số
MUL Nguồn_16bitDX:AX AX x Nguồn_16bitSố bị nhân phải là số 16 bit để trong AX Lệnh nhân có dấu: IMUL Nguồn
Tương tự MUL, số bị nhân phải là số có dấu đặt trong AL hoặc AXVí dụ: Giả sử AX chứa 1 và BX chứ FFFFh
Lệnh Tích số dạng thập phân Tích số dạng hex DX AXMUL BX 65535 0000FFFF 0000 FFFFIMUL BX -1 FFFF FFFF FFFF FFFF
B. Các lệnh chia: Lệnh chia không dấu: DIV Nguồn
DIV Nguồn_8bitLấy AX chia cho Nguồn_8bit, thương để trong AL, số dư để trong AH. Nguồn_8bit không
thể là hằng số.DIV Nguồn_16bitLấy DX:AX chia cho Nguồn_16bit, thương để trong AX, số dư để trong DX* Sự tràn số trong phép chia: Có thể xảy ra trường hợp thương số qúa lớn để có thể chứa
trong toán hạng đích (AL hoặc AX). Điều này xảy ra khi số chia nhỏ hơn nhiều so với số bị chia. Khi xảy ra điều này chương trình dừng lại và thông báo: Divide Overflow
Lệnh chia có dấu: IDIV NguồnTương tự DIV
C. Các thủ tục vào ra với số thập phân1. Việc đưa ra các số thập phân
Chúng ta viết thủ tục Write_dec để in nội dung của AX như là một số thập phân có dấu. Nếu AX<0, Write_dec sẽ in ra dấu âm (-), rồi đổi AX thành –AX (để AX thành dương) và sau đó in ra nội dung của nó dưới dạng số thập phân. Trường hợp còn lại, vấn đề chỉ còn là in ra giá trị thập phân tương đương với một số dương dạng nhị phân
Thuật toán1_ If AX<0 Then /* AX chứa giá trị cần đưa ra*/2_ In ra dấu âm3_ Thay nội dung của AX bằng số bù 2 của nó4_ End_If5_ Lấy dạng biểu diễn thập phân các chứ số trong AX6_ Đổi các chữ số này thành các kí tự rồi đưa chúng ra màn hình
Để thấy được dòng 5_ cần làm những gì, ta giả sử nội dung của AX dưới dạng thập phân là 41562. Để nhận được từng chữ số dưới dạng thập phân ta thực hiện như sau:
Chia 41562 cho 10. Thương 4156, số dư là 2
47
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
Chia 4156 cho 10. Thương 415, số dư là 6Chia 415 cho 10. Thương 41, số dư là 5Chia 41 cho 10. Thương 4, số dư là 1Chia 4 cho 10. Thương 0, số dư 4Như vậy chữ số mà chúng ta muốn chính là số dư trong phép chia lặp cho 10. Nhưng
xếp theo thứ tự ngược lại, để đổi chúng ngược lại ta dùng ngăn xếpDòng 5_:Đếm =0; /*Biến đếm số chữ số thập phân*/Repeat
Chia số bị chia cho 10Cất số dư vào ngăn xếpĐếm = Đếm +1
Until Thương =0Trong đó giá trị ban đầu thương số chính là nội dung của AX. Khi các chữ số đã ở trong ngăn xếp, ta lấy các số từ ngăn xếp và đổi chúng thành kí tự. Dòng 6_For Đếm lần Do
Lấy chữ từ ngăn xếpĐổi nó thành kí tựĐưa ra màn hình kí tự
End_ForChương trìnhWRITE_DEC PROC PUSH AX ; Cất các thanh ghi PUSH BX PUSH CX PUSH DX
CMP AX,0 JGE @DUONG PUSH AX MOV DL,'-' MOV AH,2 INT 21H POP AX NEG AX@DUONG: XOR CX,CX ;Đếm các chữ số thập phân MOV BX,10 ;BX chứa số chia@LAP: XOR DX,DX DIV BX PUSH DX INC CX CMP AX,0 JNE @LAP
MOV AH,2@KETQUA: POP DX OR DX,30H INT 21H LOOP @KETQUA
48
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
POP DX POP CX POP BX POP AX RETWRITE_DEC ENDP
2. Nhập vào số thập phânĐể nhập vào các số thập phân chúng ta phải đổi chuỗi các số ASCII thành dạng biểu diễn nhị phân của số thập phân. Ta viết thủ tục Read_decThuật toán1_: Tổng =02_: Đọc 1 chữ số ASCII3_: Repeat
Đổi kí tự ra giá trị nhị phânTổng = Tổng + giá trị nhận đượcĐọc kí tự
4_: Until Kí tự nhận được là CR
Thủ tụcREAD_DEC PROC PUSH BX PUSH CX PUSH DX@BEGIN: MOV DL,'?' ;IN RA DAU '?' MOV AH,2 INT 21H XOR BX,BX; BX LA TONG XOR CX,CX; CX CHUA DAU MOV AH,1 INT 21H CMP AL,'-' JE @MINUS CMP AL,'+' JE @PLUS JMP @REPEAT_DONE@MINUS: MOV CX,1@PLUS: INT 21H@REPEAT_DONE: CMP AL,'0' JNGE @NOT_DIGIT CMP AL,'9' JNLE @NOT_DIGIT AND AX,000FH PUSH AX MOV AX,10 MUL BX POP BX ADD BX,AX
49
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
;DOC KI TU MOV AH,1 INT 21H CMP AL,13 JNE @REPEAT_DONE
MOV AX,BX;LUU KET QUA VAO AX OR CX,CX JE @EXIT NEG AX@EXIT: POP DX POP CX POP BX RET@NOT_DIGIT: MOV AH,2 MOV DL,10 INT 21H MOV DL,13 INT 21H JMP @BEGINREAD_DEC ENDP
50
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
VI. MảngA. Mảng một chiềuKhái niệm: Mảng một chiều là một dãy có thứ tự các phần tử có cùng một kiểu“Thứ tự” ở đây có nghĩa là thứ tự trước sau giữa các phần tử.Ví dụ: Mảng một chiều A có 6 phần tửChỉ số 1 2 3 4 5 6
a[1] a[2] a[3] a[4] a[5] a[6]
Trong các phần trước chúng ta đã sử dụng toán tử giả DB và DW để khai báo mảng byte và word. Ví dụ chuỗi kí tự ‘HELLO’Msg DB ‘HELLO’Hay một mảng W gồm 6 số nguyên được khởi tạo các giá trị: 0, 5, 10, 15, 20, 25W DW 0,5,10,15,20,25- Địa chỉ của biến mảng gọi là địa chỉ cơ sở của mảng (base address of the array). Nếu như địa chỉ offset gán cho W là 200h thì mảng W sẽ được phân bố trong bộ nhớ như sau:
Địa chỉ offset Kí hiệu địa chỉ Giá trị thập phân200h W 0202h W+2h 5204h W+4h 10206h W+6h 15208h W+8h 2020Ah W+Ah 25
- Để khai báo mảng với nhiều phần tử trùng nhau ta có thể sử dụng toán tử DUPRepeat_count DUP(value)Với toán tử này, value sẽ được lặp lại một số lần xác định bởi repeat_count.Ví dụ:
Gamma DW 100 DUP(0)thiết lập một mảng gồm 100 phần tử với giá trị khởi đầu cho mỗi phần tử là 0- Xác định vị trí các phần tử trong mảngĐịa chỉ của một phần tử của mảng có thể được xác định bằng cách cộng một hằng số vào địa chỉ cơ sở. Giả sử mảng A có S là số byte của một phần tử (đối với byte S=1, với word S=2). Vị trí các phần tử của mảng A được xác định như sau:
Ví dụ1: Hoán chuyển các phần tử thứ 10 và thứ 20 của mảng word WW[10] ở tại địa chỉ W+9*2=W+18 và W[20] tại W+19*2=W+38, vì vậy ta có thể đổi chỗ như sau:
MOV AX,W+18XCHG W+48,AXMOV W+18,AX
- Chế độ địa chỉ gián tiếp thanh ghiBài tập: Viết chương trình nhập vào và tính tổng các phần tử của mảng a1, a2, …, aN, trong
đó N là số phần tử của mảng.
51
Số thứ tự Vị trí
1 A2 A+1*S3 A+2*S4 A+3*S……N A+(N-1)*S
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
VD: W DW 5,10,15,20,25,30Để thực hiện được ta cần sử dụng chế độ địa chỉ gián tiếp thanh ghi. Thanh ghi đóng vai trò
như một con trỏ trỏ đến các ô nhớ.Các thanh ghi có thể là BX, DI, SI và SP. Với thanh ghi BX, DI, SI số hiệu đoạn được chứa
trong DS; với thanh ghi BP số hiệu đoạn là SS..MODEL SMALL.STACK 100.DATA TB1 DB "NHAP N : $" TB2 DB 10,13,"NHAP N CAC PHAN TU CUA MANG:$" TB3 DB 10,13,"TONG LA: $" A DW 20 DUP(?) N DW ? CRLF DB 10,13,'$'.CODEMAIN PROC MOV AX,@DATA MOV DS,AX; NHAP N LEA DX,TB1 MOV AH,9 INT 21H CALL READ_DEC ; Thu tuc nhap so thap phan, so thap phan nhap vao chua trong AX MOV N,AX
;NHAP N CAC PHAN TU CUA MANG MOV DX,OFFSET TB2 MOV AH,9 INT 21H MOV CX,N LEA SI,A ; Dua dia chi offset dau tien vao thanh ghi SINHAP: CALL READ_DEC MOV [SI],AX ADD SI,2 LEA DX,OFFSET CRLF MOV AH,9 INT 21H LOOP NHAP
;TINH TONG MOV DX,OFFSET TB3 MOV AH,9 INT 21H LEA DI,A ; Dua dia chi offset dau tien vao thanh ghi DI XOR BX,BX MOV CX,NTINHTONG: ADD BX,[DI] ADD DI,2 LOOP TINHTONG MOV AX,BX
52
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
CALL WRITE_DEC MOV AH,4CH INT 21HMAIN ENDP;Thủ tục nhập vào một số hệ 10;Thủ tục viết ra số hệ 10END MAIN
BTVN:- Viết thủ tục (chương trình) để đảo ngược một mảng gồm N phần tử- Gợi ý:
Trước khi vào thủ tục, SI trỏ đến mảng, BX chứa số phần tử của mảng NMục đích của bài toán là đổi chỗ phần tử thứ nhất và thứ N, phần tử thứ hai và thứ
(N-1), … Số lần hoán vị sẽ bằng N/2 (làm tròn xuống nếu như N lẻ). Trong phần trước ta biết phần tử đầu tiên của mảng có địa chỉ là A, phần tử thứ N của mảng là A + S*(N-1).
- Chế độ thanh ghi địa chỉ và chế độ địa chỉ chỉ số- Toán tử PTRDùng để định lại kiểu đã khai báo của một biểu thức địa chỉ. Cú pháp
Type PTR addess_expressionTrong đó: type có thể là kiểu Byte, Word hay Dword; còn biểu thức địa chỉ có kiểu là DB,
DW hay DDVí dụ:
Dollars db 25hCents db 12h
Ta cần chuyển giá trị của Dollars vào AL, giá trị của Cents vào AH chỉ bằng một lệnh:Mov AX, Dollars; không hợp lệ vì toán hạng nguồn và đích khác kiểu
Trong trường hợp này ta định lại kiểu:Mov AX, Word PTR Dollars
Lệnh này chuyển 1225h vào AX
- Toán tử giả LABELSử dụng toán tử giả, ta khai báo
Money Label WordDollars DB 25hCents DB 12h
Khai báo này ấn định Money là một biến word, Dollars và Cents là các biến byte; Money và Dollars được gán cho cùng một địa chỉ bởi trình biên dịch.
Như vậy: Mov AX, Money ;AL=Dollars, AH=Cents
Là hợp lệ. Lệnh này cho kểt quả tương đươngMov AL, DollarsMov AH, Cents
Ví dụ: Cho các dữ liệu được khai báo:.DATA
A DW 1234hB LABEL BYTE
DW 5678hC LABEL WORDC1 DB 0ADHC2 DB 1EH
53
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
Hỏi các lệnh nào trong các lệnh sau đây là hợp lệ. Với các lệnh hợp lệ cho biết địa chỉ offset của toán tử nguồn và con số được dịch chuyển.
Các lệnha. MOV AX,B ; Không hợp lệ, sai kiểub. MOV AH,B ; Hợp lệ, c. MOV CX,C ; Hợp lệ, d. MOV BX, WORD PTR Be. MOV DL, WORD PTR Cf. MOV AX, WORD PTR C1
- Sắp xếp mảngĐể sắp xếp một mảng N phần tử chúng ta thực hiện các bước sau đây:B1: Tìm phần tử lớn nhất của A[1], …, A[N]. Đổi chỗ nó và A[N]. Do phần tử lớn nhất đặt
ở vị trí N, chúng ta chỉ cần sắp xếp A[1], …, A[N-1]B2: Tìm phần tử lớn nhất của A[1], …, A[N-1], đổi chỗ nó và A[N-1].……Bước N-1: Tìm phần tử lớn nhất của A[1], A[2]. Đổi chỗ nó cho A[2]. Lúc này A[1]…A[N]
đã được đặt ở vị trí thích hợp. Mảng đã sắp xếp xong.Thuật toán sắp xếp lựa chọni=NFor N-1 lần lặp Do
Tìm vị trí k của phần tử lớn nhất của A[1] … A[i]Đổi chỗ A[k] và A[i]i=i-1
End_For
SELECT PROC;Input: Si=Địa chỉ offset của mảng; BX là số phần tử của mảng;Output: SI chứa địa chỉ của mảng đã sắp xếp; Sử dụng Swap dùng để trao đổi 2 phần tửPUSH BXPUSH CXPUSH DXPUSH SIDEC BX ;N=N-1CMP BX,1JE END_SORT ;Thoát nếu còn 1 phần tửMOV DX,SI ; Chép offset của mảngSORT_LOOP:
MOV SI,DXMOV DI,SIMOV AX,[DI]MOV CX,BX
FIND_BIG:ADD SI,2CMP AL,[SI]JG NEXTMOV DI,SIMOV AX,[SI]
NEXT:LOOP FIND_BIG
54
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
CALL SWAPDEC BXLOOP SORT_LOOP
POP SIPOP DXPOP CXPOP BXRETSELECT ENDP
; Thủ tục đổi chỗ 2 phần tửSWAP PROC
PUSH AXMOV AX,[DI]XCHG AX,[SI]MOV D[I],AXPOP AXRET
SWAP ENDBTVN: Viết chương sắp xếp một dãy các phần tử theo thứ tự tăng dần bằng phương pháp
nổi bọt (Bubble)II. Mảng hai chiềuMảng hai chiều (two dimensional array) là mảng của các mảng có nghĩa là một mảng một
chiều mà các phần tử của nó là các mảng một chiều (các phần tử được sắp xếp vào các hàng và các cột).
Ví dụ: Mảng hai chiều 3x4 Hàng
Cột1 2 3 4
1 B[1,1] B[1,2] B[1,3] B[1,4]
2 B[2,1] B[1,2] B[1,3] B[1,4]
3 B[3,1] B[3,2] B[3,3] B[3,4]
Cách lưu trữ mảng hai chiều trong bộ nhớVì bộ nhớ là mảng một chiều nên các phần tử của mảng hai chiều phải được lưu trữ liên tiếp.
Có hai phương pháp thường được sử dụng để lưu trữ mảng.Phương pháp 1: Lưu trữ theo thứ tự hàng (row – major order), trong đó các phần tử hàng 1
được lưu trữ, tiếp theo là các phần tử của hàng 2, …Phương pháp 2: Lưu trữ theo thứ tự cột, phương pháp này lưu trữ dữ liệu cột 1, cột 2, ..Ví dụ: Mảng B chứa 10,20,30,40 hàng 1; 50, 60, 70, 80 hàng 2; 90, 100,110, 120 hàng 3. Nó
có thể được lưu trữ theo thứ tự:Hàng:B DB 10, 20, 30, 40
DB 50, 60, 70, 80DB 90, 100, 110, 120
Theo cột:B DB 10, 50, 90
20, 60, 10030, 70, 11040, 80, 120
55
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
Hầu hết các chương trình biên dịch ngôn ngữ bậc cao lưu trữ mảng hai chiều theo thứ tự hàng. Trong Hợp ngữ chúng ta có thể lưu trữ theo cả hai cách.
Xác định vị trí một phần tử trong mảng hai chiềuGiả sử ta có một mảng hai chiều lưu trữ theo hàng trong bộ nhớ, trong đó kích thước mỗi
phần tử là S (S=1 mảng byte, S=2 mảng word). Để tìm vị trí của A[i,j] ta xác định:1. Vị trí bắt đầu cột i2. Vị trí của phần tử thứ j trong hàng
Bước 1: Xác định cột thứ iHàng 1 bắt đầu tại vị trí A. Do có N phần tử trong mỗi hàng và mỗi phần tử có kích thước S byte, hàng 2 có vị trí bắt đầu tại: A+N*S. Tương tự hàng 3 bắt đầu tại vị trí A+ 2*N*S.Tổng quát: Hàng i sẽ bắt đầu tại vị trí: A+(i-1)*N*SBước 2: phần tử thứ j trong hàng được lưu trữ tại vị trí (j-1)*SVới mảng A kích thước MxN, mỗi phần tử chiếm S byte
A[i,j] có địa chỉ A+((i-1)*N+(j-1))*STương tự với các mảng lưu trữ theo thứ tự cột:
A[i,j] có địa chỉ A +((i-1)+(j-1)*M)*SBài tập: Viết chương trình s
56
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
VII. Các lệnh thao tác chuỗi1. Cờ định hướng
Một trong những cờ điều khiển đó là cờ hướng (DF – Direction Flag), có tác dụng là xác định hướng cho các thao tác chuỗi. Các thao tác này được thực hiện bằng 2 thanh ghi chỉ số SI, DIVí dụ:
St DB ‘ABCDE’Chuỗi này được lưu trong bộ nhớ tại địa chỉ offset 0200hĐịa chỉ offset Nội dung Kí tự ASCII0200h 041h A0201h 042h B0202h 043h C0203h 044h D0204h 045h E
Nếu cờ DF=0, SI và DI được xử lý theo chiều tăng của các địa chỉ bộ nhớ, từ trái sang phải trong chuỗi. Ngược lại, DF=1, SI và DI được xử lý trong chuỗi theo chiều giảm dần của địa chỉ bộ nhớ: từ phải sang trái trong các chuỗi.* Các lệnh LCD và STDĐể làm cho DF=0, chúng ta sử dụng lệnh CLD (Clear Direction flag)
CLD ;xoá cờ định hướngĐể làm cho DF=1 chúng ta sử dụng lệnh STD (SeT Direction flag)
STD ;thiết lập cờ định hướngCác lệnh CLD, STD không làm ảnh hưởng tới các cờ khác2. Lệnh chuyển một chuỗi
Giả sử:.DATA
St1 DB ‘Xin chao’St2 DB 8 DUP (?)
Giờ ta muốn chuyển nội dung của chuỗi St1 (chuỗi nguồn) vào St2 (chuỗi đích). Lệnh MOVSB
MOVSB ; chuyển một chuỗi các byte- Sao chép nội dung của byte được định bởi địa chỉ DS:SI đến byte được định bởi địa chỉ
ES:DI. Nội dung của byte nguồn không thay đổi. Sau khi byte được chuyển cả 2 thanh ghi SI và DI đều tự động tăng lên 1 nếu DF=0, giảm đi 1 nếu DF=1.
- Lệnh MOVSB chỉ chuyển 1 byte từ chuỗi nguồn tới chuỗi đích. Để chuyển cả chuỗi ta khởi tạo CX =N bằng số byte trong chuỗi nguồn và thực hiện lệnh:
REP MOVSBLệnh REP có tác dụng làm cho MOVSB thực hiện N lần, sau mỗi lệnh MOVSB, CX được
giảm đi 1 cho đến khi CX =0.Ví dụ 1: Viết các lệnh sao chép chuỗi St1 vào chuỗi St2 theo thứ tự ngược lạiGiải: Ý tưởng: là cho SI trỏ đến cuối chuỗi 1 và DI trỏ đến đầu chuỗi 2, sau đó chuyển các
kí tự, SI chuyển dọc theo chuỗi St1 từ phải qua trái.
LEA SI,ST1+7LEA DI,ST2STD ; Chieu giam dan bo nho MOV CX,8
MOVE:MOVSB ; Chuyển từng byteADD DI,2 ; Vì DF=1 thì sau mỗi lệnh Movsb thì SI, DI đều tự động giảm 1, trong khi
ta cần tăng DI lên 1LOOP MOVE
57
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
Lệnh MOVSWDạng lệnh:
MOVSW ; Chuyển một chuỗi các wordTương tự lệnh MOVSB, nhưng lệnh MOVSW chuyển từng word từ chuỗi nguồn đến chuỗi
đích. Sau khi một word được chuyển cả SI, DI đều tăng lên 2 đơn vị nếu DF=0 hoặc giảm đi 2 nếu DF=1
MOVSB, MOVSW đều không ảnh hưởng đến cờ.3. Lệnh lưu chuỗiLệnh STOSBDạng lệnh:
STOSB ; Lưu chuỗi các byteChuyển nội dung của thanh ghi AL đến byte được định bởi địa chỉ ES:DI. Sau khi lệnh được
thực hiện DI tăng lên 1 nếu DF=0 hoặc giảm đi 1 nếu DF=1Lệnh STOSWDạng lệnh
STOSW ; Lưu chuỗi các wordChuyển nội dung của thanh ghi AX vào word được định bởi địa chỉ ES:DI và tăng hay giảm
DI đi 2 đơn vị tuỳ thuộc vào trạng thái cờ DFCác lệnh STOSB và STOSW không ảnh hưởng tới cờ.Đọc và lưu một chuỗi kí tựViết thủ tục đọc và lưu các kí tự trong một chuỗi, kết thúc bởi Enter. Thủ tục bắt đầu với địa chỉ offset của chuỗi tại DI, thực hiện xong nó trả về địa chỉ offset
chuỗi trong DI và số kí tự nhập vào trong BX. Nếu nhập kí tự BackSpace thì thủ tục xoá kí tự đó khỏi chuỗi
READ_STR PROC PUSH AX PUSH DI CLD XOR BX,BX MOV AH,1 INT 21HWHILE1: CMP AL,13 ;So sánh AL với kí tự xuống dòng JE END_WHILE1 CMP AL,8H ; So sánh AL với Backspace JNE @DONE DEC DI DEC BX JMP @READ@DONE:
STOSB INC BX@READ:
INT 21H JMP WHILE1END_WHILE1: POP DI POP AX RETREAD_STR ENDP
58
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
4. Nạp một chuỗiLệnh LODSBDạng lệnh:
LODSB ; nạp một chuỗi các byteChuyển byte tại địa chỉ được chỉ bởi DS:SI vào AL, sau đó SI được tăng lên 1 nếu DF=0, giảm 1 nếu DF=1Lệnh LODSWDạng lệnh:
LODSW; nạp một chuỗi các wordChuyển word tại địa chỉ được chỉ bởi DS:SI vào AX, sau đó SI được tăng lên 2 nếu DF=0, giảm 2 nếu DF=1Các lệnh LODSB, LODSW không tác động đến các cờ.Hiển thị một chuỗi kí tựViết thủ tục hiển thị một chuỗi kí tự được trỏ bởi SI với số kí tự trong BXWRITE_STR PROC PUSH AX PUSH BX PUSH CX PUSH DX PUSH SI MOV CX,BX JCXZ EXIT CLD MOV AH,2TOP: LODSB MOV DL,AL INT 21H LOOP TOPEXIT: POP SI POP DX POP CX POP BX POP AX RETWRITE_STR ENDP
5. Lệnh duyệt chuỗi (Scan String)Dạng lệnh:
SCASB ; Duyệt một chuỗi các byteSử dụng để tìm một byte (tạm gọi là byte đích - target byte) trong một chuỗi. Byte đích được chứa trong AL. Lệnh SCASB lấy nội dung của AL trừ đi từngbyte trong chuỗi và sử dụng kết quả dể thiết lập các cờ. Kết quả không lưu lại và sau mỗi lần thực hiện phép trừ DI được tăng lên 1 nếu DF=0 và giảm 1 nếu DF=1Dạng word
SCASW ; Duyệt chuỗi các wordTrường hợp này word đích được đặt trong AX. SCASW trừ nội dung của AX cho từng word của chuỗi và thiết lập cờ. DI được tăng lên 2 nếu DF=0 và giảm 2 nếu DF=1Tất cả các cờ đều bị ảnh hưởng bởi 2 lệnh này.
Ví dụ:St1 DB ‘ABCDE’
59
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
Kiểm tra xem 2 byte đầu của chuỗi có phải là chữ ‘B’ không?
MOV AX, @DATAMOV ES, AXCLDLEA DX, ST1MOV AL,’B’SCASB ;Duyệt byte thứ nhấtSCASB ; Duyệt byte thứ 2
Trước lệnh SCASBDI
St1 ‘A’ ‘B’ ‘C’ ‘D’ ‘E’ ‘B’ ZF=0(Không thấy)Offset 0 1 2 3 4 AL
Sau lệnh SCASB thứ nhấtDI
St1 ‘A’ ‘B’ ‘C’ ‘D’ ‘E’ ‘B’ ZF=0(Không thấy)Offset 0 1 2 3 4 AL
Sau lệnh SCASB thứ haiDI
St1 ‘A’ ‘B’ ‘C’ ‘D’ ‘E’ ‘B’ ZF=1(Không thấy)Offset 0 1 2 3 4 AL
Ta thấy khi đích ‘B’ được tìm thấy, cờ ZF được thiết lập và do DI tự động được tăng thêm 1 nên DI trở tới kí tự đứng sau kí tự cần tìm.
Khi tìm một byte đích trong chuỗi, chuỗi sẽ được duyệt cho đến khi byte được tìm thấy hoặc hết chuỗi
Khi tìm một byte đích trong chuỗi, chuỗi sẽ được duyệt cho đến khi byte được tìm thấy hoặc hết chuỗi. Nếu CX nhận giá trị đầu là số byte trong chuỗi
REPNE SCASB ;lặp lại khi chưa bằng (chưa đến đích)Sẽ lặp lại phép trừ nội dung của AL đi từngbyte trong chuỗi, điều chỉnh DI, giảm CX cho đến khi có kết quả 0 (khi tìm thấy byte đích) hoặc CX=0 (khi chuỗi kết thúc)
Chú ý: Lệnh REPNZ (REPeat while Not Zero) tạo ra mã máy giống như lệnh REPNE (REPeat while Not Equal)Bài tập: Đếm số nguyên âm và phụ âm trong chuỗi
6. Lệnh so sánh chuỗi
60
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
Lệnh CMPSBCMPSB ; so sánh chuỗi các byte
Trừ byte tại địa chỉ DS:SI cho byte tại địa chỉ ES:DI và thiết lập cờ. Kết quả không được lưu lại, sau đó cả SI và DI cùng tăng 1 nếu DF=0 hay giảm 1 nếu DF=1
Dạng wordCMPSW ; so sánh chuỗi các word
Lệnh này trừ word tại địa chỉ DS:SI cho word tại địa chỉ ES:DI và thiết lập các cờ. Nếu DF=0 SI và DI được tăng 2 và ngược lại. Lệnh CMPSW rất hữu hiệu khi dùng để so sánh các mảng số kiểu word.
Tất cả các cờ đều bị tác động bởi 2 lệnh CMPSB và CMPSWVí dụ:
ST1 DB ‘DKG’ST2 DB ‘DEG’
Để so sánh 2 byte đầu tiên của chuỗi trên ta thực hiệnMOV AX, @DATAMOV DS,AXMOV ES,AXCLDLEA SI,ST1LEA DI,ST2CMPSBCMPSB
Trước lệnh CMPSBSI
St1 ‘D’ ‘K’ ‘G’
Offset 0 1 2
DI
St2 ‘D’ ‘E’ ‘G’
Offset 0 1 2
Sau lệnh CMPSB thứ nhất
SI
Kết qủa 44h-44h=0Không lưuZF=1, SF=0St1 ‘D’ ‘K’ ‘G’
Offset 0 1 2
DI
St2 ‘D’ ‘E’ ‘G’
Offset 0 1 2
Sau lệnh CMPSB thứ hai
61
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
SI
Kết qủa: 4Bh-45h=5h(Không lưu)
ZF=0, SF=0St1 ‘D’ ‘K’ ‘G’
Offset 0 1 2
DI
St2 ‘D’ ‘E’ ‘G’
Offset 0 1 2
Các lệnh khởi tạo REPE và REPZViệc so sánh chuỗi có thể được thực hiện bằng cách gắn thêm lệnh khởi tạo REPE
(Repeat while Equal) hay REPZ (REPeat while Zero) vào các lệnh CMPSB và CMPSW. CX nhận giá trị ban đầu là số byte trong chuỗi ngắn hơn sau đó ta có:
REPE CMPSB; So sánh chuỗi các byte khi còn bằng nhauHay
REPZ CMPSW; So sánh chuỗi các word khi còn bằng nhauSẽ lặp lại việc thực hiện CMPSB hay CMPSW rồi giảm CX cho đến khi
Có 2 byte tương ứng ở 2 chuỗi không bằng nhau CX=0
Các cờ được thiết lập tùy theo kết quả của phép so sánh cuối cùngLệnh CMPSB có thể sử dụng để so sánh 2 chuỗi xem chuỗi nào đứng trước theo thứ tự
alpha bê, chúng có giống nhau hay chuỗi này có là chuỗi con của chuỗi kia không (có nghĩa là một chuỗi được chứa trong chuỗi còn lại như là một chuỗi các ký tự liên tiêp nhau)
Ví dụ: Chuỗi St1, St2 có độ dài là 10. Thực hiện so sánh 2 chuỗi, đưa 0 vào AX nếu 2 chuỗi giống nhau, 1 nếu chuỗi St1 đứng trước chuỗi St2, 2 nếu chuỗi St1 đứng sau chuỗi St2. Giả sử DS, ES được khởi động thích hợp.
MOV CX,10LEA SI,ST1LEA DI,ST2CLDREPE CMPSBJL DUNGTRUOC ;ST1 đứng trước ST2JG DUNGSAU ;ST1 đứng sau ST2MOV AX,0JMP EXIT
DUNGTRUOC: MOV AX,1 JMP EXIT
DUNGSAU:MOV AX,2
EXIT:
62
Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly
63