57
Bi ging k thut vi x l Chương 3 Lp trình Assembly cho hệ vi x l 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 - 18

Chuong03_H

Embed Size (px)

Citation preview

Page 1: Chuong03_H

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

Page 2: Chuong03_H

Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly

19

Page 3: Chuong03_H

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

Page 4: Chuong03_H

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

Page 5: Chuong03_H

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

Page 6: Chuong03_H

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

Page 7: Chuong03_H

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

Page 8: Chuong03_H

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

Page 9: Chuong03_H

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

Page 10: Chuong03_H

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

Page 11: Chuong03_H

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

Page 12: Chuong03_H

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

Page 13: Chuong03_H

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

Page 14: Chuong03_H

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

Page 15: Chuong03_H

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

Page 16: Chuong03_H

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

Page 17: Chuong03_H

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

Page 18: Chuong03_H

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

Page 19: Chuong03_H

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

Page 20: Chuong03_H

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

Page 21: Chuong03_H

Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly

38

Page 22: Chuong03_H

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

Page 23: Chuong03_H

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

Page 24: Chuong03_H

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

Page 25: Chuong03_H

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

Page 26: Chuong03_H

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

Page 27: Chuong03_H

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

Page 28: Chuong03_H

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

Page 29: Chuong03_H

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

Page 30: Chuong03_H

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

Page 31: Chuong03_H

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

Page 32: Chuong03_H

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

Page 33: Chuong03_H

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

Page 34: Chuong03_H

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

Page 35: Chuong03_H

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

Page 36: Chuong03_H

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

Page 37: Chuong03_H

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

Page 38: Chuong03_H

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

Page 39: Chuong03_H

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

Page 40: Chuong03_H

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

Page 41: Chuong03_H

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

Page 42: Chuong03_H

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

Page 43: Chuong03_H

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

Page 44: Chuong03_H

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

Page 45: Chuong03_H

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

Page 46: Chuong03_H

Bai giang ky thuât vi xư ly Chương 3 Lâp trình Assembly cho hệ vi xư ly

63