Giáo trình Lập trình hệ thống - Nguyễn Hứa Duy Khang
Bạn đang xem 20 trang mẫu của tài liệu "Giáo trình Lập trình hệ thống - Nguyễn Hứa Duy Khang", để tải tài liệu gốc về máy bạn click vào nút DOWNLOAD ở trên
Tài liệu đính kèm:
- giao_trinh_lap_trinh_he_thong_nguyen_hua_duy_khang.pdf
Nội dung text: Giáo trình Lập trình hệ thống - Nguyễn Hứa Duy Khang
- TRƯỜNG ĐẠI HỌC CẦN THƠ KHOA CÔNG NGHỆ BỘ MÔN ĐIỆN TỬ - VIỄN THÔNG Giáo trình LẬP TRÌNH HỆ THỐNG Biên soạn: ThS. Nguyễn Hứa Duy Khang Ks. Trần Hữu Danh -ĐHCT- Tháng 5-2008
- Lập trình Hệ Thống NỘI DUNG Chương 1 - TỔ CHỨC BỘ XỬ LÝ INTEL-8086 1 1.1. Bộ xử lý Intel-8086 (CPU-8086) 1 1.1.1. Cấu trúc tổng quát 1 1.1.2. Các thanh ghi của 8086 2 1.1.3. Trạng thái tràn: 5 1.2. Bộ nhớ trong của Intel-80x86 5 1.2.1. Tổ chức dữ liệu 5 1.2.2. Sự phân đoạn bộ nhớ trong 6 1.3. Địa chỉ các ngoại vi 7 1.4. Các bộ xử lý Intel khác 8 1.4.1. Bộ xử lý Intel-80386 8 1.4.2. Tập thanh ghi của bộ xử lý Intel-80386: 8 1.4.3. Các chế độ vận hành của bộ xử lý Intel-80386 9 1.4.4. Bộ xử lý Intel-80486: 10 1.4.5. Bộ xử lý Intel PENTIUM: 11 BÀI TẬP CHƯƠNG 1 13 Chương 2 - HỢP NGỮ 15 2.1. Ngôn ngữ máy và hợp ngữ 15 2.2. Đặc tính tổng quát của hợp ngữ 16 2.2.1. Cấu trúc của một dòng lệnh hợp ngữ. 16 2.2.2. Macro 17 2.2.3. Chương trình con 17 2.2.4. Biến toàn cục (global), biến địa phương (local) 18 2.2.5. Các bảng, thông báo: 18 2.2.6. Hợp ngữ chéo (cross assembler) 19 2.3. Hợp ngữ MASM (hợp ngữ của CPU-8086) 19 2.3.1. Cấu trúc của một hàng lệnh 19 2.3.2. Tên 19 2.3.3. Từ gợi nhớ mã lệnh, lệnh giả 20 2.3.4. Toán hạng và toán tử 27 2.4. Cấu trúc của chương trình hợp ngữ MASM 30 2.4.3. Tập tin thi hành dạng COM và dạng EXE 31 2.4.4. Ví dụ 32 2.5. Cách tạo chương trình hợp ngữ 33 ThS. Nguyễn Hứa Duy Khang i
- Lập trình Hệ Thống Chương 3 - TẬP LỆNH CPU-8086 ĐƠN GIẢN và KIỂU ĐỊNH VỊ 36 3.1. Tập lệnh của CPU-8086 36 3.1.1. Lệnh sao chép dữ liệu, địa chỉ: 36 3.1.2. Lệnh tính toán số học. 38 3.1.3. Nhóm lệnh logic và ghi dịch 39 3.1.4. Nhóm lệnh vào ra ngoại vi. 42 1.3.5. Nhóm lệnh hệ thống 43 3.2. Kiểu định vị 43 3.2.1. Định vị tức thì: 44 3.2.2. Định vị thanh ghi 44 3.1.3. Định vị trực tiếp (bộ nhớ): 44 3.1.4. Định vị gián tiếp thanh ghi 45 3.1.5. Định vị nền 45 3.1.6. Định vị chỉ số 46 3.1.7. Định vị chỉ số nền 46 3.1.8. Định vị chuỗi 46 3.1.9. Định vị cổng vào/ra 47 BÀI TẬP CHƯƠNG 3 48 Chương 4 - HỆ THỐNG NGẮT MỀM 50 4.1. Những cơ sở của ngắt mềm 50 4.2. Sử dụng ngắt trong hợp ngữ 50 4.3. Ngắt MS-DOS 51 4.4 Các ví dụ 56 Chương 5 - LỆNH NHẢY VÀ VÒNG LẶP 60 5.1. Lệnh nhảy (chuyển điều khiển) 60 5.1.1. Lệnh nhảy không điều kiện 60 5.1.2. Lệnh nhảy có điều kiện: 61 5.2. Vòng lặp 64 BÀI TẬP CHƯƠNG 5 66 Chương 6 - NGĂN XẾP VÀ CHƯƠNG TRÌNH CON 68 6.1. Ngăn xếp 68 6.1.1. Tổ chức và vận hành 68 6.1.2. Truy xuất ngăn xếp 69 6.2. Chương trình con 70 6.2.1. Khai báo chương trình con (Thủ tục) 70 6.2.2. Gọi thủ tục 71 6.3. Các ví dụ 71 BÀI TẬP CHƯƠNG 6 75 ThS. Nguyễn Hứa Duy Khang ii
- Lập trình Hệ Thống Chương 7 - XỬ LÝ KÝ SỐ VÀ XỬ LÝ CHUỖI 76 7.1. Xử lý ký tự 76 7.1.1. Nhập xuất số nhị phân (Binary) 76 7.1.2. Nhập xuất số thập lục phân (Hexa) 77 7.2. Lệnh xử lý chuỗi 78 7.2.1. Hướng xử lý chuỗi 79 7.2.2. Các tiền tố lập REP (Repeat) 79 7.2.3. Lệnh Ghi vào chuỗi 80 7.2.4. Lệnh Nạp từ chuỗi 81 7.2.5. Lệnh di chuyển chuỗi 81 7.2.6. Lệnh So sánh hai chuỗi 83 7.2.7. Lệnh dò tìm trong chuỗi 85 BÀI TẬP CHƯƠNG 7 87 Phụ lục 1 - Hướng Dẫn Sử Dụng Emu8086 88 Phụ lục 2 – Tập Lệnh Intel-8086 93 Phụ lục 3 – Bảng mã ASCII 117 ThS. Nguyễn Hứa Duy Khang iii
- Giới thiệu môn học GIỚI THIỆU MÔN HỌC I. MỤC ĐÍCH YÊU CẦU Môn Lập Trình Hệ Thống (CT143) cung cấp cho sinh viên những kiến thức cơ bản về lập trình hệ thống trên máy tính IBM/PC thông qua Hợp Ngữ (Assembly). Môn học này là nền tảng để tiếp thu hầu hết các môn học khác trong chương trình đào tạo. Mặt khác, nắm vững Hợp ngữ là cơ sở để phát triển các ứng dụng điều khiển thiết bị. Học xong môn này, sinh viên phải nắm được các vấn đề sau: - Tổ chức bộ xử lý Intel-8086 - Cấu trúc chương trình Hợp ngữ - Tập lệnh của Intel-8086 - Hệ thống ngắt mềm trên máy tính IBM/PC - Lệnh nhảy và vòng lập trong Assembly - Ngăn xếp và Thủ tục - Xử lý số và Chuỗi II. ĐỐI TƯỢNG MÔN HỌC Môn học được dùng để giảng dạy cho các sinh viên sau: - Sinh viên năm thứ 3 của các chuyên ngành Điện tử III. NỘI DUNG CỐT LÕI Giáo trình được cấu trúc thành 7 chương: Chương 1: Tổ chức bộ xử lý Intel-8086 Chương 2: Hợp ngữ Chương 3: Tập lệnh và Kiểu định vị Chương 4: Hệ thống ngắt mềm Chương 5: Lệnh nhảy và Vòng lập Chương 6: Ngăn xếp và Chương trình con Chương 7: Xử lý số và Chuỗi IV. KIẾN THỨC LIÊN QUAN Để học tốt môn Lập trình Hệ thống, sinh viên cần phải có các kiến thức nền tảng sau: - Kiến thức Kỹ thuật số. - Kiến thức Kiến trúc máy tính - Kiến thức Ngôn ngữ lập trình cấp cao: C, Pascal, Delphi - Kỹ năng thao tác sử dụng máy tính. 1
- Giới thiệu môn học V. DANH MỤC TÀI LIỆU THAM KHẢO [1] Nguyễn Văn Linh, Lâm Hoài Bảo, Dương Văn Hiếu, Giáo trình Lập trình căn bản A, Khoa Công Nghệ Thông Tin, Đại học Cần Thơ, 2005. [2] Nguyễn Đình Tê, Hoàng Đức Hải , Giáo trình lý thuyết và bài tập ngôn ngữ C; Nhà xuất bản Giáo dục, 1999. [3] Nguyễn Cẩn, C – Tham khảo toàn diện, Nhà xuất bản Đồng Nai, 1996. [4] Brain W. Kernighan & Dennis Ritchie, The C Programming Language, Prentice Hall Publisher, 1988. [5] Võ Văn Chín, Bài giảng Ngôn ngữ hệ thống, Khoa Công Nghệ Thông Tin, Đại học Cần Thơ, 1994. 2
- Tổ chức bộ xử lý Intel-8086 Chương 1 TỔ CHỨC BỘ XỬ LÝ INTEL-8086 Mục đích: - Cấu trúc bên trong CPU Intel-8086 - Tập thanh ghi - Tổ chức bộ nhớ và dữ liệu - Khái quát các bộ xử lý Intel khác như: 80386, 80486, Pentium 1.1. BỘ XỬ LÝ INTEL-8086 (CPU-8086) 1.1.1. Cấu trúc tổng quát Intel-8086 là một CPU 16 bit (bus dữ liệu ngoại có 16 dây). Nó được dùng để chế tạo các máy vi tính PC-AT đầu tiên của hãng IBM vào năm 1981. Trong thực tế, hãng IBM đã dùng CPU 8088 (là một dạng của CPU 8086 với bus số liệu giao tiếp với ngoại vi là 8 bit) để chế tạo máy vi tính cá nhân đầu tiên gọi là PC-XT. Cho đến nay CPU 8086 đã không ngừng cải tiến và đã trải qua các phiên bản 80186, 80286, 80386, 80486, Pentium (80586), Pentium Pro, Pentium MMX, Pentium II, III, 4. Các CPU trên tương thích từ trên xuống (downward compatible) nghĩa là tập lệnh của các CPU mới chế tạo gồm các tập lệnh của CPU chế tạo trưóc đó được bổ sung thêm nhiều lệnh mạnh khác. Cấu trúc tổng quát của CPU-8086 có dạng như hình 1.1, gồm 2 bộ phận chính là: Bộ thực hiện lệnh và bộ phận giao tiếp bus. 1. Bộ phận thực hiện lệnh (EU): Thi hành các tác vụ mà lệnh yêu cầu như: Kiểm soát các thanh ghi (đọc/ghi), giải mã và thi hành lệnh. Trong EU có bộ tính toán và luận lý (ALU) thực hiện được các phép toán số học và luận lý. Các thanh ghi đa dụng là các ô nhớ bên trong CPU chứa dữ liệu tương tự như ô nhớ trong bộ nhớ. Cờ cũng là một thanh ghi dùng để ghi lại trạng thái hoạt động của ALU. Thanh ghi lệnh chứa nội dung lệnh hiện tại mà CPU đang thực hiện. Các thanh ghi và bus trong EU đều là 16 bit. EU không kết nối trực tiếp với bus hệ thống bên ngoài. Nó lấy lệnh từ hàng chờ lệnh mà BIU cung cấp. Khi có yêu cầu truy xuất bộ nhớ hay ngoại vi thì EU yêu cầu BIU làm việc. BIU có thể tái định địa chỉ để cho phép EU truy xuất đầy đủ 1 MB (8086 có 20 đường địa chỉ ngoại). 2. Bộ giao tiếp bus (BIU): BIU thực hiện chức năng giao tiếp giữa EU với bên ngoài (Bộ nhớ, thiết bị ngoại vi ) thông qua hệ thống BUS ngoại (bus dữ liệu và bus địa chỉ). BIU thực hiện tất cả các tác vụ về bus mỗi khi EU có yêu cầu. Khi EU cần trao đổi dữ liệu với bên ngoài, BIU sẽ tính toán địa chỉ và truy xuất dữ liệu để phục vụ theo yêu cầu EU. Trong BIU có 5 thanh ghi CS, DS, ES, SS và IP chứa địa chỉ. Thanh ghi IP chứa địa chỉ của lệnh sẽ được thi hành kế tiếp nên gọi là con trỏ lệnh. Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 1
- Tổ chức bộ xử lý Intel-8086 EU và BIU liên lạc với nhau thông qua hệ thống bus nội. Trong khi EU đang thực hiện lệnh thì BIU lấy lệnh từ bộ nhớ trong nạp đầy vào hàng chờ lệnh (6 bytes). Do đó EU không phải đợi lấy lệnh từ bộ nhớ. Đây là một dạng đơn giản của cache để tăng tốc độ đọc lệnh. Hình 1.1: Sơ đồ khối của CPU 8086 1.1.2. Các thanh ghi của 8086 Thanh ghi (register) là thành phần lưu trữ dữ liệu bên trong CPU, mỗi thanh ghi có độ dài nhất định (16 bit hoặc 8 bit) và được nhận biết bằng một tên riêng. Tùy vào độ dài và chức năng mà thanh ghi có công dụng chứa dữ liệu hoặc kết quả của phép toán, hoặc là các địa chỉ dùng để định vị bộ nhớ khi cần thiết. Nội dung của thanh ghi được truy xuất thông qua tên riêng của nó, do đó tên thanh ghi là từ khóa quan trọng cần phải lưu ý trong lập trình. CPU-8086 có 16 thanh ghi, mỗi thanh ghi là 16 bit, có thể chia 4 nhóm sau: 1. Thanh ghi đoạn: Gồm 4 thanh ghi 16 bit: CS, DS, ES, SS. Đây là những thanh ghi dùng để chứa địa chỉ đoạn của các ô nhớ khi cần truy xuất. Mỗi thanh ghi đoạn quản lý 1 đoạn tối đa 64K ô nhớ trong bộ nhớ trong. Người sử dụng chỉ được phép truy xuất ô nhớ dựa vào địa chỉ tương đối. CPU (cụ thể là BIU) có nhiệm vụ chuyển đổi địa chỉ tương đối thành địa chỉ tuyệt đối để truy xuất vào ô nhớ tuyệt đối tương ứng trong bộ nhớ. (Xem phần tổ chức bộ nhớ) CS: Thanh ghi đoạn mã lệnh, lưu địa chỉ đoạn chứa mã lệnh chương trình của người sử dụng Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 2
- Tổ chức bộ xử lý Intel-8086 DS: Thanh ghi đoạn dữ liệu, lưu địa chỉ đoạn chứa dữ liệu (các biến) trong chương trình. ES: Thanh ghi đoạn dữ liệu thêm, lưu địa chỉ đoạn chứa dữ liệu thêm trong chương trình. SS: Thanh ghi đoạn ngăn xếp, lưu địa chỉ đoạn của vùng ngăn xếp. 15 0 CS Code Segment DS Data Segment ES Extra data Segment SS Stack Segment Thông thường bốn thanh ghi này có thể chứa những giá trị khác nhau, do đó chương trình có thể được truy cập trên bốn đoạn khác nhau và chương trình chỉ có thể truy cập cùng 1 lúc tối đa bốn đoạn. Mặc khác, đối với những chương trình nhỏ, chỉ sử dụng 1 đoạn duy nhất, khi đó cả bốn thanh ghi đều chứa cùng giá trị địa chỉ đoạn, gọi là đoạn chung. 2. Thanh ghi đa dụng (General Register): Bao gồm bốn thanh ghi đa dụng 16 bit (AX, BX, CX, DX). Mỗi thanh ghi đa dụng có thể được sử dụng với nhiều mục đích khác nhau, tuy nhiên từng thanh ghi có công dụng riêng của nó. 15 8 7 0 AH AL AX (Accumulator) BH BL BX (Base register) CH CL CX (Count register) DH DL DX (Data register) AX : Là thanh ghi tích lũy cơ bản. Mọi tác vụ vào/ra đều dùng thanh ghi này, tác vụ dùng số liệu tức thời, một số tác vụ chuỗi ký tự và các lệnh tính toán đều dùng thanh AX. BX: Thanh ghi nền dùng để tính toán địa chỉ ô nhớ. CX: Là thanh ghi đếm, thường dùng để đếm số lần trong một lệnh vòng lặp hoặc lệnh xử lý chuổi ký tự. DX: Thanh ghi dữ liệu, thường chứa địa chỉ của một số lệnh vào/ra, lệnh tính toán số học (kể cả lệnh nhân và chia). Mỗi thanh ghi 16 bit có thể chia đôi thành 2 thanh ghi 8 bit. Do đó, CPU-8086 có 8 thanh ghi 8 bit là: AH, AL; BH, BL; CH, CL; DH, DL (thanh ghi AH và AL tương ứng với byte cao và byte thấp của thanh ghi AX, tương tự cho các thanh ghi 8 bit còn lại). Ví dụ: AX = 1234h => AH = 12h, AL = 34h 3. Thanh ghi con trỏ và chỉ số (Pointer & Index register): Chức năng chung của nhóm thanh ghi này là chứa địa chỉ độ dời của ô nhớ trong vùng dữ liệu hay ngăn xếp. SI : Thanh ghi chỉ số nguồn DI : Thanh ghi chỉ số đích Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 3
- Tổ chức bộ xử lý Intel-8086 BP: Thanh ghi con trỏ nền dùng để lấy số liệu từ ngăn xếp. SP : Thanh ghi con trỏ ngăn xếp luôn chỉ vào đỉnh ngăn xếp. 15 0 SI Source Index Reg. DI Destination Index Reg. BP Base Pointer Reg. SP Stack Pointer Reg. SI và DI chứa địa chỉ độ dời của ô nhớ tương ứng trong đoạn có địa chỉ chứa trong DS hoặc ES (dữ liệu, còn gọi là Biến). Còn BP và SP chứa địa chỉ độ dời của ô nhớ tương ứng trong đoạn có địa chỉ chứa trong SS, dùng để thâm nhập số liệu trong ngăn xếp. 4. Thanh ghi Đếm chương trình và thanh ghi trạng thái (Cờ): 15 0 F Flag Register. IP Intrucstion Pointer Reg. • Thanh ghi con trỏ lệnh IP (còn gọi là PC – đếm chương trình) là thanh ghi 16 bit chứa địa chỉ của lệnh kế tiếp mà CPU sẽ thực hiện trong. Các lệnh của chương trình có địa chỉ đoạn trong CS. • Thanh ghi Cờ (F) dài 16 bit, mỗi bit là một cờ. Mỗi cờ có giá trị 1 (gọi là SET –Đặt) hoặc 0 (gọi là CLEAR – Xóa). Hình 1.2 mô tả 9 bit trong số 16 bit tương ứng với 9 cờ trạng thái (các bit còn lại dùng cho dự trữ mở rộng khi thiết kế các CPU khác) Thanh ghi cờ được chia thành hai nhóm: o Nhóm cờ điều khiển (bảng 1.1) bao gồm các cờ dùng để điều khiển sự hoạt động của CPU và giá trị của cờ được thiết lập bằng các lệnh phần mềm. o Nhóm cờ trạng thái (bảng 1.2) bao gồm các cờ phản ánh kết quả thực hiện lệnh cũng như trạng thái của CPU 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 O D I T S Z A P C Dự trữ Hình 1.2: Cấu trúc thanh ghi Cờ KÝ HIỆU TÊN Ý NGHĨA Nhóm cờ điều khiển TF Bẩy (Trap) TF = 1: cho phép chương trình chạy từng bước IF Ngắt (Interrupt) IF = 1: cho phép ngắt phần cứng Hướng DF DF = 1: thì SI và DI giảm 1 cho mỗi vòng lặp (Direction) Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 4
- Tổ chức bộ xử lý Intel-8086 Nhóm cờ trạng thái CF = 1: khi có số nhớ hoặc mượn từ MSB trong Số giữ CF phép cộng hoặc trừ. (Carry) (Có tthể bị thay đổi theo lệnh ghi dịch và quay) PF = 1: khi byte thấp của thanh ghi kết quả một phép PF Chẳn lẻ (Parity) tính có số lượng bit 1 chẳn Số giữ phụ AF = 1: khi có nhớ hoặc mượn từ bit 3 trong phép AF (Hafl) cộng hoặc trừ. Dùng trong các lệnh với số BCD ZF Zero ZF = 1: khi kết quả của một phép tính bằng 0 SF = 1 khi kết quả phép tính là âm (MSB=1). SF Dấu (Sign) SF = 0 khi kết quả dương (MSB=0) OF = 1: nếu kết quả vượt quá khả năng tính toán của OF Tràn (Overflow) CPU Bảng 1.1: Ý nghĩa cờ 1.1.3. Trạng thái tràn: Trạng thái tràn có thể không xảy ra (nếu không tràn) hoặc xảy ra (nếu tràn có dấu, tràn không dấu, đồng thời tràn có dấu và không dấu). Nói chung là có 2 trạng thái tràn: Tràn không dấu và Tràn có dấu. Lưu ý: Nếu một giá trị có MSB=1 (bit dấu) thì CPU luôn luôn cho đó là số có dấu. a. Tràn không dấu: CF=1 Ví dụ: ADD AX, BX ; với AX = 0FFFFh, BX = 1 - Nếu xem đây là các số không dấu thì AX không đủ chứa kết quả nên TRÀN không dấu, vậy CF = 1 - Nếu xem đây là các số có dấu thì kết quả sẽ là 0 (vì AX = -1) nên không tràn, do đó OF = 0 b. Tràn có dấu: OF = 1 Ví dụ: ADD AX, BX ; với AX = BX = 7FFFh = 32767 - Nếu xem đây là các số không dấu thì AX = 7FFFh + 7FFFh = 0FFFEh = 65534 nên không tràn. - Nếu xem đây là các số có dấu thì tràn vì kết quả vượt quá phạm vi cho phép đối với số có dấu (cộng 2 số dương, kết quả lại là số âm). Thật sự trong trường hợp này, CPU sẽ làm cho OF = 1 theo qui tắc "Nhớ ra và vào MSB xảy ra không đồng thời” nghĩa là có nhớ vào MSB nhưng không có nhớ ra hoặc ngược lại thì tràn và không có hoặc có nhớ ra và vào MSB thì không tràn. 1.2. BỘ NHỚ TRONG CỦA INTEL-80x86 1.2.1. Tổ chức dữ liệu Bộ nhớ trong được tổ chức thành mảng gồm các ô nhớ 8 bit liên tực nhau. Các dữ liệu có thể được ghi vào hoặc đọc ra (gọi là truy xuất) từ bất cứ vị trí ô nhớ nào. Mỗi ô nhớ 8 bit được phần cứng quản lý bằng một địa chỉ vật lý duy nhất. Việc truy xuất nội dung ô nhớ phải bằng địa chỉ vật lý này. Dữ liệu 8 bit được lưu trữ bằng một ô nhớ và địa chỉ của ô nhớ chính là địa chỉ dùng để truy xuất dữ liệu. Dữ liệu nhiều hơn 8 bit được lưu trữ bởi nhiều ô Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 5
- Tổ chức bộ xử lý Intel-8086 nhớ liên tục nhau. Theo quy ước Intel, byte dữ liệu cao được lưu ở ô nhớ có địa chỉ cao và byte dữ liệu thấp hơn lưu ở ô nhớ có địa chỉ thấp hơn. Khi đó, địa chỉ dùng để truy xuất dữ liệu là địa chỉ của ô nhớ thấp (ô nhớ chứa byte thấp nhất của dữ liệu) Hình 1.3 mô tả việc tổ chức các dữ liệu có độ dài khác nhau trong bộ nhớ. Giá trị 5Fh (1 byte) được lưu trữ ở địa chỉ 0010h. Giá trị 0A0B1h (2 byte) được lưu trữ bởi 2 ô nhớ có địa chỉ 0015h và 0016h, địa chỉ để truy xuất giá trị này là 0015h. Còn giá trị 0A2B1C0h (3 byte) được lưu trữ bởi 3 ô nhớ 0012h, 0013h và 0014h, do đó địa chỉ truy xuất giá trị ấy là 0012h. Bộ nhớ Địa chỉ (A0h là byte cao, B1h là byte thấp) A0h 0016h Giá trị: 0A0B1h → B1h 0015h A2h 0014h (C0h byte thấp nhất, A2h byte cao nhất) B1h 0013h Giá trị: 0A2B1C0h → C0h 0012h 0011h Giá trị: 5Fh → 5Fh 0010h Hình 1.3: Tổ chức dữ liệu trong bộ nhớ 1.2.2. Sự phân đoạn bộ nhớ trong CPU 8086 có không gian địa chỉ là 1MB (ứng với 20 bit địa chỉ) Vậy CPU 8086 có thể quản lý bộ nhớ trong là 220 = 1MB. Bộ nhớ 1 MB này được CPU-8086 quản lý bằng nhiều đoạn 64 KB. Các đoạn có thể tách rời hoặc có thể chồng lên nhau. Mỗi đoạn có một địa chỉ đoạn 16 bit duy nhất, tùy vào mục đích sử dụng đoạn mà địa chỉ đoạn được lưu trữ trong thanh ghi đoạn tương ứng. Đối với người lập trình, Địa chỉ của ô nhớ trong bộ nhớ được xác định bởi hai thông số 16 bit (gọi là địa chỉ logic): Địa chỉ Đoạn (segment) và địa chỉ độ dời (offset). Cách viết: Segment : Offset Địa chỉ vật lý của ô nhớ khi truy xuất sẽ được BIU tự động chuyển đổi từ địa chỉ logic bằng cách dịch trái thanh ghi đoạn bốn bit (tức nhân nội dung của thanh ghi đoạn cho 16) rồi cộng với địa chỉ độ dời. Vì vậy, người lập trình không cần địa chỉ vật lý của ô nhớ mà chỉ cần biết địa chỉ logic của ô nhớ. Ví dụ: đoạn CS có giá trị là 1002h, địa chỉ độ dời của ô nhớ K trong đoạn CS là 500h (CS:0500h hoặc 1002h:0500h). Khi đó, địa chỉ vật lý của ô nhớ K được tính như sau: 10020h (dịch trái địa chỉ đoạn 4 bit) + 0500h (độ dời) 10520h (địa chỉ vật lý) Trong ví dụ trên, đoạn CS có điểm bắt đầu ở địa chỉ vật lý 10020h. Độ dời 500h là khoảng cách từ địa chỉ của điểm bắt đầu của đoạn CS đến ô nhớ K (xem hình 1.4) Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 6
- Tổ chức bộ xử lý Intel-8086 Bộ nhớ Địa chỉ vật lý 10521h Ô nhớ K → 10520h ← Độ dời 500h tính từ trong đoạn CS (CS:500h) 1051Fh điểm đầu đoạn CS - - - - - - - - - - - - Ô nhớ có độ dời 05h → 10025h 501h ô nhớ 10024h 10023h Ô nhớ có độ dời 01h → 10022h 10021h Ô nhớ có độ dời 0h → 10020h ← Điểm đầu đoạn CS trong đoạn CS (CS:00h) 1001Fh Hình 1.4: Địa chỉ vật lý của ô nhớ K trong đoạn CS Khi truy xuất ô nhớ, BIU lấy sẽ sử dụng địa chỉ đoạn trong thanh ghi đoạn tương ứng với tính chất của ô nhớ cần truy xuất: - Ô nhớ là Code (Mã lệnh) thì đoạn tương ứng là CS. - Ô nhớ là Data (dữ liệu) thì đoạn tương ứng là DS. - Ô nhớ nằm trên ngăn xếp thì dùng đoạn SS. - Khi truy xuất chuỗi, DI và SI luôn chứa độ dời của ô nhớ trong đoạn DS hay ES Khi khởi động, CPU 8086 nhảy đến địa chỉ vật lý cao nhất của bộ nhớ trong (đoạn CS = 0FFFFh và độ dời 0) để lấy lệnh. Địa chỉ này ứng với địa chỉ của ROM- BIOS của bộ nhớ trong nơi chứa chương trình khởi động máy tính. 1.3. Địa chỉ các ngoại vi Các ngoại vi đều có địa chỉ riêng từ 0 đến 64K. CPU 8086 dùng các lệnh riêng biệt để truy xuất ngoại vi và bộ nhớ trong. Muốn truy xuất ngoại vi, BIU chỉ cần đưa địa chỉ của ngoại vi lên 16 bit thấp của bus địa chỉ (không có đoạn). Memory I/O 1 MByte 64 kByte Intel-8086 Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 7
- Tổ chức bộ xử lý Intel-8086 Hình 1.5: Cấu trúc đơn giản của máy tính 1.4. CÁC BỘ XỬ LÝ INTEL KHÁC Ngoài CPU-8086, Intel đã cho ra đời thế hệ CPU mới hơn, nhiều tính năng hơn và mạnh hơn như: 80186, 80286, 80386, 80486, Celeron và Pentium (80586). Ngày nay, sức mạnh và tính năng của CPU Intel tăng vượt bậc nhờ công nghệ mới như: Centrino, Hyper Threading, Core Duo. Bắt đầu từ CPU 80286, hãng Intel đã đưa vào một số cải tiến có ý nghĩa như tăng bus địa chỉ lên 24 bit và có thể vận hành với chế độ bảo vệ (protected mode). Chế độ này cho phép CPU 80286 vận hành trong một hệ điều hành đa nhiệm (multitasking). 1.4.1. Bộ xử lý 80386 Hãng Intel đã thành công lớn khi chế tạo CPU 80386. Đây vẫn còn là một CPU CISC thuần túy có bus địa chỉ 32 bit và bus số liệu 32 bit (ta gọi CPU 80386 là một CPU 32 bit). Các thanh ghi của CPU 80386 đều là thanh ghi 32 bit (Hình 1.5). Một số thanh ghi đa dụng có thể chia thành thanh ghi 16 bit hoặc chia thành thanh ghi 8 bit để đảm bảo tính tương thích với các CPU chế tạo trước đó. Với bus địa chỉ 32 bit, không gian địa chỉ của CPU 80386 là 4 GB tức 4096 MB. CPU 80386 có 64K cửa vào/ra 8 bit, 16 bit và 32 bit. CPU 80386 cũng có thể hoạt động với bộ đồng xử lý toán học 80387 (math coprocessor). Bộ đồng xử lý toán học dùng xử lý các phép tính trên các số có dấu chấm động (số lẻ). I.4.2. Tập thanh ghi của bộ xử lý 80386: Hình 1.6 mô tả đầy đủ tập thanh ghi của CPU-80386. Các thanh ghi đa dụng và thanh ghi con trỏ được mở rộng thành thanh ghi 32 bit được gọi tên là: EAX, EBX, ESP, EDI . Tuy nhiên ta vẫn có thể sử dụng các thanh ghi 16 bit (AX, BX, ) hoặc 8 bit (AH, AL, BH, BL ) giống như các thanh ghi 16 bit hoặc 8 bit của bộ xử lý 8086. Chiều dài các thanh ghi đoạn vẫn giữ nguyên 16 bit nhưng có thêm hai thanh ghi đoạn thêm là FS và GS. Các thanh ghi FS và GS được dùng giống như thanh ghi ES. Nghĩa là CPU‐80386 quản lý được bốn đoạn dữ liệu. Thanh ghi trạng thái SR (Status register) và thanh ghi đếm chương trình PC (program counter) cũng được nâng lên 32 bit. Ngoài các bit trạng thái đã thấy trong thanh ghi trạng thái của CPU-8086 (C, Z, S, ) thanh ghi trạng thái của CPU-80386 còn có thêm các bit trạng thái như sau: • IOP (Input/Output protection: bảo vệ vào/ra): Đây là hai bit trạng thái dùng trong chế độ bảo vệ để xác định mức ưu tiên mà một tiến trình phải có để có thể thâm nhập một vùng vào ra. Chỉ hệ điều hành mới có quyền dùng các bit này. • N (Nested task: tiến trình lồng vào nhau): Trong chế độ bảo vệ, các hệ điều hành dùng bit này để biết có nhiều tiến trình đang vận hành và ít nhất có một tiến trình đang bị gián đoạn. • R (Resume: tải trục): Bit này cho phép một tiến trình được tiếp tục vận hành lại sau khi bị gián đoạn. Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 8
- Tổ chức bộ xử lý Intel-8086 • V (Virtual 8086 mode: chế độ 8086 ảo): Bit này cho phép 80386 đang vận hành ở chế độ bảo vệ, chuyển sang chế độ 8086 ảo. 31 16 15 8 7 0 EAX AH AL EBX BH BL ECX CH CL EDX DH DL ESP SP EBP BP ESI SI EDI DI ESR SR EPC PC CS DS SS ES FS GS Hình 1.6a: Thanh ghi đa dụng và thanh ghi con trỏ 15 0 31 0 19 0 TR LDTR IDTR GDTR Hình 1.6b: Thanh ghi quản lý bộ nhớ 31 16 15 0 31 16 15 0 CR3 DR7 CR2 DR6 CR1 DR5 CR0 DR4 Hình 1.6c: Thanh ghi điều khiển DR3 31 16 15 0 DR2 TR7 DR1 TR6 DR0 Hình 1.6d: Thanh ghi kiểm tra Hình 1.6e: Thanh ghi gỡ rối Hình 1.6: Các thanh ghi của CPU 80386 1.4.3. Các chế độ vận hành của bộ xử lý 80386 CPU-80386 có thể vận hành theo một trong ba chế độ khác nhau: chế độ thực (real mode), chế độ bảo vệ (protected mode) và chế độ 8086 ảo (virtual 8086 mode). Chế độ vận hành của CPU phải được thiết lập trước bằng phần cứng. Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 9
- Tổ chức bộ xử lý Intel-8086 • Chế độ thực: chế độ thực của bộ xử lý 80386 hoàn toàn tương thích với chế độ vận hành của bộ xử lý 8086. Trong chế độ này, không gian địa chỉ của 80386 bị giới hạn ở mức 220 = 1MB giống như không gian địa chỉ của 8086 mặc dù bus địa chỉ của 80386 có 32 đường dây. • Chế độ bảo vệ: (Còn gọi là chế độ đa nhiệm) chế độ bảo vệ đã được đầu tiên đưa vào bộ xử lý 80286. Chế độ này cho phép bộ xử lý 80386 dùng hết không gian địa chỉ của nó là 232 = 4096 MB và cho phép nó vận hành dưới một hệ điều hành đa nhiệm. Trong hệ điều hành đa nhiệm, nhiều tiến trình có thể chạy đồng thời và được bảo vệ chống lại các thâm nhập trái phép vào vùng ô nhớ bị cấm. Trong chế độ bảo vệ, các thanh ghi đoạn không được xem như địa chỉ bắt đầu của đoạn mà là thanh ghi chọn (selector) gán các ưu tiên khác nhau cho các tiến trình. Phần ưu tiên khác nhau cho các tiến trình. Phần cốt lõi của hệ điều hành có ưu tiên cao nhất và người sử dụng có ưu tiên thấp nhất. • Chế độ 8086 ảo: Chế độ này cho phép thiết lập một kiểu vận hành đa nhiệm trong đó các chương trình dùng trong chế độ thực, có thể chạy song song với các tiến trình khác. 1.4.4. Bộ xử lý Intel 80486: CPU-80486DX được phát hành năm 1989. Đó là bộ xử lý 32bit chứa 1.2 triệu transistor. Khả năng quản lý bộ nhớ tối đa giống như 80386 nhưng tốc độ thi hành lệnh đạt được 26.9 MIPS (Mega Instructions Per Second - triệu lệnh mỗi giây) tại xung nhịp 33 MHz Nếu bộ xử lý 80386 là bộ xử lý CISC thuần túy với bộ đồng xử lý toán học 80387 nằm bên ngoài bộ xử lý 80386, thì bộ xử lý 80486 là một bộ xử lý hỗn tạp CISC và RISC với bộ đồng xử lý toán học và với 8K cache nằm bên trong bộ xử lý 80486. Trong bộ xử lý 80486, một số lệnh thường dùng, ví dụ như lệnh MOV, dùng mạch điện (kỹ thuật RISC) để thực hiện lệnh thay vì dùng vi chương trình như trong các CPU CISC thuần túy. Như thế thì các lệnh thường dùng này được thi hành với tốc độ nhanh hơn. Kỹ thuật ống dẫn cũng được đưa vào trong bộ xử lý 80486. Với các kỹ thuật RISC được đưa vào, bộ xử lý 80486 nhanh hơn bộ xử lý 80386 đến 3 lần (nếu tốc độ xung nhịp là như nhau). Bộ xử lý 80486 hoàn toàn tương thích với 2 bộ xử lý 80386 và 80387 cộng lại và như thế nó có các chế độ vận hành giống như 80386. Bộ xử lý 80486 tỏ ra rất mạnh đối với các chương trình cần tính toán nhiều và các chương trình đồ họa, vì bộ đồng xử lý toán học nằm ngay trong bộ xử lý 80486. Hàng chờ lệnh của bộ xử lý 80486 là 32 byte. Hình 1.7: CPU-80386 Hình 1.8: CPU-80486 Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 10
- Tổ chức bộ xử lý Intel-8086 1.4.5. Bộ xử lý Intel PENTIUM: Được đưa ra thị trường vào giữa năm 1993, các bộ xử lý Pentium được chế tạo với hơn 3 triệu transistor, thụ hưởng các tính năng kỹ thuật của các bộ xử lý 80486 DX/2 và được có thêm nhiều tính năng mới. Theo hãng sản xuất Intel, nếu hoạt động ở với xung nhịp 66 MHz thì tốc độ thi hành lệnh của Pentium là 112 MIPS thay vì 54 MIPS cho bộ xử lý 80486 DX/2 cùng xung nhịp. Các tính năng nổi bật của bộ xử lý Pentium là : • Hoàn toàn tương thích với các bộ xử lý được chế tạo trước đó (8086, 80286, 80386, 80486). • Dùng kỹ thuật ống dẫn tốt hơn với 2 ống dẫn số nguyên độc lập và một ống dẫn số lẻ. Kỹ thuật siêu vô hướng và tiên đoán lệnh nhảy cũng được đưa vào. • Dùng cache lệnh và cache dữ liệu riêng biệt. • Bus số liệu là 64 bit với cách vận chuyển theo từng gói. • Dùng cách quản lý hệ thống cho phép tiết kiệm năng lượng tiêu hao trong bộ xử lý Pentium. • Có tối ưu hóa các chuỗi mã lệnh. Petium MMX: Các lệnh xử lý multimedia được đưa vào tập lệnh của CPU nên việc thi hành chương trình multimedia được cải thiện rất nhiều. Pentium Celeron Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 11
- Tổ chức bộ xử lý Intel-8086 Hình 1.9: Hình ảnh các loại bộ xử lý Intel Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 12
- Tổ chức bộ xử lý Intel-8086 BÀI TẬP CHƯƠNG 1 1. Chọn các thanh ghi đa dụng để lưu trữ các dữ liệu sau đây, sao cho mỗi thanh ghi lưu trữ 1 giá trị và không trùng nhau (Giải thích việc chọn thanh ghi): 15h, 0AFh, 01234h, 230, 257, ‘H’, 8086. Ghi chú: Số có tận cùng bằng h (hay H) là số thập lục phân (Hexa); ‘H’ : Ký tự H 2. Các thanh ghi đang lưu trữ giá trị như sau: AH = 11h AL = 22h CL = 15 CH = 10 BX = 0A1D4h DX = 8086 Hãy cho biết giá trị thập lục phân của những thanh ghi sau và giải thích: AX, CX, BH, BL, DH, DL 3. Mô tả các cách có thể sử dụng được để lưu trữ giá trị vào thanh ghi sau: a. 1234h vào thanh ghi SI b. 5678h vào thanh ghi AX c. 100 vào thanh ghi DI d. 100 vào thanh ghi DX 4. Sử dụng mô hình bộ nhớ gồm 17 ô nhớ như hình A1 để ghi các dữ liệu sau đây vào bộ nhớ sao cho các giá trị không chồng lên nhau (sinh viên tự chọn địa chỉ ô nhớ để lưu trữ): 15h, 0AFh, 01234h, 230, 257, ‘H’, 8086, 3A4B5h, 0F1D2E3h Ô nhớ Địa chỉ 00010h 00002h 00001h 00000h Hình A1: Mô hình bộ nhớ 5. Với mô hình bộ nhớ kết quả của câu 4, hãy cho biết giá trị dữ liệu 8/16/24/32 bit tại mỗi địa chỉ sau đây ở dạng thập lục phân: a. 00004h b. 00008h c. 0000Bh d. 0000Dh 6. Đổi sang địa chỉ vật lý tương ứng với mỗi địa chỉ logic sau: a. 0000:0001h b. 0100:1234h c. ABCD:3AFFh d. AF70:00CFh 7. Viết ra 4 địa chỉ logic khác nhau đối với mỗi địa chỉ vật lý sau: a. 40000h b. 0D32FCh 8. Tìm tất cả các địa chỉ logic khác nhau có thể có của mỗi ô nhớ có địa chỉ vật lý sau đây: a. 00000h b. 0000Fh c. 00010h d. 0001Fh Có nhận xét gì về các kết quả trên? 9. Cho một chương trình bao gồm 100 byte lệnh (Code), 200 byte dữ liệu (Data) và 16 KB ngăn xếp (Stack). Vẽ hình mô tả tổ chức vùng nhớ của chương trình trên Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 13
- Tổ chức bộ xử lý Intel-8086 trong bộ nhớ có mô hình như hình A2 theo hai cách sau (sinh viên tự gán địa chỉ vật lý và logic thích hợp với đầu và cuối cho từng vùng): a. Dùng chung 1 đoạn duy nhất cho cả 3 vùng Code, Data và Stack b. Dùng 3 đoạn riêng biệt không chồng nhau cho Code, Data, Stack Địa chỉ logic Ô nhớ Địa chỉ vật lý .: . . : .: . .: . .: . Hình A2: Mô hình tổ chức bộ nhớ 10. Bằng mô hình bộ nhớ kết quả của câu 9a, hãy thiết lập giá trị các thanh ghi sao cho CPU-8086 truy xuất được những ô nhớ trong mỗi trường hợp sau: a. Byte lệnh đầu tiên b. Byte lệnh thứ 20 c. Byte dữ liệu đầu tiên d. Byte dữ liệu thứ 10 Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 14
- Hợp Ngữ Chương 2 HỢP NGỮ Mục Đích - So sánh ngôn ngữ máy và hợp ngữ - Lệnh giả của MASM - Các cấu trúc chương trình Hợp ngữ - Cách tạo chương trình hợp ngữ 2.1. NGÔN NGỮ MÁY VÀ HỢP NGỮ Chương trình là một tập hợp các lệnh được đưa vào bộ nhớ trong của máy tính để bộ xử lý thực hiện. Các lệnh có thể được thể hiện ở những dạng (ngôn ngữ) khác nhau. Bộ xử lý hoạt động dựa trên kỹ thuật số nên chỉ hiểu được những giá trị nhị phân (để đơn giản, giá trị nhị phân còn được viết thành giá trị thập lục phân). Do đó, ngôn ngữ mà CPU hiểu được ấy gọi là ngôn ngữ máy (Machine language). Mỗi bộ xử lý có tập giá trị phân trong đó mỗi giá trị nhị phân sẽ điều khiển CPU thực hiện một tác vụ (gọi là mã lệnh), tập hợp các mã lệnh nhị phân ấy gọi là tập lệnh. Những bộ xử lý khác nhau sẽ có tập lệnh khác nhau, do đó ngôn ngữ máy của CPU nào thì chỉ thực hiện được trên CPU đó. Bảng 2.1 trình bày đoạn chương trình ngôn ngữ máy viết cho họ Intel-8086. Thứ tự lệnh Giá trị thập lục phân Mã lệnh nhị phân 1 B4 09 10110100 00001001 2 BA 03 01 10111010 00000011 00000001 3 40 01000000 Bảng 2.1: Đoạn chương trình ngôn ngữ máy họ Intel-80x86 Đối với CPU có kiến trúc CISC, chiều dài các lệnh có thể khác nhau do đó trong đoạn chương trình trên gồm 3 lệnh, có chiều dài lần lượt là 2 byte, 3 byte và 1 byte. Byte đầu tiên của mỗi lệnh là Tác vụ (Op-Code) mà CPU phải thực hiện còn các byte còn lại là Tác tử (Operand) xác định dữ liệu hoặc nơi chứa dữ liệu mà lệnh tác động vào. Để có thể lập trình với ngôn ngữ máy này, người lập trình phải hiểu rõ tổ chức phần cứng của máy đang sử dụng. Vì là ngôn ngữ riêng của CPU và được CPU thực hiện ngay khi đọc được lệnh nên chương trình viết bằng ngôn ngữ máy thực hiện rất nhanh và chiếm ít bộ nhớ trong. Tuy nhiên, dạng nhị phân của ngôn ngữ máy rất khó nhớ dễ nhầm lẫn nên khó viết. Để khắc phục nhược điểm khó nhớ của dạng nhị phân, người ta dùng những từ ngữ dễ nhớ để thay thế cho những mã lệnh nhị phân (gọi là từ gợi nhớ mã lệnh – mnemonic). Chương trình viết bằng Từ gợi nhớ mã lệnh gọi là Hợp Ngữ (Assembly). Mỗi mã lệnh nhị phân sẽ có một lệnh tương ứng trong Hợp ngữ và mỗi CPU khác nhau sẽ có Hợp ngữ khác nhau. Các tài liệu tham khảo về tập lệnh của CPU thường cung cấp cho lập trình viên tập lệnh của CPU ở dạng Hợp Ngữ. Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 15
- Hợp Ngữ Bảng 2.2 viết lại đoạn chương trình trong bảng 2.1 ở dạng Hợp ngữ. Qua đó người đọc có thể hiểu được phần nào chức năng của mỗi dòng lệnh trong đoạn chương trình đó thông qua lệnh Hợp ngữ. Thứ tự lệnh Giá trị thập lục phân Hợp Ngữ Ý nghĩa 1 B4 09 MOV AH, 09h AH ← 09h 2 BA 03 01 MOV DX, 0103h DX ← 0103h 3 40 INC AX AX ← AX + 1 Bảng 2.1: Đoạn chương trình Hợp ngữ cho họ Intel-80x86 Như vậy, Hợp ngữ sẽ làm cho lập trình viên dễ dàng hơn trong việc viết chương trình nhưng CPU thì không hiểu được những từ gợi nhớ mã lệnh đó. Do đó, từng lệnh trong chương trình viết bằng hợp ngữ phải được dịch sang ngôn ngữ máy tương ứng (hình 2.1). Chương trình làm nhiệm vụ này gọi là Trình hợp dịch (Assembler) mov ax,bx 010101010 add dx,cx 110101010 sub al,bl Trình hợp dịch 101010101 cmp cx,0 010101010 ja nhan 010101010 H ợ p ng ữ Ngôn ngữ máy (Trình nguồn) (Trình đích) Hình 2.1: Hợp ngữ và Ngôn ngữ máy Khi mới ra đời, các chương trình hợp ngữ chỉ làm việc đơn thuần là dịch những từ gợi nhớ mã lệnh sang mã máy nhưng dần dần các trình hợp dịch bổ sung thêm các lệnh riêng của trình hợp dịch cho phép dùng các nhãn, các ký hiệu, biến đổi dạng lệnh, khai báo biến, phân phối bộ nhớ, macro nhằm giúp cho người lập trình viết chương trình hợp ngữ dễ dàng hơn, các lệnh riêng đó gọi là lệnh giả (pseudo code). Các lệnh giả không có mã máy nhị phân tương ứng nên bản thân các lệnh giả không điều khiển CPU thực hiện tác vụ mà chỉ dùng để hướng dẫn trình hợp dịch trong quá trình dịch chương trình. Do đó, khi gặp từ gợi nhớ mã lệnh, trình hợp dịch sẽ dịch sang mã máy nhị phân; còn khi gặp lệnh giả, trình hợp dịch không dịch thành mã nhị phân. 2.2. ĐẶC TÍNH TỔNG QUÁT CỦA HỢP NGỮ 2.2.1. Cấu trúc của một dòng lệnh hợp ngữ. Đối với hợp ngữ, trên một dòng văn bản chỉ cho phép viết một dòng lệnh duy nhất. Hình 2.2 trình bày bốn thành phần có thể có trong cấu trúc của dòng lệnh hợp ngữ. Tên Mã lệnh Toán hạng Chú thích Hình 2.2: Cấu trúc dòng lệnh hợp ngữ Bốn thành phần của dòng lệnh hợp ngữ được sắp xếp theo thứ tự trên một hàng lệnh và được phân cách nhau bằng một ký tự đặc biệt gọi là ký tự ngăn cách (delimiter). Các ký tự ngăn cách có thể gồm: Khoảng trống, hai chấm, chấm phẩy, dấu Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 16
- Hợp Ngữ phẩy, dấu hỏi tùy theo hợp ngữ. Chính các ký tự ngăn cách này giúp cho trình hợp dịch phân biệt được các vùng khác nhau trong dòng lệnh. Vì vậy, khi khảo sát một hợp ngữ nào đó, chúng ta phải chú ý và sử dụng đúng các ký tự ngăn cách. 1. Tên (name) Vùng tên cho phép gán tên cho một địa chỉ (nhãn) hay một dữ liệu (Biến, hằng). Khi đó ta có thể sử dụng tên này để thay thế địa chỉ hay dữ liệu khi tham khảo đến địa chỉ hay dữ liệu ấy. Mỗi tên chỉ được thay thế cho duy nhất một địa chỉ hoặc một trong chương trình và được đặt theo quy cách của trình hợp dịch. 2. Mã lệnh Đây là vùng duy nhất không thể thiếu được của hàng lệnh, có thể chứa một từ gợi nhớ mã lệnh hoặc một lệnh giả. - Từ gợi nhớ mã lệnh được trình bày ở chương 3 (Tập lệnh CPU-8086). - Mỗi trình hợp dịch có thể xây dựng tập lệnh giả riêng, nên trong phần 2.3 sẽ trình bày các lệnh giả thường dùng của trình hợp dịch MASM. 3. Toán hạng: Chứa các toán hạng mà lệnh cần. Số toán hạng tùy vào mã lệnh 4. Chú thích: Dùng để ghi chú, giải thích cho dòng lệnh. 2.2.2. Macro Macro là một nhóm lệnh nào đó được dùng nhiều lần trong cùng một chương trình nên ta gán cho nó một tên. Mỗi khi sử dụng nhóm lệnh ấy chỉ cần gọi tên đã gán cho nhóm lệnh đó. 2.2.3. Chương trình con Hợp ngữ thường cho phép dịch riêng biệt các chương trình con, nó sẽ đánh dấu các tham khảo đến chương trình con trong chương trình chính và chương trình liên kết (linker) sẽ gán các địa chỉ của các chương trình con. Một số hợp ngữ còn cho phép làm một thư viện chương trình con để sử dụng chung cho nhiều chương trình khác nhau. Muốn sử dụng chương trình con thì phài dùng lệnh CALL hay lệnh JUMP để chuyển điều khiển đến chương trình con đó. Do đó phải lưu địa chỉ trở về chương trình chính ở ngăn xếp và làm chậm đi việc thực hiện chương trình chính. Đối với macro, thì mổi lần chương trình chính gọi macro để thực hiện thì toàn bộ nhóm lệnh trong macro được xen vào ngay điểm gọi, không cần dùng lệnh CALL hay JUMP, nên chương trình chính được thực hiện nhanh hơn . Tuy nhiên mỗi lần gọi macro thì đoạn mã lệnh trong macro được xen vào chương trình chính làm cho chương trình chính ngày càng dài ra và chiếm nhiều ô nhớ trong hơn. Chương trình con chỉ chiếm một vùng ô nhớ nhất định. Khi chương trình chính gọi nó thì chương trình chính lưu trữ địa chỉ trở về, nhảy đến địa chỉ bắt đầu của chương trình con để thực hiện chương trình này và khi thực hiện xong thì lấy lại địa chỉ trở về để tiếp tục thực hiện chương trình chánh. Dùng chương trình con ít chiếm bộ nhớ trong. Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 17
- Hợp Ngữ Sử dụng Chương trình con Sử dụng Macro CT con A → Lệnh 1 Lệnh 1 ← Macro A Lệnh 2 Lệnh 2 Lệnh 3 Lệnh 3 Lệnh 4 Lệnh 4 CT chính → Lệnh i Lệnh i ← CT chính Gọi CT con A→ CALL A -Lệnh 1 ← Gọi MacroA Lệnh ii -Lệnh 2 Gọi CTC A→ CALL A -Lệnh 3 Lệnh iii -Lệnh 4 Lệnh ii -Lệnh 1 ← Gọi MacroA -Lệnh 2 -Lệnh 3 -Lệnh 4 Lệnh iii Dài hơn!!! Hình 2.3: So sánh chương trình dùng Chương trình con và Macro Trước đây, do bộ nhớ trong của máy tính còn hạn hẹp và tốc độ chưa cao nên việc dùng macro hay chương trình con được xem xét rất cẩn thận đảm bảo được chương trình ngắn và hoạt động không chậm. Ngày nay, dung lượng bộ nhớ trong khá lớn và với tốc độ nhanh của bộ xử lý đã làm cho người lập trình thoải mái hơn trong việc sử dụng macro hay chương trình con. 2.2.4. Biến toàn cục (global), biến địa phương (local) Các biến được khai báo trong chương trình chính được gọi là biến toàn cục. Các biến này có thể dùng cho chương trình chính, trong macro và các chương trình con. Các biến được khai báo bên trong macro hay chương trình con được gọi là biến địa phương và chỉ được dùng cho nội bộ một macro hoặc chương trình con. Nói cách khác, nếu có 2 biến cùng tên được khai báo ở 2 chương trình con khác nhau là 2 biến hoàn toàn khác nhau. Việc hiểu biết cặn kẽ về biến toàn cục và địa phương giúp cho người lập trình quản lý biến và sử dụng biến hiệu quả hơn, tránh trường hợp không bị trùng lấp khi sử dụng tên biến trong chương trình lớn. 2.2.5. Các bảng, thông báo: Đa số các trình hợp ngữ khi tiến hành hợp dịch có thể cung cấp các bảng và thông báo cho người lập trình. Các bảng thông báo được cung cấp dưới dạng tập tin văn bản, bao gồm các bảng như sau: ¾ Liệt kê chương trình hợp ngữ và mã máy tương ứng. ¾ Liệt kê các lỗi trong chương trình gốc. ¾ Liệt kê các tên được dùng trong chương trình gốc. ¾ Danh sách các tham khảo ở chương trình khác, bên ngoài chương trình (chương trình con, biến dùng ở bên ngoài) ¾ Các macro, chương trình con và độ dài của chúng Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 18
- Hợp Ngữ 2.2.6. Hợp ngữ chéo (cross assembler) Một hợp ngữ chạy trên một máy tính nào đó để dịch ra mã máy cho chương trình viết phục vụ một CPU khác chủng loại với CPU của máy tính mà hợp ngữ đó đang dùng thì được gọi là hợp ngữ chéo. Ví dụ, hiện nay rất khó tìm được một máy tính dùng CPU-Z80. Muốn dịch một chương trình hợp ngữ P1 thành chương trình mã máy P2 dùng cho CPU-Z80, người ta phải dùng hợp ngữ chéo chạy trên máy IBM-PC (có CPU-8086) thông dụng. Chương trình P2 không chạy được trên máy IBM-PC mà chỉ chạy được trên máy tính hoặc hệ vi xử lý do CPU-Z80 điều khiển. 2.3. HỢP NGỮ MASM (HỢP NGỮ CỦA CPU-8086) MASM (Microsoft Macro Assembler) là trình hợp ngữ do hãng phần mềm Microsoft phát triển cùng với phiên bản hệ điều hành DOS. Ngoài ra, hãng Borland – chuyên xây dựng các chương trình dịch – cũng phát hành chương trình dịch hợp ngữ gọi là TASM (Turbo Assembler). Các phiên bản này chỉ cho phép viết chương trình trên hệ điều hành DOS, cho nên không viết được chương trình cho Windows bằng các phiên bản này. Hiện nay, đã có các phiên bản cho phép viết chương trình trên Windows, như MASM32 (MASM 32 bits). Ta dùng các từ gợi nhớ mã lệnh, các lệnh giả, các ký hiệu do trình hợp ngữ MASM qui định để viết ra một chương trình mà ta gọi là chương trình hợp ngữ nguồn (source file). Chương trình nguồn được lưu trữ trong đĩa từ dưới một tên tập tin có đuôi là ASM. MASM sẽ dịch chương trình nguồn thành chương trình đối tượng có đuôi OBJ (Object file). Chương trình đối tượng sẽ được liên kết (LINK) thành chương trình có thể chạy được có đuôi là EXE (Executive file). Các loại hợp ngữ khác nhau đều có cú pháp giống nhau, nhưng cũng có những đặc điểm riêng thể hiện khả năng mạnh mẽ của nó. Sau đây chúng ta nghiên cứu các qui định, các cú pháp thường dùng cho việc viết một chương trình hợp ngữ. 2.3.1. Cấu trúc của một hàng lệnh : Một hàng lệnh gồm có bốn thành phần: Từ gợi nhớ mã lệnh Toán hạng hoặc Tên Ghi chú hoặc lệnh giả biểu thức Hình 2.4: Cấu trúc dòng lệnh hợp ngữ MASM Ví dụ: BDAU: MOV DX, 3F8h ; 3F8H là địa chỉ cổng vào ra nối tiếp Trong đó: BDAU – Tên với vai trò là nhãn : – (Dấu 2 chấm) phân cách Tên và Từ gợi nhớ MOV – Từ gợi nhớ mã lệnh DX, 3F8h – Hai toán hạng, phân cách bằng dấu phẩy 3F8H là địa chỉ cổng vào ra nối tiếp – Câu chú thích ; – (Dấu ; ) Phân cách Toán hạng và Chú thích 2.3.2. Tên: Tên có thể là nhãn, biến hay ký hiệu (hằng). Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 19
- Hợp Ngữ Tên có chiều dài tối đa là 31 ký tự và phải bắt đầu bằng một chữ cái. Các khoảng trống và ký hiệu toán học không được dùng để đặt tên. 1. NHÃN: Nhãn dùng để đánh dấu một địa chỉ mà các lệnh như: lệnh nhảy, gọi chương trình con, lệnh lập cần đến. Nó cũng được dùng cho các lệnh giả LABEL hoặc PROC hoặc EXTRN Ví dụ: NH: MOV AX, DS ; NH là nhãn đánh dấu một địa chỉ ô nhớ FOO LABEL near ; đặt tên cho địa chỉ ô nhớ sau lệnh giả này CTCON PROC FAR ; địa chỉ bắt đầu của chương trình con EXTRN NH near ; NH là nhãn ngoài chương trình gốc nầy 2. BIẾN: Biến dùng làm toán hạng cho lệnh hoặc biểu thức. Biến tượng trưng cho một địa chỉ nơi đó có giá trị mà ta cần. Ví dụ: TWO DB 2 ; khai báo biến TWO có giá trị là 2 3. KÝ HIỆU: Ký hiệu là một tên được định nghĩa để thay cho một biểu thức, một từ gợi nhớ lệnh. Ký hiệu có thể dùng làm toán hạng trong biểu thức, trong lệnh hay trong lệnh giả. Ví dụ: FOO EQU 7h ; ký hiệu FOO thay thế giá trị 07h TOTO = 0Fh ; ký hiệu TOTO thay thế giá trị 0Fh 2.3.3. Từ gợi nhớ mã lệnh, lệnh giả: Từ gợi nhớ mã lệnh sẽ được trình bày trong các chương sau về tập lệnh của bộ xử lý 8086. Trong phần này sẽ trình bày các lệnh giả thường dùng của MASM. Lệnh giả có thể được chia thành 5 nhóm: cấu trúc chương trình, khai báo dữ liệu, dịch có điều kiện, Macro và Liệt kê A. Nhóm cấu trúc chương trình: SEGMENT và ENDS: Khai báo đoạn. Cú pháp: SEGMENT [align] [combine] [‘class‘] ; nội dung của đoạn ENDS [align] xác định nơi bắt đầu của đoạn như sau, gồm các giá trị : Byte : Đoạn có thể bắt đầu ở địa chỉ bất kỳ. Word : Đoạn phải bắt đầu ở địa chỉ chẳn. Para : Đoạn phải bắt đầu ở địa chỉ là bội số của 16. Page : Đoạn phải bắt đầu ở địa chỉ là bội số của 256. [combine] xác định cách kết hợp phân đoạn này với phân đoạn khác: PUBLIC: các đoạn cùng tên và cùng class được ghép nối tiếp nhau khi liên kết. COMMON: các đoạn cùng tên và cùng class được ghép phủ lấp lên nhau khi liên kết. Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 20
- Hợp Ngữ AT : Đoạn được đặt tại một địa chỉ là bội số của 16 và được ghi trong biểu thức. STACK : Giống như Public, tuy nhiên con trỏ ngăn xếp SP chỉ vào địa chỉ đầu tiên của ngăn xếp đầu tiên. PRIVATE: các đoạn cùng tên và cùng class không được ghép vào nhau Ví dụ: Khai báo hai đoạn có tên là DSEG và CSEG: Không phủ lấp lên nhau DSEG SEGMENT ; Khai báo dữ liệu DSEG ENDS CSEG SEGMENT ; Các lệnh trong đoạn CSEG ENDS ASSUME: Chỉ định loại của một đoạn. Cú pháp: ASSUME : , : Ví dụ: Chỉ định đoạn có tên DATA là đoạn dữ liệu (DS) và đoạn có tên CODE là đoạn lệnh (CS): ASSUME DS: DATA, CS: CODE Lưu ý: Lệnh ASSUME chỉ được viết trong đoạn lệnh. Ví dụ: Báo cho hợp ngữ biết là không có đoạn nào được chỉ định loại. Khi đó, mỗi lần liên hệ đến một nhản (biến) phải dùng cả địa chỉ đoạn của chúng: ASSUME NOTHING COMMENT: ghi chú chương trình. Có thể viết trên nhiều dòng Cú pháp: COMMENT * * EVEN : Làm cho thanh ghi đếm chương trình PC là giá trị chẳn EXTRN: Cho biết một tên hay một ký hiệu đã được định nghĩa bên ngoài ở một module khác được sử dụng ở module chương trình hiện tại. END: Điểm cuối chương trình nguồn và xác định điểm bắt đầu Cú pháp: END Ví dụ: END begin ; điểm bắt đầu chạy CT là nhãn begin GROUP: Nhóm các đoạn khác nhau có một tên nhóm dùng chung Ví dụ: Nhóm 3 đoạn có tên DATA1, DATA2 và DATA3 có tên nhóm dùng chung là CGROUP: CGROUP GROUP DATA1,DATA2,DATA3 Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 21
- Hợp Ngữ INCLUDE : xen một tập tin hợp ngữ khác vào tập tin hiện hành Ví dụ: Xen tập tin THEM.ASM trên ổ đĩa C:\ASM vào tập tin hiện hành ngay tại vị trí của lệnh giả INCLUDE: INCLUDE C:\ASM\THEM.ASM LABEL : đánh dấu một địa chỉ là địa chỉ của lệnh hay số liệu kế Ví dụ: NHF LABEL FAR ; nhản xa, đánh dấu vị trí NH của lệnh kế NH: MOV AX, DATA CH DW 100 DUP (0) ; chuỗi từng từ NAME : đặt tên cho một module hợp ngữ Ví dụ: NAME Cursor ; đặt tên cho modun là cursor ORG: ấn định địa chỉ bắt đầu cho đoạn chương trình Ví dụ: ORG 100h MOV AX,code ; Lệnh này được đặt tại địa chỉ CS:100h PROC và ENDP: Khai báo chương trình con Cú pháp: PROC [Near/Far] ENDP Ví dụ: CTCON PROC Near MOV AX, 10 ; Bắt đầu chương trình con ADD DX, AX RET ; Trở về CT chính CTCON ENDP PUBLIC : khai báo các tên trong module hiện hành mà các module khác có thể sử dụng. Ví dụ : PUBLIC FOO, NH, TOTO B. Nhóm khai báo dữ liệu: Tất cả dữ liệu trong chương trình hợp ngữ được trình hợp dịch chuyển sang dạng nhị phân. Do đó giá trị của dữ liệu có thể được viết ở các dạng như: ký tự, thập phân, nhị phân, bát phân hay thập lục phân. B.1. Cách viết số: - Hệ thập phân: 10, 150, 1234 - Hệ bát phân: kết thúc bằng ký tự O (hay o), như: 10o, 35O, 1230O - Hệ thập lục phân: phải kết thúc bằng ký tự H (hoặc h) và bắt đầu là số, như: 10h, 13H, 2Fh, 0D4E1h Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 22
- Hợp Ngữ - Hệ nhị phân: kết thúc bằng ký tự B (hoặc b), như: 10b, 01100100B B.2. Chuỗi ký tự Ký tự hay chuỗi ký tự phải được kẹp giữa cặp dấu nháy đơn (‘) hoặc cặp dấu nháy kép (“), như: ‘A’, “b”, ‘Hello Assembly’, “This is a string” Trình hợp dịch chuyển ký tự sang dạng nhị phân tương ứng với mã ASCII, do đó ‘A’, “A”, 41h hay 65 đều có nghĩa như nhau khi lưu trữ. B.3. Định nghĩa dữ liệu (Khai báo biến) Cú pháp chung: [Tên Biến] [Tên biến] đặt theo quy cách của Tên. Tên biến (tên vùng nhớ), thực chất là địa chỉ tượng trưng của vùng nhớ và được chuyển thành địa chỉ thật sau khi dịch chương trình. xác định kích thước của biến theo byte, bao gồm: DB (Define Byte): khai báo biến 1 byte (1 ô nhớ) DW (Define Word): khai báo biến 2 byte (1 từ máy tính) DD (Define Double word): khai báo biến 4 byte (từ đôi) DQ (Define Quad word): khai báo biến 8 byte (bốn từ). DT (Define Ten byte): khai báo biến 10 byte. bao gồm các dạng: - Số hay biểu thức: 01100b, 0A1D3h, 15 hay (50+10h)*9 - Ký tự hay chuỗi: 'A', 'CHAO BAN' - Rỗng (không gán trước giá trị): ? - Mãng có n giá trị khác nhau: , , , - Mãng có X giá trị giống nhau: X DUP( ) Lưu ý: - Độ lớn của Trị không vượt quá khả năng lưu trữ của vùng nhớ đã định nghĩa bằng - Biến chuỗi ký tự phải khai báo bằng DB Các ví dụ: - Khai báo biến 1 byte, tên là SO và gán trước trị là 14: SO DB 14 SO (Tên biến/ địa chỉ ô nhớ) 1 byte nhớ→ 0Eh (Trị của Biến/ nội dung ô nhớ) - Khai báo mãng M gồm 5 phần tử có trị lần lượt 1, 3, 5, 7, 9: M DB 1, 3, 5, 7, 9 M M+1 M+2 M+3 M+4 01h 03h 05h 07h 09h - Khai báo biến 2 byte, lưu trữ giá trị 10, tên là WA: WA DW 10 ; 10 = 000Ah WA WA+1 WB WB+1 0Ah 00h 34h 12h Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 23
- Hợp Ngữ - Khai báo biến lưu trữ giá trị 1234h, đặt tên là WB: WB DW 1234h - Khai báo biến, lưu trữ chuỗi “Hello”, tên là str: str DB ‘Hello’ ; Lưu trong bộ nhớ bằng các mã ASCII str str+1 str+2 str+3 str+4 48h 65h 6Ch 6Ch 6Fh - Khai báo biến mãng Str2 lưu trữ lần lượt các trị ‘ABC’, 0Ah, 0Dh, ‘$’: Str2 DB ‘ABC’, 0Ah, 0Dh, ‘$’ ; Mãng 6 phần tử 1 byte Str2 Str2 +1 Str2 +2 Str2 +3 Str2 +4 Str2 +5 41h 42h 43h 0Ah 0Dh 24h - Khai báo biến mãng 7 phần tử có cùng giá trị là ‘$’, tên là Str3: Str3 DB 7 DUP(‘$’) ; Mãng 7 phần tử 1 byte Str3 Str3+1 Str3+2 Str3+3 Str3+4 Str3+5 Str3+6 24h 24h 24h 24h 24h 24h 24h Trong hợp ngữ, kiểu của biến được hiểu đơn giản hơn thông qua số lượng ô nhớ của biến và được thể hiện bằng . Các biến phải được khai báo trong đoạn dữ liệu (DS), một vài trường hợp đặt biệt vẫn được khai báo trong đoạn lệnh, nhưng phải luu ý đến tổ chức chương trình sao cho CPU không xem các biến như là lệnh. Các biến sẽ được phân phối bộ nhớ theo thứ tự được khai báo lần lượt từ ô nhớ có địa thấp đến cao. Trong một đoạn có nhiều biến được khai báo, biến được khai báo đầu tiên sẽ có địa chỉ độ dời trong đoạn dữ liệu bắt đầu là 0h và tiếp theo cho các biến được khai báo tiếp theo sau. B.4. Dữ liệu có cấu trúc: RECORD và STRUC: Khai báo biến kiểu có cấu trúc mẫu tin. Cú pháp: [Tên Biến] [trường: d] [, ] d: Số nguyên dương, xác định độ lớn của trường. : RECORD: d tính bằng bít. Cấu trúc dài tối đa là 16 bít STRUC: d tính bằng byte. Ví dụ: Hình 2.5 mô tả quản lý vùng nhớ cho 2 biến có cấu trúc sau: FOO RECORD CAO : 7, VUA : 3, THAP : 4 DIEMSV STRUC TEN: 3, MON1: 1, MON2: 1, MON3:1 D15 D14 D13 D12 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 FOO.CAO FOO.VUA FOO.THAP Hình 2.5a: Mô hình quản lý biến FOO Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 24
- Hợp Ngữ DS:0007h DS:0005h DIEMSV.TEN → DS:0004h DIEMSV.MON1 → DS:0003h DIEMSV.MON2 → DS:0002h DIEMSV.MON3 → DS:0001h Hình 2.5b: Mô hình quản lý biến DIEMSV B.5. Khai báo hằng EQU và = : gán trị cho 1 ký hiệu. EQU để gán trị cho ký hiệu (hằng số) chỉ một lần khi khai báo. Muốn gán lại giá trị nhiều lần, ta dùng lệnh “=“ Ví dụ: FOO EQU 2*10 ; gán trị 20 vào FOO FOO = 2*10 ; gán trị 20 vào FOO C. Nhóm lệnh giả về dịch (compile) có điều kiện: Các lệnh giả về dịch có điều kiện nhằm báo cho hợp ngữ tiến hành dịch một nhóm lệnh nếu một điều kiện được thỏa mãn (đúng). Ngược lại sẽ không dịch khi điều kiện không thoả mãn (sai) Cú pháp chung: ; Điều kiện dịch chương trình Nhóm lệnh A [ ELSE ] Nhóm lệnh B ENDIF ; Hết điều kiện dịch có thể có những hình thức sau: IFE : Nếu = 0 thì nhóm lệnh A được dịch. Nếu ≠ 0 thì nhóm lệnh B được dịch (nếu có lệnh giả ELSE) IF1 : Nếu đang dịch lần 1 thì nhóm lệnh A được dịch IF2 : Nếu đang dịch lần 2 thì nhóm lệnh A được dịch IFDEF : Nếu ký hiệu đã định nghĩa thì dịch nhóm lệnh A. IFNDEF : Nếu ký hiệu không được định nghĩa thì dịch nhóm lệnh A IFB : Nếu đối số là khoảng trống hoặc không có đối số thì dịch nhóm lệnh A. IFNB : Nếu có đối số thì dịch nhóm lệnh A IFIDN , : Nếu ĐốiSố1=ĐốiSố2 thì dịch nhóm lệnh A IFDIF , : Nếu ĐốiSố1 ≠ ĐốiSố2 thì dịch nhóm lệnh A Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 25
- Hợp Ngữ D. Nhóm lệnh giả về MACRO Cú pháp: MACRO [tham số] . ; đoạn chương trình ENDM ; chấm dứt Macro Ví dụ : Viết MACRO tên gen với 3 tham số vào X, Y, Z như sau : gen MACRO X, Y, Z MOV AX, X ; AX ← X ADD AX, Y ; AX ← AX + Y ADD AX, Z ; AX ← AX + Z ENDM Trong chương trình, gọi macro gen bằng lệnh: gen 10, 20, 30 ; X=10, Y=20, Z=30 Một đoạn chương trình sau đây được xen vào ngay lệnh gọi macro: MOV AX, 10 ; AX ← 10 ADD AX, 20 ; AX ← AX + 20 ADD AX, 30 ; AX ← AX + 30 Ngoài ra, trong Macro ta có thể dùng lệnh giả LOCAL, EXITM: EXITM : Thoát ra khỏi MACRO trước khi gặp lệnh ENDM. LOCAL: Định nghĩa các nhãn địa phương trong các MACRO khi chương trinh muốn gọi macro nhiều lần. Ví dụ: WAIT MACRO count MOV CX, count next: ADD AX, 1 LOOP next ENDM MACRO nầy chỉ được phép gọi một lần vì nhãn next chỉ có thể xuất hiện trong chương trình một lần. Nếu muốn gọi macro WAIT nhiếu lần thì ta phải thêm lệnh giả local như sau: WAIT MACRO count Local next ; nhãn địa phương MOV CX, count next: ADD AX,1 LOOP next ENDM E. Nhóm lệnh giả về liệt kê (listing) Nhóm lệnh nầy dùng để điều khiển in ấn chương trình theo 1 định dạng văn bản ở đầu mỗi trang, như: Số trang, số cột, Tựa đề chương trình PAGE số hạng, số cột Ví dụ : PAGE 58, 60 ; mỗi trang liệt kê có 58 hàng, 60 cột. TITLE (đề tựa) : cho phép đặt đề tựa chương trình Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 26
- Hợp Ngữ Ví dụ : TITLE chương trình hợp ngữ thứ nhứt. SUBTTL (Subtitle: đề tựa con): liệt kê tựa đề con ở mỗi đầu trang. % OUT : văn bản được liệt kê khi hợp ngữ dịch chương trình. Bao gồm các chỉ thị loại văn bản sau: .LIST : Liệt kê tất cả dòng lệnh với mã của nó (mặc nhiên) .XLIST : Không cho liệt kê .XALL : Liệt kê mã do MACRO tạo nên .LALL : Liệt kê toàn bộ MACRO .SALL : Không liệt kê MACRO .CREF : Liệt kê bảng đối chiếu chéo .XCREF : Không liệt kê bảng đối chiếu chéo 2.3.4. Toán hạng và toán tử A. Toán hạng: Hợp ngữ phân biệt 3 loại toán hạng: tức thì, thanh ghi và ô nhớ. Để phân biệt, mỗi loại toán hạng có cách viết khác nhau hoàn toàn. A.1. Toán hạng tức thì: có thể là một số, biểu thức hay một ký hiệu đã được định nghĩa (bằng lệnh EQU hay =). Toán hạng tức thì có thể được sử dụng theo 4 dạng: thập phân, nhị phân, thập lục phân, bát phân và Ký tự Cách viết: 10, ‘B’, 10b, 10h Ký hiệu tổng quát đại diện cho toán hạng tức thì: Immed : Toán hạng tức thì nói chung Immed8 : Toán hạng tức thì 8 bit Immed16 : Toán hạng tức thì 16 bit Immed32 : Toán hạng tức thì 32 bit A.2. Toán hạng thanh ghi: dùng để truy xuất đến nội dung thanh ghi. Cách viết: AX, BX, CX, DX, AL, AH, SI, DS, Ký hiệu tổng quát đại diện cho toán hạng thanh ghi: Reg : Toán hạng thanh ghi đa dụng nói chung Reg8 : Toán hạng thanh ghi đa dụng 8 bit Reg16 : Toán hạng thanh ghi đa dụng 16 bit SegReg : Toán hạng thanh ghi đoạn A.3. Toán hạng ô nhớ: dùng để truy xuất đến nội dung ô nhớ. Toán hạng ô nhớ thường được tượng trưng một địa chỉ của ô nhớ. Địa chỉ đó luôn luôn là địa chỉ độ dời trong một đoạn tương ứng. Các cách viết cơ bản: Tên_Biến : Truy xuất đến nội dung của Biến. [Immed16] : Truy xuất nội dung của ô nhớ trong đoạn DS, ô nhớ đó có địa chỉ độ dời là Immed16 . Còn gọi là trực tiếp ô nhớ. Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 27
- Hợp Ngữ [Reg16] : Truy xuất nội dung của ô nhớ trong đoạn DS, mà ô nhớ đó có địa chỉ độ dời lưu trong Reg16. Còn gọi là gián tiếp thanh ghi. Ví dụ: MOV AH, FOO ; AH ← nội dung biến FOO MOV DH, [1234h] ; DH ← nội dung ô nhớ có địa chỉ là 1234h MOV AL, [BX] ; AL ← nội dung ô nhớ có địa chỉ trong BX Ký hiệu tổng quát đại diện cho toán hạng ô nhớ: Mem : Toán hạng ô nhớ nói chung Mem8 : Toán hạng ô nhớ 8 bit Mem16 : Toán hạng ô nhớ 16 bit Mem32 : Toán hạng ô nhớ 32 bit Ví dụ các cách viết khác của toán hạng ô nhớ: FOO+5 , FOO[5] , 5[FOO] : chỉ đến địa chỉ “FOO cộng 5” (FOO là tên của 1 biến) FOO FOO+1 FOO+2 FOO+3 FOO+4 FOO+5 5[BX][SI] , [BX+5][SI] , [BX]5[SI] : tương đương với [BX+SI+5]. B. Toán tử: Có 4 loại toán tử: Thuộc Tính, Số Học, Quan Hệ và Logic. Cú pháp chung: Toán tử tác động lên toán hạng để cho ra kết quả, kết quả này dùng làm toán hạng trong lệnh. B.1. Toán tử thuộc tính (attribute): PTR (pointer): dùng thay đổi kiểu của các địa chỉ, số liệu Ví dụ : CALL Word PTR [BX+SI] ; Gọi CT Con [BX+SI] mặc nhiên trỏ tới ô nhớ (dữ liệu) 1 byte, nhưng nếu muốn lấy dữ liệu 2 byte thì phải dùng WORD PTR để đổi. : (Dấu hai chấm): dùng thay đổi đoạn mặc nhiên. Ví dụ : MOV AH, ES : [BX+SI] ; AH ← ES:[BX+SI] [BX+SI] mặc nhiên là địa chỉ độ dời của dữ liệu trong đoạn DS nhưng nếu dữ liệu trong đoạn ES thì phải viết ES:[BX+SI] SHORT: dùng để thay đổi kiểu mặc nhiên là Near của lệnh JMP (lệnh nhảy) và báo cho hợp ngữ biết chỉ nhảy trong vòng từ -128 đến +127 so với vị trí lệnh JMP THIS : tạo một toán hạng có giá trị tùy thuộc vào tham số của THIS Ví dụ: NH EQU THIS BYTE Ù NH LABEL BYTE SCH = THIS NEAR Ù SCH LABEL NEAR SEG : trả về địa chỉ đoạn của một nhãn hay biến Ví dụ: lấy địa chỉ đoạn của biến TENB vào AX MOV AX, SEG TENB Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 28
- Hợp Ngữ OFFSET: trả về địa chỉ độ dời của một nhãn hay biến Ví dụ: MOV BX, OFFSET FOO ; độ dời của biến FOO TYPE: Xác định kiểu của biến hay nhãn TYPE : cho số byte ô nhớ mà loại biến đó được khai báo (BYTE = 1, WORD= 2, DWORD = 4 ) TYPE : 0FFFFh nếu nhãn Near; 0FFFEh nếu nhãn Far LENGTH : Trả về số phần tử của biến mãng khai báo bằng DUP() SIZE : trả về tổng số byte mà một biến chiếm Ví dụ: FOO DW 100 DUP (?) MOV AX, type FOO ; AX ← 2 MOV CX, length FOO ; CX ← 100 MOV BX, size FOO ; BX ← 200 MOV DX, type FOO * length FOO ; DX ← 200 B.2. Toán tử số học: Ngoài các toán tử số học thông dụng (+, -, *, /) còn có các toán tử: MOD : chia lấy số dư SHR : dịch sang trái SHL : dịch sang phải – : Dấu trừ đứng trước một số để chỉ đó là số âm: -5, -300 Ví dụ: MOV AX, 100 MOD 17 ; AX ← 15 MOV AX, 1100000b SHR 5 ; AX ← 11b B.3. Toán tử quan hệ: Toán tử quan hệ dùng so sánh 2 toán hạng và thường được dùng trong việc dịch chương trình có điều kiện Cú pháp: : EQ (Equal): trả về 1 (TRUE) nếu 2 toán hạng bằng nhau NE (not equal): trả về TRUE nếu 2 toán hạng không bằng nhau LT (less than): trả về TRUE nếu (toán hạng 1) (toán hạng 2) LE (less than or equal): trả về TRUE nếu (t.hạng 1) ≤ (t.hạng 2) GE (greater than or equal): trả về TRUE nếu (t.hạng 1) ≥ (t.hạng 2) B.4. Toán tử logic: so sánh từng bit tương ứng giữa 2 toán hạng. NOT : trả về TRUE nếu hai toán hạng logic bên trái và phải khác nhau AND : trả về TRUE nếu cả hai toán hạng logic đều là TRUE. OR : trả về TRUE nếu một trong hai toán hạng là TRUE XOR : trả về TRUE nếu hai toán hạng khác nhau. Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 29
- Hợp Ngữ Ví dụ: MOV AH, 10 ; AH ← 10 MOV AL, 15 ; AL ← 15 MOV DH, AH EQ AL ; DH ← 0 (vì AH ≠ AL) MOV DL, AH EQ 10 ; DL ← 1 (vì AH = 10) MOV CH, AL LT AH ; CH ← 0 (vì AL < AH) MOV BH, AH AND 0Ah ; BH ← 1 (vì AL < AH) 2.4. CẤU TRÚC CỦA CHƯƠNG TRÌNH HỢP NGỮ MASM Một chương trình hợp ngữ có thể gồm nhiều module. Các module có thể viết riêng lẽ bằng một chương trình xử lý văn bản và dịch riêng lẽ bằng MASM để cho các chương trình đích. Các chương trình đích sẽ được chương trình liên kết (LINK) nối lại với nhau thành một chương trình chạy được có đuôi EXE. Mỗi module có thể viết theo một cấu trúc tổng quát như sau: PAGE 60, 132 TITLE ; chọn tiền đề cho module. . ; các phát biểu EXTRN hay PUBLIC (nếu có). MCR MACRO ; Nếu có ; viết macro ENDM STACK SEGMENT PARA STACK ‘STACK’ DB 64 DUP (?) STACK ENDS DSEG SEGMENT PARA PUBLIC ‘DATA’ . ; Khai báo Dữ liệu DSEG ENDS CSEG SEGMENT PARA PUBLIC ‘CODE’ ASSUME CS:CSEG, DS:DSEG, SS:STACK BATDAU:MOV AX, DSEG MOV DS, AX ; khởi động DS . ; (chương trình chính) CTC PROC NEAR ; Nếu có . ; viết chương trình con CTC ENDP CSEG ENDS END BATDAU ; Chấm dứt CTrình và chọn địa chỉ bắt đầu Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 30
- Hợp Ngữ 2.4.3. Tập tin thi hành dạng COM và dạng EXE Hợp ngữ MASM cho phép tạo 2 loại tập tin thi hành. Tập tin dạng COM dùng cho các chương trình nhỏ và tập tin dạng EXE dùng để xây dựng các chương trình lớn. Mỗi loại có cấu trúc chương trình khác nhau. 1. Dạng COM: - Chỉ dùng một đoạn duy nhất, các thanh ghi CS, DS, ES và SS đều có giá trị giống nhau. - Kích thước chương trình tối đa là 64K. - Tập tin COM được nạp vào bộ nhớ trong và thực hiện nhanh hơn tập tin EXE. Khi DOS thực hiện tập tin COM, nó tạo một vùng ô nhớ từ độ dời 0 đến 0FFh để chứa thông tin cần thiết cho DOS. Vùng này gọi là vùng PSP (program segment prefix) và tất cả các thanh ghi đoạn đều phải chỉ tới vùng PSP này. Vì thế địa chỉ bắt đầu của tập tin COM phải có địa chỉ độ dời là 100h. Cấu trúc chương trình điển hình của tập tin dạng COM như sau: ; Khai báo hằng số (Nếu có) MNAME MACRO ; Viết Macro (Nếu có) ENDM CSEG SEGMENT ASSUME CS: CSEG, DS: CSEG ORG 100h start: MOV AX, CSEG MOV DS, AX ; khởi động DS ; (Chương trình chính) INT 20h ; thoát ; Khai báo dữ liệu (Nếu có) CT_CON PROC ; Viết Thủ tục (Nếu có) RET CT_CON ENDP CSEG ENDS END start 2.4.3.2. Dạng EXE: - Chương trình lớn và nằm ở nhiều đoạn khác nhau. - Có thể gọi các chương trình con dạng Far. - Kích thước tập tin tùy ý. - Có header ở đầu tập tin để chứa các thông tin điều khiển cần thiết. - Thi hành chậm hơn tập tin dạng COM. Tập tin dạng EXE, không dùng lệnh ORG 100h ở đầu chương trình. Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 31
- Hợp Ngữ Cấu trúc chương trình điển hình của tập tin dạng EXE như sau: . ; Khai báo hằng số (nếu có) MNAME MACRO ; (Nếu có) ; Viết lệnh Macro ENDM DSEG SEGMENT ; Khai báo dữ liệu DSEG ENDS CSEG SEGMENT ASSUME CS: CSEG, DS: DSEG start: MOV AX, DSEG MOV DS, AX ; khởi động DS . . ; (Chương trình chính) . MOV AH, 4Ch ; hay MOV AX,4C00h INT 21h ; thoát CT_CON PROC ; Viết các Thủ tục (Nếu có) RET CT_CON ENDP CSEG ENDS END start 2.4.4. Ví dụ: Đoạn chương trình hợp ngữ sau thực hiện việc in ký tự ‘B’ lên màn hình (sử dụng hàm 02h của ngắt 21h – Ngắt này được trình bày cụ thể trong chương 4) MOV AH, 02h ; Sử dụng hàm in ký tự của ngắt 21h MOV DL, ‘B’ ; DL chứa ký tự cần in INT 21h ; Gọi ngắt để thực công việc 1. Muốn đoạn chương trình này thực thi trên máy tính ở dạng COM thì phải dùng cấu trúc chương trình dạng COM để viết, như sau: Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 32
- Hợp Ngữ CSEG SEGMENT ASSUME CS: CSEG ORG 100h Begin: MOV AH, 02h ; Sử dụng hàm in ký tự của ngắt 21h MOV DL, ‘B’ ; DL chứa ký tự cần in INT 21h ; Gọi ngắt để thực công việc INT 20h CSEG ENDS END Begin 2. Muốn đoạn chương trình này thực thi trên máy tính ở dạng EXE thì phải dùng cấu trúc chương trình dạng EXE để viết, như sau: DSEG SEGMENT ; Vì không có biến để khai báo nên đoạn DSEG có thể bỏ đi DSEG ENDS CSEG SEGMENT ASSUME CS: CSEG, DS: DSEG Begin: MOV AX, DSEG MOV DS, AX MOV AH, 02h ; Sử dụng hàm in 1 ký tự của ngắt 21h MOV DL, ‘B’ ; DL chứa ký tự cần in INT 21h ; Gọi ngắt để thực công việc MOV AH, 4Ch INT 21h CSEG ENDS END Begin 3. Viết lại chương trình trên nhưng không khai báo đoạn DSEG, khi đó chương trình chỉ có 1 đoạn duy nhất, như sau: CSEG SEGMENT ASSUME CS: CSEG, DS: CSEG Begin: MOV AX, CSEG MOV DS, AX MOV AH, 02h ; Sử dụng hàm in ký tự của ngắt 21h MOV DL, ‘B’ ; DL chứa ký tự cần in INT 21h ; Gọi ngắt để thực công việc MOV AH, 4Ch INT 21h CSEG ENDS END Begin Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 33
- Hợp Ngữ II.5. CÁCH TẠO CHƯƠNG TRÌNH HỢP NGỮ: Để tạo một chương trình viết bằng hợp ngữ chạy trên máy tính PC, bạn cần phải có bộ trình hợp dịch MASM (hay TASM). Trình hợp dịch MASM được cung cấp gồm các 2 tập tin cơ bản: MASM.EXE (hợp dịch) và LINK.EXE (liên kết). Ngoài ra còn một số tập tin khác như EXE2BIN.COM dùng để chuyển sang dạng COM và DEBUG.COM dùng để gở rối chương trình. Các tập tin này được thực thi dưới MS- DOS. Cần ba hoặc bốn bước để tạo chương trình hợp ngữ chạy được trên máy tính PC. Hình 2.6 và 2.7 mô tả các bước và lưu đồ thực hiện qui trình này. DSEG SEGMEMNT DSEG ENDS File đối CSEG SEGMENT File File thi ASSUME CS:CSEG BD: MOV AX,DSEG tượng hành MOV DS,AX nguồn EDIT MASM LINK CSEG ENDS *.ASM *.OBJ *.EXE END BD Bước 1 Bước 2 Bước 3 Hình 2.6: Các bước tạo chương trình hợp ngữ BƯỚC 1: Thảo chương, tạo tập tin nguồn (*.ASM) Dùng bất kỳ trình soạn thảo văn bản dạng TEXT quen thuộc để viết chương trình nguồn hợp ngữ, lưu thành file có phần mở rộng là *.ASM, Ví dụ: HELLO.ASM BƯỚC 2: Hợp dịch file ASM thành file đối tượng (HELLO.OBJ) C:\> MASM Trình hợp dịch kiểm tra lỗi cú pháp trên từng dòng lệnh. Nếu có lỗi thì phải quay về bước 1 để sửa chữa và dịch lại cho đến hết lỗi. BƯỚC 3: Liên kết một hay nhiều file OBJ thành file thi hành (*.EXE) C:\> LINK [ ] [ ] BƯỚC 4: Đổi từ EXE sang COM (Dành cho chương trình viết dạng COM) C:\> EXE2BIN Ví dụ: Dịch file nguồn HELLO.ASM thành file thực thi HELLO.EXE, từng bước thực hiện các lệnh như sau C:\>MASM HELLO; C:\>LINK HELLO; Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 34
- Hợp Ngữ Thảo chương MASM (Hợp dịch) CÓ LỖI? Đ S LINK (Liên kết) DẠNG *.COM ? S Đ Thi hành !!! EXE2COM Hình 2.7: Lưu đồ thực hiện qui trình Ngày nay, hầu hết các máy tính đều sử dụng hệ điều hành Windows, nên các lập trình viên đã phát triển các phần mềm chạy trên Windows 98/2000/XP để làm môi trường phát triển Hợp ngữ, như RadASM Assembly IDE ( Khi đó, việc sử dụng các phần mềm này đơn giản hơn rất nhiều thông qua giao diện đồ họa, nó cung cấp sẳn giao diện soạn thảo chương trình nguồn mạnh và các bước hợp dịch, liên kết đều được thực hiện trên thanh công cụ hay bằng phím tắt. Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 35
- Tập lệnh Intel-8086 và Kiểu định vị Chương 3 TẬP LỆNH INTEL-8086 và KIỂU ĐỊNH VỊ 3.1. TẬP LỆNH CỦA CPU-8086 Bộ xử lý 8086 có tập lệnh gồm 111 lệnh với chiều dài của lệnh từ 1 byte đến vài byte. Tập lệnh của họ các bộ xử lý Intel 80x86 càng ngày càng có nhiều lệnh mạnh và phức tạp (CPU-80386 có 206 lệnh, Pentium có hơn 400 lệnh). Lệnh của CPU-8086 có tối đa 2 toán hạng, mỗi lệnh có số toán hạng và loại toán hạng đã được xác định trước. Cú pháp tổng quát như sau: TH1, TH2 Tác vụ lệnh cho biết công việc mà CPU sẽ thực hiện (là thành phần bắt buộc), các toán hạng (TH1 và TH2) phải cách nhau bởi dấu phẩy (,). Đối với lệnh có hai toán hạng, thông thường TH2 sẽ là toán hạng nguồn còn TH1 là toán hạng đích và cũng là toán hạng nguồn còn lại. Kích thước của hai toán hạng phải bằng nhau: - Nếu TH1 là 8 bit thì TH2 cũng phải là 8 bit và ngược lại. - Nếu TH2 là 16 bit thì TH1 cũng phải là 16 bit và ngược lại. Tập lệnh CPU-8086 được sắp xếp theo các nhóm như sau: • Sao chép dữ liệu và địa chỉ • Tính toán số học • Tính toán logic, ghi dịch và quay • Truy xuất ngoại vi • Lệnh hệ thống • Rẽ nhánh và vòng lập • Chương trình con • Xử lý chuỗi Chương này chỉ trình bày các nhóm lệnh đơn giản và thường dùng. Các nhóm lệnh phức tạp như: rẽ nhánh, vòng lập, chương trình con và xử lý chuỗi) sẽ được trình bày trong những chương sau (chương 5, 6 và 7). Tập lệnh đầy đủ của bộ xử lý Intel- 8086 sẽ được giới thiệu trong phụ lục 1. 3.1.1. Lệnh sao chép dữ liệu, địa chỉ: 1. MOV - Di chuyển dữ liệu Cú pháp: MOV Đích, Nguồn MOV SegReg, Reg16 MOV Reg16, SegReg Nguồn (toán hạng nguồn) : Reg, Mem, Immed. Đích (toán hạng đích) : Reg, Mem. Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 36
- Tập lệnh Intel-8086 và Kiểu định vị Ý nghĩa: Sao chép dữ liệu (xác định bởi toán hạng nguồn) vào vùng nhớ hoặc thanh ghi (xác định bởi toán hạng đích). Sau khi thực hiện xong thì giá trị toán hạng nguồn và toán hạng đích bằng nhau. Lưu ý: - Lệnh MOV không ảnh hưởng đến thanh ghi trạng thái. - Một trong hai toán hạng phải là thanh ghi. Ví dụ: MOV CX, BX ; Sao chép nội dung thanh ghi BX vào thanh ghi CX. Sau khi thực hiện xong, BX=CX. MOV DX, 1234h ; DL ← 34h, DH ← 12h MOV DS, AX ; DS ← AX MOV AH, [1234h] ; AH ← M[DS:1234h] MOV [1235h], DX ; M[DS:1235h] ← DL, M[DS:1236h] ← DH MOV AH, CX ; SAI vì AH có 8 bit trong khi CX là 16 bit. Bộ Nhớ DS:1237h DS:1236h DS:1235h DX DH DL DS:1234h Hình 3.1: Mô tả lệnh MOV [1235h], DX Hình 3.1 mô tả cách sao chép dữ liệu 16 bit giữa thanh ghi và ô nhớ. Byte thấp của dữ liệu trong DX (là DL) đưa vào ô nhớ địa chỉ thấp (DS:1235h), còn byte cao trong DX (là DH) đưa vào ô nhớ có địa chỉ cao hơn (DS:1236h) 2. XCHG – Hoán chuyển dữ liệu Cú pháp: XCHG Đích, Nguồn ; Đích ↔ Nguồn Nguồn, đích: Reg, Mem. Ý nghĩa: Lệnh XCHG hoán chuyển dữ liệu giữa nguồn và đích. Cả hai toán hạng không đồng thời là Mem. Ví dụ: XCHG AL, BH ; AL ↔ BH XCHG AX, [1235h] ; AL ↔ M[DS:1235h], AH ↔ M[DS:1236h] XCHG bienA, bienB ; SAI vì bienA và bienB đều là vùng nhớ. 3. LEA - Lấy địa chỉ độ dời Cú pháp: LEA Reg16, Mem16 ; Reg16 ← Địa chỉ độ dời Ý nghĩa: Lấy địa chỉ độ dời của biến hay nhãn (mem16) đưa vào thanh ghi đích Reg16. Ví dụ: LEA DX, bienA ; Lấy độ dời của biến bienA lưu vào DX Theo hình 3.1, bienA được cấp phát tại vùng nhớ có địa chỉ độ dời là 1A2Bh, sau khi thực hiện lệnh thì thanh ghi DX = 1A2Bh. Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 37
- Tập lệnh Intel-8086 và Kiểu định vị Bộ Nhớ Địa Chỉ DS:1A2C6h bienA→ DS:1A2Bh DX 1Ah 2Bh DS:1A2Ah Hình 3.2: Mô tả lệnh LEA DX, bienA 3.1.2. Lệnh tính toán số học. 1. ADD - Cộng hai số nguyên Cú pháp: ADD đích, nguồn ; đích ← đích + nguồn Nguồn : Reg, Mem, Immed. Đích : Reg, Mem. Ý nghĩa: Lấy toán hạng nguồn cộng toán hạng đích và lưu kết quả lưu toán hạng đích. 2. SUB - Trừ hai số nguyên Cú pháp: SUB đích, nguồn ; đích ← đích – nguồn Nguồn : Reg, Mem, Immed. Đích : Reg, Mem. Ý nghĩa: Lấy toán hạng đích (số bị trừ) trừ toán hạng nguồn (số trừ) và lưu kết quả ở toán hạng đích. Ví dụ: ADD AL, 15 ; AL ← AL + 15 ADD AX, DX ; AX ← AX + DX SUB BX, 15h ; BX ← BX – 15h SUB DX, CL ; SAI vì DX là 16bit trong khi CL chỉ có 8bit ADD 15h, AL ; SAI vì đích là Immed 3. INC - Tăng 1 đơn vị (Increment) Cú pháp: INC đích ; đích ← đích + 1 Đích : Reg, Mem. Ý nghĩa: Tăng nội dung của toán hạng đích thêm 1 đơn vị. 4. DEC - Giảm 1 đơn vị (Decrmemt) Cú pháp: DEC đích ; đích ← đích – 1 Đích : Reg, Mem. Ý nghĩa: Giảm nội dung của đích đi 1 đơn vị. Ví dụ: INC AL ; AL ← AL + 1 DEC AX ; AX ← AX - 1 INC bienC ; bienC ← bienC + 1 5. MUL - Nhân hai số nguyên Cú pháp: MUL nguồn Nguồn: Reg, Mem Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 38
- Tập lệnh Intel-8086 và Kiểu định vị Ý nghĩa: Nhân thanh ghi tích lũy với toán hạng nguồn. Tùy vào kích thước của toán hạng nguồn mà CPU thực hiện phép nhân 8 hay 16 bit. - Nhân 8 bit: dành cho toán hạng nguồn là 8 bit. Khi đó, CPU sẽ lấy thanh ghi AL nhân với toán hạng nguồn và lưu kết quả vào AX. - Nhân 16 bit: dành cho toán hạng nguồn là 16 bit. Khi đó, CPU sẽ nhân thanh ghi AX với toán hạng nguồn và lưu kết quả vào cặp thanh ghi DX:AX (nghĩa là kết quả có 32 bit, 16 bit cao lưu vào DX, còn 16 bit thấp lưu vào AX) Ví dụ: MUL BL ; AX ← AL * BL (nhân 8 bit) MUL BX ; DX:AX ← AX * BX (nhân 16 bit) MUL [1235h] ; AX ← AL * M[DS:1235h] (nhân 8 bit) 6. DIV - Chia hai số nguyên Cú pháp: DIV nguồn Nguồn: Reg, Mem Ý nghĩa: lấy thanh ghi tích lũy (số bị chia) chia cho nguồn (số chia). Tùy vào kích thước của toán hạng nguồn mà CPU thực hiện phép chia 8 hay 16 bit. - Chia 8 bit: dành cho toán hạng nguồn là 8 bit. Khi đó, CPU sẽ lấy thanh ghi AX chia cho toán hạng nguồn. Thương số của kết quả được lưu vào AL còn phần dư lưu vào AH. - Chia 16 bit: dành cho toán hạng nguồn là 16 bit. Khi đó, CPU lấy DX:AX (số 32 bit) chia cho toán hạng nguồn. Thương số của kết quả được lưu vào AX còn phần dư thì lưu vào DX. Ví dụ: DIV DL ; AL, AH ← AX ÷ DL DIV BX ; AX, DX ← DX:AX ÷ BX 3.1.3. Nhóm lệnh logic và ghi dịch 1. AND, OR, XOR, TEST: Và, Hoặc, Cộng không nhớ, Kiểm tra bit Cú pháp: AND đích, nguồn ; đích ← đích ∧ nguồn OR đích, nguồn ; đích ← đích ∨ nguồn XOR đích, nguồn ; đích ← đích ⊕ nguồn TEST đích, nguồn ; Cờ ← đích ∧ nguồn Nguồn: Reg, Mem hay Immed. Đích: Reg, Mem. Ý nghĩa: Thực hiện phép toán logic (and, or, xor) theo từng bit tương ứng giữa toán hạng đích và toán hạng nguồn, lưu giữ kết quả ở toán hạng đích. - Lệnh TEST thực hiện kiểm tra bit, giống lệnh AND nhưng không lưu giữ lại kết quả mà kết quả của phép toán chỉ ảnh hưởng đến các cờ trạng thái. Ví dụ: MOV AL, 01101110b ; AL ← 01101110b AND AL, 00110110b ; AL ← AL ∧ 01101110b (AL=00100110b) XOR AX, AX ; AX ← AX ⊕ AX (Kết quả: AX = 0) Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 39
- Tập lệnh Intel-8086 và Kiểu định vị AND DL, 11000011b ; Xóa 4 bit giữa trong thanh ghi DL TEST DH, 00010000b ; Kiểm tra giá trị của bit 4 trong thanh ghi DH. Kết quả kiểm tra sẽ ảnh hưởng lên cờ Zero (ZF) 2. NOT – Đảo bit (Lấy Bù 1) Cú pháp: NOT đích ; đích ← đích Đích: Reg, Mem Ý nghĩa: Đảo ngược từng bit (hay lấy bù 1) toán hạng đích. Ví dụ: MOV AH, 0Fh ; AH ← 0Fh (00001111b) NOT AH ; AH = 0F0h (11110000b) 3. SHL – Dịch trái logic (logical SHift Left) Cú pháp: SHL đích, 1 ; dịch toán hạng đích sang trái 1 bit. SHL đích, CL ; dịch sang trái CL bít Đích: Reg, Mem Ý nghĩa: Dịch toán hạng đích sang trái, có thể dịch 1 bit hay nhiều bit hơn (CL chứa số bit dịch). LSB được nạp vào logic 0, còn MSB được dịch sang cờ Carry (CF). CF 7 2 1 0 0 Hình 3.3: Dịch toán hạng đích 8 bit sang trái 1 bit Ví dụ: MOV AL, 01101101b ; AL = 01101101b SHL AL, 1 ; AL = 11011010b và CF=0 4. SHR (logical shift right) dịch phải logic. Cú pháp: SHR đích, 1 ; dịch trái toán hạng đích 1 bit. SHR đích, CL ; dịch trái đích với số bít trong CL Ý nghĩa: Giống lệnh SHL nhưng bay giờ dịch toán hạng đích sang phải 7 6 1 0 CF 0 Hình 3.4: Dịch toán hạng đích 8 bit sang phải 1 bit Ví dụ: MOV AL, 01101101b ; AL = 01101101b SHR AL, 1 ; AL = 00110110b và CF=1 5. SAL (Shift arithmetic left): dịch trái số học Cú pháp: SAL đích, 1 ; dịch toán hạng đích sang trái 1 bit. SAL đích, CL ; dịch sang trái CL bít Đích: Reg, Mem Ý nghĩa: Lệnh nầy giống SHL nhưng LSB (bit thấp nhất) vừa được dịch lên bít 1 và giữ nguyên (bảo toàn bit 0). Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 40
- Tập lệnh Intel-8086 và Kiểu định vị CF 7 2 1 0 Hình 3.5: Dịch toán hạng đích 8 bit sang trái 1 bit Ví dụ: MOV AL, 01101101b ; AL = 01101101b SHL AL, 1 ; AL = 11011011b và CF=0 6. SAR (Shift arithmetic right) : dịch phải số học Cú pháp: SAR đích, 1 ; dịch toán hạng đích sang trái 1 bit. SAR đích, CL ; dịch sang trái CL bít Đích: Reg, Mem Ý nghĩa: Lệnh nầy giống SHR nhưng MSB (bit cao nhất) vừa được dịch xuống bit thấp hơn và giữ nguyên (bảo toàn bit MSB – Bit dấu). 7 6 0 CF Hình 3.6: Dịch toán hạng đích 8 bit sang phải 1 bit Ví dụ: MOV AL, 01101101b ; AL = 01101101b SAR AL, 1 ; AL = 00110110b và CF=1 7. ROL (Rotate left) : quay vòng sang trái Cú pháp: ROL đích, 1 ; quay vòng toán hạng đích sang trái 1 bit. ROL đích, CL ; quay vòng sang trái số lần quay bằng CL. Ý nghĩa: Giống SHL, nhưng thực hiện việc quay vòng, MSB dịch vào LSB CF 7 2 1 0 Hình 3.7: Quay toán hạng đích 8 bit sang trái 1 bit Ví dụ: MOV AL, 01101101b ; AL = 01101101b ROL AL, 1 ; AL = 11011010b và CF=0 8. ROR (Rotate right) : Quay vòng sang phải Cú pháp: ROR đích, 1 ; Quay vòng toán hạng đích sang phải1 bit. ROR đích, CL ; Quay vòng với số lần quay bằng CL Đích: Reg, Mem Ý nghĩa: Lệnh nầy giống ROL nhưng quay vòng sang phải, nghĩa là LSB (bit thấp nhất) vừa được dịch đến MSB. 7 6 0 CF Hình 3.8: Quay toán hạng đích 8 bit sang phải 1 bit Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 41
- Tập lệnh Intel-8086 và Kiểu định vị Ví dụ: MOV AL, 01101101b ; AL = 01101101b SAR AL, 1 ; AL = 00110110b và CF=1 9. RCL (Rotate through carry left): Quay trái qua cờ Carry Cú pháp: RCL đích, 1 ; quay vòng TH. đích qua cờ sang trái 1 bit. RCL đích, CL ; quay vòng qua cờ sang trái số lần bằng CL. Ý nghĩa: Giống như lệnh ROL nhưng có sự tham gia của cờ carry (CF). Xem hình 3.9. Như vậy CF cũng là 1 bit tham gia vào vòng quay CF 7 2 1 0 Hình 3.9: Quay toán hạng đích 8 bit qua cờ sang trái 1 bit 10. RCR (Rotate through carry right): Quay vòng qua cờ sang phải Cú pháp: RCR đích, 1 ; Quay vòng TH. đích qua cờ sang phải 1 bit. RCR đích, CL ; số lần quay bằng CL Đích: Reg, Mem Ý nghĩa: Lệnh nầy giống RCL nhưng quay vòng sang phải. 7 6 0 CF Hình 3.10: Quay toán hạng đích 8 bit qua cờ sang phải 1 bit 3.1.4. Nhóm lệnh vào ra ngoại vi. 1. IN - Lấy số liệu từ ngoại vi. Cú pháp: IN AL, địa chỉ cổng 8 bít IN AL, DX ; DX chứa địa chỉ cổng 16 bit Ý nghĩa: Lấy dữ liệu ở ngoại vi có địa chỉ 8 bit đưa vào thanh ghi AL. Nếu địa chỉ của ngoại vi là 16 bít thì phải dùng DX chứa địa chỉ này. Ví dụ : - Đọc dữ liệu ở ngoại vi 3Fh IN AL, 3Fh ; AL ← port(3Fh) (3Fh là địa chỉ cổng 8 bít) - Đọc dữ liệu ở ngoại vi 3F8h MOV DX, 3F8h ; DX ← 3F8h (3F8h là địa chỉ cổng 16 bit) IN AL, DX ; AL ← port(DX) 2. OUT - Đưa số liệu ra ngoại vi. Cú pháp: OUT địa chỉ cổng 8 bít, AL ; port(8 bit) ← AL OUT DX, AL ; port(DX) ← AL Ý nghĩa: Giống lệnh IN nhưng là xuất dữ liệu trong AL ra ngoại vi. Ví dụ: MOV DX, 04A5h ; DX ← 04A5h OUT DX, AL ; port(DX) ← AL Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 42
- Tập lệnh Intel-8086 và Kiểu định vị 1.3.5. Nhóm lệnh hệ thống Nhóm lệnh hệ thống bao gồm các lệnh điều khiển hoạt động của CPU hay thiết lập giá trị các cờ. Các lệnh này không có toán hạng do đó cú pháp của lệnh rất đơn giản chỉ gồm các tác vụ lệnh sau: CLC ; Xóa cờ CF (CF = 0) – Clear Carry flag CMC ; Đảo ngược cờ CF – Complement Carry flag CLD ; Xóa cờ hướng (DF=0) – Clear Diretion flag STD ; Đặt cờ hướng (DF=1) – Set Diretion flag CLI ; Xóa cờ ngắt (IF=0) – Clear Interrupt flag STI ; Đặt cờ ngắt (IF=1) – Set Interrupt flag HLT ; Dừng mọi hoạt động của CPU (treo máy) – Halt INT ; Gọi ngắt phần mềm – Interrupt IRET ; Trở về chương trình chính từ chương trình phục vụ ngắt – Return from Interrupt LOCK ; Khóa Bus ngoài. CPU sẽ không giao tiếp với BUS NOP ; Không có tác vụ – No operation WAIT ; Tạm dừng CPU cho đến khi có tín hiệu điện (mức thấp) ở chân TEST của CPU-8086 thì hoạt động tiếp. 3.2. KIỂU ĐỊNH VỊ Kiểu định vị (Addressing mode) là cách thức xác định vị trí của dữ liệu được mô tả trong câu lệnh. Thông qua kiểu định vị, CPU biết được vị trí lưu trữ toán hạng để truy xuất đến đúng giá trị mà lệnh cần xử lý. Tùy vào loại toán hạng, CPU-8086 cung cấp các kiểu định vị sau: - Định vị thanh ghi (register addressing) - Định vị tức thì (immediate addressing) - Định vị trực tiếp (direct addressing) - Định vị gián tiếp thanh ghi (register indirect addressing) - Định vị nền (based offset addressing) - Định vị chỉ số (index offset addressing) - Định vị chỉ số nền (based index offset addressing) - Định vị chuỗi (string addressing) - Định vị vào ra (port in/out addressing). Trong các kiểu định vị trên thì kiểu định vị thanh ghi và tức thì có tốc độ truy xuất nhanh nhất. Đối với toán hạng tức thì, dữ liệu nằm ngay trong lệnh và giá trị của của nó được chèn trực tiếp vào trong mã máy; còn đối với kiểu định vị thanh ghi, do thanh ghi là một bộ phận bên trong của CPU, nên CPU không mất thời gian truy xuất bộ nhớ trong. 3.2.1. Định vị tức thì: Là kiểu định vị trong đó phải có toán hạng nguồn là toán hạng tức thì và toán hạng đích phải là toán hạng thanh ghi. Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 43
- Tập lệnh Intel-8086 và Kiểu định vị Ví dụ: MOV AX, 15 ; AX ← 15 (AH=0; AL=15) ADD AH, ‘A’ ; AH ← AH + 41h (‘A’ = 41h) MOV DX, 3*1Ah ; DX ← 4Eh (DH=0; DL=4Eh) IN AL, 0Fh ; Không phải kiểu định vị tức thì Các giá trị tức thì là: 15, ‘A’ và 004Eh Toán hạng tức thì là dữ liệu nằm ngay trong mã lệnh. Khi khi CPU thực hiện lệnh, mã lệnh được đọc vào thanh ghi lệnh (IR) do đó giá trị tức thì cũng tồn tại trong CPU khi lệnh được thi hành (Xem hình 3.11) AX 00 15 15 15 IR Hình 3.11: Vị trí toán hạng tức thì khi CPU thi hành lệnh 3.2.2. Định vị thanh ghi Định vị thanh ghi là kiểu định vị mà tất cả các toán hạng đều phải là toán hạng thanh ghi. Kiểu định vị này được sử dụng phổ biến vì có tốc độ nhanh và ít chiếm bộ nhớ. Ví dụ: MOV AX, CX ; AX ← CX INC AX ; AX ← AX +1 OUT DX, AL ; Không phải kiểu định vị thanh ghi Trong đó AX và CX đều là 2 toán hạng thanh ghi. AX 0A 12 0A 12 0A 12 CX Hình 3.12: Hoạt động của lệnh MOV AX, CX 3.1.3. Định vị trực tiếp (bộ nhớ): Địa chỉ hiệu dụng (EA - Effective Address): Là địa chỉ độ dời (Offset) mà EU tính toán cho một toán hạng bộ nhớ để có thể truy xuất nội dung toán hạng bộ nhớ đó. EU có thể tính địa chỉ hiệu dụng theo nhiều cách. Tùy theo cách tính mà ta có các kiểu định vị bộ nhớ khác nhau. Định vị trực tiếp là kiểu định vị trong đó chỉ có một toán hạng là địa chỉ độ dời của ô nhớ chứa dữ liệu, toán hạng kia là toán hạng thanh ghi. Địa chỉ hiệu dụng nằm ngay trong lệnh. Địa chỉ hiệu dụng EA kết hợp với nội dung hiện tại của thanh ghi DS trong BIU để tính toán ra địa chỉ vật lý của ô nhớ theo công thức : PA = Segment * 10h + EA Ví dụ: MOV AH, 12h MOV FOO, AH ; FOO ← AH (=12h) MOV BX, [1234h] ; BL ← M[DS:1234h], BH ← [DS:1235h] Giả sử thanh ghi đoạn dữ liệu có địa chỉ segment là DS=0200h. Vậy địa chỉ vật lý (Physical Address) của toán hạng nguồn được tính như sau: PA = DS*10h + EA = 200h * 10h + 1234h = 03234h Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 44
- Tập lệnh Intel-8086 và Kiểu định vị Chú ý không có lệnh nào cho phép cả hai toán hạng đều tham chiếu đến vị trí bộ nhớ. Muốn làm được điều này chúng ta phải dùng kiểu định vị gián tiếp thanh ghi. 3.1.4. Định vị gián tiếp thanh ghi Địa chỉ hiệu dụng là nội dung của một trong các thanh ghi BX, BP, SI, DI. Định vị gián tiếp thanh ghi cũng tương tự như định vị trực tiếp, địa chỉ hiệu dụng EA kết hợp với nội dung của thanh ghi phân đoạn DS để hình thành một địa chỉ vật lý của toán hạng. Tuy nhiên cũng có sự khác nhau về cách tính độ dời. Địa chỉ hiệu dụng EA là nội dung trong các thanh ghi BP, BX, SI và DI bên trong CPU 8086. Ví dụ: MOV AL, [BX] ; AL ← M[DS:BX] ADD CX, [BP] ; CX ← CX + M[DS:BP] MOV [SI], DX ; M[DS:SI] ← DL, M[DS:SI+1] ← DH Giả sử SI = 1234h và DS = 0300h, địa chỉ vật lý được tính là: PA = DS * 10h + EA = 0300h*10h + 1234h = 04234h (với EA = SI = 1234h) 3.1.5. Định vị nền Giống như định vị gián tiếp thanh ghi, nhưng địa chỉ hiệu dụng EA trong trường hợp này là tổng của nội dung của thanh ghi BX hoặc BP với độ dời (giá trị 16 bit có dấu): EA = BX + Độ Dời hay EA = BP + Độ Dời Địa chỉ vật lý là tổng giá trị độ dời đô dịch chuyển trực tiếp hoặc gián tiếp nội dung của thanh ghi BX hoặc BP với giá trị chứa trong thanh ghi phân đoạn DS hoặc SS tương ứng. Ví dụ: MOV AL, [BX + 20h] ; AL← M[DS:BX+20h] MOV [BX].beta, CX ; M[DS:BX+beta] ← CL ; M[DS:BX+beta+1] ← CH Giả sử DS = 0200h, BX = 1000h còn beta = 0FA34h. Vậy địa chỉ vật lý của toán hạng đích trong trường hợp này là: PA = 0200h*10h + 1000h + 0FA34h = 10C34h Nếu thanh ghi BP được sử dụng thay vì sử dụng thanh ghi BX thì việc tính toán địa chỉ vật lý của toán hạng đích khi đó sẽ phải sử dụng thanh ghi phân đoạn SS thay vì là DS như trên. Điều này cho phép truy xuất đến dữ liệu trong phân đoạn ngăn xếp của bộ nhớ. 3.1.6. Định vị chỉ số Địa chỉ hiệu dụng là tổng của độ dời 16 bit và thanh ghi SI hoặc DI EA = SI + Độ dời hoặc EA = DI + Độ dời Cũng tương tự như kiểu định vị nền, địa chỉ vật lý là tổng độ dịch chuyển trực tiếp hoặc gián tiếp nội dung của thanh ghi SI hoặc DI với giá trị chứa trong thanh ghi phân đoạn DS hoặc ES tương ứng. Ví dụ: MOV DL, [ SI+ 25h] ; DL ← M[DS:SI+25h] Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 45
- Tập lệnh Intel-8086 và Kiểu định vị MOV AL , ARRAY[SI] ; AL ← M[DS:SI+ARRAY] Giả sử DS = 0200h, SI = 2000h còn ARRAY là độ dời có giá trị là 1234h. Vậy địa chỉ vật lý của toán hạng đích trong trường hợp này là: EA = SI + ARRAY = 2000h + 1234h = 3234h PA = 0200h*10h + EA = 2000h + 3234h = 05234h Nếu thanh ghi DI được sử dụng thay vì sử dụng thanh ghi SI thì việc tính toán địa chỉ vật lý của toán hạng đích khi đó sẽ phải sử dụng thanh ghi phân đoạn ES thay vì là DS như trên. Ví dụ: MOV AL, [DI +1Fh] ; AL ← M[ES:DI+1Fh] PA = ES * 10h + DI + 100h 3.1.7. Định vị chỉ số nền Đây là kiểu định vị kết hợp từ kiểu định vị nền và định vị chỉ số. Địa chỉ hiệu dụng là tổng của thanh ghi nền (BX hay BP), thanh ghi chỉ số (SI hay DI) và độ dời 16 bit. EA = BX + SI + Độ Dời ⇒ PA = DS * 10h + EA EA = BX + DI + Độ Dời ⇒ PA = ES * 10h + EA Ví dụ: MOV DL, [BX+SI+100] ; PA = DS * 10h + BX + SI + 100 MOV AL, [BX+DI+200] ; PA = ES * 10h + BX + DI + 200 3.1.8. Định vị chuỗi Các lệnh xử lý chuỗi không dùng kiểu định vị bộ nhớ thông thường mà dùng 2 thanh ghi chỉ số SI và DI để chứa địa chỉ độ dời của chuỗi nguồn và chuỗi đích. Các lệnh xử lý chuỗi trong 8086 tự động dùng các thanh ghi chỉ mục nguồn và đích để tính toán địa chỉ của toán hạng nguồn và đích tương ứng. Kiểu định vị này gọi là định vị chuỗi và chỉ áp dụng cho các lệnh xử lý chuỗi. Các lệnh xử lý chuỗi của Intel-8086 được trình bày kỹ trong chương 6, bao gồm: MOVSB/W, SCASB/W, CMPSB/W, STOSB/W, LODSB/W. Lệnh sẽ xử lý 1 lần 1 Byte hoặc 2 byte (Word) - còn gọi là phần tử. Sau khi thực hiện xong lệnh, SI và DI tự động điều chỉnh tăng/giảm 1 đơn vị để chỉ đến phần tử kế tiếp cần xử lý. SI và DI tự động cùng tăng hay cùng giảm được quyết định bởi cờ Hướng (DF). Nếu DF = 0 thì xử lý theo chiều tăng địa chỉ, còn DF = 1 thì xử lý theo chiều giảm địa chỉ. Tùy vào cách xử lý chuỗi mà người lập trình chọn hướng xử lý thích hợp. Khi đó: • DS:SI phải chỉ đến byte đầu tiên cần xử lý của chuỗi nguồn. • ES:DI phải chỉ đến byte đầu tiên cần xử lý của chuỗi đích. Hình 3.13 mô tả vị trí 2 chuỗi Nguồn và Đích (mỗi chuỗi 256 byte) trong bộ nhớ với chiều xử lý tăng địa chỉ. Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 46
- Tập lệnh Intel-8086 và Kiểu định vị 1AF4:0000h Địa chỉ đầu chuỗi Nguồn Chuỗi (DS ← 1AF4h và SI ← 0000h) Nguồn 256 byte 1AF4:00FFh Địa chỉ cuối chuỗi Nguồn . 1AD4:0100h Địa chỉ đầu chuỗi Đích Chuỗi (ES ← 1AD4h và DI ← 0100h) Đích 256 byte 1AD4:01FFh Địa chỉ cuối chuỗi Đích Hình 3.13: Mô hình bộ nhớ chứa chuỗi Nguồn và Đích 3.1.9. Định vị cổng vào/ra Định vị cổng vào/ra chỉ áp dụng các lệnh vào ra ngoại vi trong tập lệnh của 8086 (IN và OUT) để truy xuất đến các port vào/ra của thiết bị ngoại vi. Có 2 cách truy xuất đến không gian địa chỉ của Port vào ra: • Trực tiếp: Chỉ dùng cho cổng có địa chỉ 8 bit. Địa chỉ cổng được cung cấp trực tiếp trên dòng lệnh. Ví dụ: IN AL, 0F8h ; Đọc dữ liệu tại cổng 0F8h đưa vào AL OUT 01h, AL ; Xuất giá trị AL ra cổng có địa chỉ 01h • Gián tiếp: Đối với những cổng có địa chỉ 16 bit thì không sử dụng cách trực tiếp để truy xuất được, khi đó thanh ghi DX được dùng để chứa địa chỉ của thiết bị ngoại vi. Ví dụ: IN AL, DX ; AL ← port(DX) OUT DX, AL ; port(DX) ← AL Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 47
- Tập lệnh Intel-8086 và Kiểu định vị BÀI TẬP CHƯƠNG 3 3.1. Cho biết nội dung của các toán hạng đích và giá trị các cờ CF, SF, ZF, PF, OF sau khi thực hiện mỗi lệnh sau: a. ADD AX, BX ; Với AX = 7FFFh, BX = 1 b. SUB AL, BL ; Với AL = 1, BL = 0FFh c. DEC AL ; Với AL = 0 d. NEG AL ; Với AL = 7Fh e. XCHG AX, BX ; Với AX = 1ABCh, BX = 712Ah f. ADD AL, BL ; Với AL = 80h, BL = 0FFh g. SUB AX, BX ; Với AX = 0, BX = 8000h h. NEG AX ; Với AX = 1 3.2. Cho biết kết quả sau khi thực hiện lệnh ADD AX, DX và trạng thái cờ tràn (OF) trong các trường hợp sau: a. AX = 512Ch , DX = 4185h b. AX = 0FE12h, DX = 1ACBh c. AX = 0E1E4h, DX = 0DAB3h d. AX = 7132h , DX = 7000h e. AX = 6389h , DX = 1176h 3.3. Cho biết kết quả sau khi thực hiện lệnh SUB CX, BX và trạng thái cờ tràn (OF) trong các trường hợp sau: a. CX = 2143h , BX = 1986h b. CX = 81FEh , BX = 1986h c. CX = 19BCh , BX = 81FEh d. CX = 02h , BX = FE0Fh e. CX = 8BCDh , BX = 71ABh 3.4. Cho AL = 0CBh và CF = 1. Cho biết giá trị AL sau khi thực hiện lệnh: a. SHL AL, 1 b. SHR AL, 1 c. ROL AL, CL ; Với CL =2 d. ROR AL, CL ; Với CL = 3 e. SAR AL, CL ; Với CL = 2 f. RCL AL, 1 g. RCR AL, CL ; Với CL = 3 3.5. Dùng lệnh TEST để thiết lập giá trị các cờ sau: a. ZF = 1 nếu AX = 0 b. ZF = 0 nếu AX lẻ c. SF = 1 nếu DX = 0 e. PF = 1 nếu BL chẵn. 3.6. Viết đoạn lệnh thực hiện từng yêu cầu sau: a. Xóa các bit ở vị trí chẵn của AX, giữ nguyên các bit khác. b. Đặt LSB và MSB của BL, giữ nguyên các bit khác. c. Đảo MSB của AL, giữ nguyên các bit khác. d. Xóa bốn bít cao của DL, giữ nguyên các bit khác. 3.7. Cho biết nội dung DX, AX và các cờ OF, CF sau khi thực hiện lệnh: a. MUL BX ; với AX = 08h, BX = 03h b. MUL BX ; với AX = 0FFFFh, BX = 1000h c. DIV BX ; với AX = 07h, BX = 02h, DX = 0h d. DIV CX ; với AX = 0FFFEh, CX = 10h, DX = 0h Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 48
- Tập lệnh Intel-8086 và Kiểu định vị 3.8. Cho biết nội dung AX và các cờ OF, CF sau khi thực hiện lệnh: a. MUL BL ; với AL = 0ABh, BL = 10h b. MUL AH ; với AL = 0ABh, AH = 01h c. DIV BL ; với AX = 0Dh, BL = 03h d. DIV DL ; với AX = 0FEh, DL = 10h 3.9. Xem mô hình bộ nhớ trong hình C1. Cho AX = 500h, BX = 1000h, SI = 1500h, DI = 2000h, BETA Ô nhớ Địa chỉ là biến kiểu word nằm ở địa chỉ 1000h. Trong các 03h DS:3001h lệnh sau đây, nếu hợp lệ thì hãy cho biết địa chỉ của 00h DS:3000h các toán hạng nguồn hoặc thanh ghi và kết quả lưu 02h DS:2501h trong toán hạng đích. Nếu không hợp lệ thì giải 50h DS:2500h thích tại sao? 02h DS:2001h a. MOV DL, SI 00h DS:2000h b. MOV DX, [DI] 01h DS:1501h c. ADD AX, [SI] 50h DS:1500h d. SUB BX, [DI] 01h DS:1001h e. LEA BX, BETA[BX] 00h DS:1000h f. ADD [SI], [DI] Hình C1: Mô hình bộ nhớ g. ADD BH, [BL] h. ADD AH, [SI] i. MOV AX, [BX+DI+BETA] 3.10. Với khai báo dữ liệu: A DB 1, 2, 3 B DW 4, 5, 6 C LABEL WORD ; C chỉ là 1 nhãn kiểu word ; (không chiếm vùng nhớ) MSG DB ‘ABC’ và giả sử BX chứa địa chỉ của C. Hãy cho biết lệnh nào hợp lệ (nếu không thì giải thích) và trị của các toán hạng đích sau khi thi hành lệnh trong các trường hợp sau: a. MOV AH, BYTE PTR A b. MOV AX, WORD PTR B c. MOV AX, C d. MOV AX, MSG e. MOV AH, BYTE PTR C 3.11. Dùng thanh ghi BP và kiểu định vị nền để viết các lệnh thực hiện yêu cầu sau (không được dùng các lệnh PUSH và POP) a. Đưa 0 vào hai word ở đỉnh ngăn xếp. b. Sao chép 5 word ở đỉnh ngăn xếp vào mãng ARR lần lượt theo thứ tự (nghĩa là phần tử ở đỉnh ngăn xếp vào phần tử 1 của ARR, phần tử kế trong ngăn xếp vào phần tử thứ 2 của ARR, ) Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 49
- Hệ thống ngắt mềm Chương 4 HỆ THỐNG NGẮT MỀM 4.1. NHỮNG CƠ SỞ CỦA NGẮT MỀM Một bí quyết để lập trình thành công và hiệu quả cao trên máy tính kiểu IBM- PC là việc sử dụng có hiệu quả các chương trình phục vụ của BIOS (Basic Input Output System) được cài đặt sẳn ngay trong vùng nhớ ROM-BIOS của máy tính hay các chương trình phục vụ của hệ điều hành DOS. Ngắt mềm (hay Ngắt) là cách gọi tên ngắn gọn của các chương trình phục vụ này. Ngắt mềm là chương trình mã máy nhị phân (chính xác hơn là chương trình con) được thiết kế sẳn và tồn tại trong bộ nhớ của máy tính nhằm thực hiện các chức năng điều khiển phần cứng máy tính mỗi khi được gọi thực hiện. Khi đó, để điều khiển phần cứng nào thì người lập trình chỉ cần gọi các ngắt tương ứng để thực hiện công việc mà không cần phải biết đến cấu trúc của phần cứng là như thế nào, nguyên lý vận hành của phần cứng đó ra sao . đây là công việc rất khó khăn đối với người làm phần mềm không quen thuộc với phần cứng là những mạch điện tử. Các ngắt mềm xem như là cầu nối giữa phần cứng và các ngôn ngữ lập trình (kể cả hệ Ngôn Ngữ Lập Trình (Hợp Ngữ) điều hành). Chúng làm việc trực tiếp với phần cứng và các thiết bị ngoại vi, thực hiện những chức năng cơ bản nhất của hệ thống như đọc/ghi từng byte dữ liệu ở bàn phím, ra màn hình hoặc Ngắt DOS ở đĩa từ Hình 4.1 trình bày các cách giao tiếp với Ngắt ROM BIOS phần cứng của ngôn ngữ lập trình thông qua các ngắt hay trực tiếp. Giao tiếp trực tiếp sẽ khó khăn hơn rất nhiều so với giao tiếp thông qua các Ngắt. Phần Cứng - Ngoại Vi Các ngắt của BIOS thì luôn sẳn có trong máy tính IBM-PC, còn các ngắt DOS chỉ tồn tại Hình 4.1: Giao tiếp phần cứng đối với hệ điều hành DOS. Nghĩ là, nếu máy tính IBM-PC được cài đặt hệ điều hành UNIX thì trên máy đó không tồn tại các ngắt DOS. Hệ điều hành Windows được phát triển trên cơ sở của hệ điều hành DOS nên các ngắt DOS vẫn sử dụng được trên hệ điều hành Windows. Tất nhiên có một vài ngắt DOS không được phép sử dụng vì đảm bảo độ an toàn cho vận hành của hệ điều hành Windows. Toàn bộ tài liệu về các ngắt mềm được nhiều sách về lập trình hợp ngữ nêu lên đầy đủ. Giáo trình này chỉ giới thiệu những ngắt rất cơ bản và thường dùng. 4.2. SỬ DỤNG NGẮT TRONG HỢP NGỮ Khi sử dụng ngắt cần lưu ý một số yếu tố: - Chức năng của ngắt/hàm. - Tên ngắt/hàm: Dùng số hex từ 0h đến 0FFh - Tham số vào: Thanh ghi hay bộ nhớ do hàm qui định. - Tham số ra: Thanh ghi hay bộ nhớ do hàm qui định. Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 50
- Hệ thống ngắt mềm Lệnh gọi 1 ngắt hay 1 hàm: MOV AH, . ; Khai báo tham số vào (nếu có) INT . ; Lưu trữ tham số ra (nếu có) Ví dụ: Hàm 02h của ngắt 21h thực hiện việc in ký tự trong thanh ghi DL ra màn hình. Như vậy, khi muốn hiển thị ký tự B trên màn hình, ta viết như sau đoạn lệnh như sau: MOV AH, 02h ; Chọn hàm 02h MOV DL, ‘B’ ; DL chứa ký tự cần in ‘B’ INT 21h ; Gọi ngắt thực hiện để in ký tự Lưu ý: Việc sử dụng thanh ghi DL để chứa ký tự cần in là do hàm 02h qui định, không thể sử dụng thanh ghi khác để thay thế. 4.3. NGẮT MS-DOS Các ngắt của DOS được đánh số từ 20h đến 0FFh. Ngắt quan trọng nhất là ngắt 21h – gồm nhiều chức năng (hàm) của DOS. INT 20h: Chấm dứt chương trình và trở về DOS từ một chương trình có đuôi COM. INT 23h: Chặn tổ hợp phím Ctrl- Break Người sử dụng có thể chấm dứt sớm một chương trình bằng cách bấm tổ hợp phím Ctrl-Break. Tổ hợp phím nầy làm CPU nhảy tới chương trình phục vụ ngắt 23h và sau đó đến một thủ tục của DOS để kết thúc chương trình đang chạy và trở về DOS. Nếu muốn không cho phép chương trình kết thúc sớm bằng Ctrl-Break, ta có thể cho ngắt 23h trỏ đến một chương trình đặt biệt nào đó để thông báo lên màn hình rằng không cho chương trình đang chạy kết thúc sớm. INT 27h: Kết thúc và đặt thường trú Ngắt này cho phép để trong bộ nhớ trong một chương trình nào đó cho đến khi tắt máy. Để sử dụng ngắt 27h, ta cho chạy một chương trình gồm 2 phần. Một phần sẽ phụ trách việc thường trú cho phần kia. INT 21h: Các chức năng của DOS Hàm 01h Đợi đọc 1 ký tự từ bàn phím (có hiện trên màn hình) Vào Không Ra AL : Mã ASCII của phím nhận được Đợi đọc một ký tự từ bàn phím (phím nhận được sẽ hiển thị trên màn hình). Khi một phím được ấn thì ký tự tương ứng với phím đó được lưu trong thanh ghi AL. Nếu phím được ấn là một phím đặt biệt thì AL=0. Tổ hợp phím Ctrl-Break kết thúc công việc của hàm này. Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 51
- Hệ thống ngắt mềm Hàm 02h Hiển thị 1 ký tự tại vị trí con trỏ trên màn hình Vào DL ← Mã ASCII của ký tự cần hiển thị Ra Không Hàm 03h Đọc dữ liệu vào từ cổng nối tiếp chuẩn (COM1) Vào Không Ra AL : byte dữ liệu đọc được Hàm 04h Xuất ký tự ra cổng nối tiếp chuẩn (COM1) Vào DL ← ký tự cần xuất Ra Không Hàm 05h Xuất byte dữ liệu ra cổng máy in chuẩn (LPT1) Vào DL : Byte dữ liệu cần xuất Ra Không Hàm 06h Nhập / Xuất từ thiết bị chuẩn (không đợi) DL ← Mã ASCII ký tự cần xuất lên màn hình Vào Nếu DL ← 0FFh : Thực hiện chức năng nhập ký tự Nếu ZF = 0 thì AL chứa Mã ASCII ký tự nhận được Ra Nếu ZF = 1 thì không nhận được ký tự Hàm 07h Giống hàm 1, nhưng không hiện ký tự ra màn hình Vào Không Ra AL : Mã ASCII ký tự nhận được Hàm 08h Giống hàm 1, nhưng không hiện ký tự ra màn hình Vào Không Ra AL : Mã ASCII ký tự nhận được Lưu ý: Ctrl-Break không ảnh hưởng đến hoạt động của hàm 07h và 08h Hàm 09h Xuất 1 chuỗi ký tự lên màn hình Vào DS:DX ← địa chỉ logic của chuỗi ký tự cần xuất Ra Không Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 52
- Hệ thống ngắt mềm Lưu ý: DS ← địa chỉ segment của chuỗi trong bộ nhớ DX ← địa chỉ offset của chuỗi trong bộ nhớ Chuỗi ký tự phải chấm dứt bằng ký tự ‘$’ Ví dụ: In chuỗi “Hello Assembly” ra màn hình. Khai báo biến chứa chuỗi trong đoạn dữ liệu DS: chuoi DB ‘Hello Assembly$’ Viết chương trình trong đoạn lệnh: MOV AH, 09h ; Gọi hàm 09h LEA DX, chuoi ; DX ← Offset(chuoi) INT 21h ; Thực hiện hàm Hàm 0Ah Đợi đọc 1 chuỗi ký tự từ bàn phím, kết thúc bằng Enter Vào DS:DX ← địa chỉ của vùng đệm bàn phím trong bộ nhớ LEN: Tổng số ký tự nhận được Ra BUFF: Mã ASCII của các ký tự nhận được Hàm 0Ah nhận 1 chuỗi ký tự từ bàn phím, kết thúc bằng phím Enter (Mã ASCII là 0Dh). Hàm trả về chuỗi nhận được và chiều dài chuỗi trong vùng đệm bàn phím. Vùng đệm bàn phím là 1 biến mãng trong bộ nhớ gồm 3 phần MAX, LEN và BUFF có cấu trúc như sau: MAX LEN BUFF BUFF+1 BUFF+2 BUFF+n MAX: Phần tử chứa số ký tự tối đa có thể nhận được gán khi khai báo. LEN: Phần tử chứa tổng số ký tự của chuỗi nhận được, do hàm trả về sau khi nhận được chuỗi. BUFF: Phần tử chứa mã ASCII của từng ký tự trong chuỗi nhận được (mỗi ký tự chiếm 1 byte nhớ). Như vậy, số byte của BUFF phải bằng hay lớn hơn giá trị của MAX. Ví dụ: Nhận chuỗi tối đa 30 ký tự từ bàn phím Khai báo vùng đệm trong đoạn dữ liệu: MAX DB 30 ; Tạo biến MAX LEN DB ? ; Tạo biến LEN BUFF DB 31 DUP(?) ; Vùng nhớ lưu trữ ký tự Viết chương trình trong đoạn lệnh: MOV AH, 0Ah LEA DX, MAX ; DX ← Đ/c vùng đệm bàn phím INT 21h Cách khai báo biến vùng đệm bàn phím khác: BANPHIM DB 30, ?, 31 DUP(?) Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 53
- Hệ thống ngắt mềm Hàm 0Bh Cho trạng thái bàn phím Vào DS:DX ← địa chỉ logic của vùng đệm bàn phím trong bộ nhớ LEN: Tổng số ký tự nhận được Ra BUFF: Mã ASCII của các ký tự nhận được Hàm 3Ch Tạo tập tin mới DS:DX ← Địa chỉ chuỗi tên của tập tin mới. Vào CX ← thuộc tính của tập tin (0: bình thường, 1: chỉ đọc, 2: ẩn, 4: tập tin hệ thống) Ra AX : Thẻ tập tin Hàm 3Dh Mở tập tin trên đĩa DS:DX ← Địa chỉ chuỗi tên của tập tin mới. Vào AL ← kiểu truy xuất tập tin (0: chỉ đọc, 1: chỉ ghi, 2: đọc/ghi) Ra AX : Thẻ tập tin Khai báo tên tập tin và biến chứa thẻ file: Tenf DB “C:\DULIEU\DATA.TXT”,0 Thef DW ? Chuỗi Tên tập tin có chứa cả tên đường dẫn của file. Nếu không có tên đường dẫn thì sẽ truy xuất trong thư mục hiện hành. Thẻ tập tin là thành phần quan trọng trong việc truy xuất file nên sau khi mở hay tạo file phải lưu trữ lại để sử dụng trong việc đọc/ghi file. Mỗi file phải có một thẻ file, biến thẻ file phải là 2 bytes. MOV Thef,AX ;Lưu trữ thẻ file vào biến. MOV BX,Thef ;Đưa thẻ file vào BX để truy xuất file Có thể mở hay tạo nhiều tập tin khác nhau trong cùng chương trình để xử lý. Khi đó, mỗi thẻ tập tin phải được lưu trữ trong mỗi biến khác nhau. Hàm 3Eh Đóng tập tin đang mở. Vào BX ← Thẻ tập tin Ra AX : Mã lỗi (nếu có) Sau khi xử lý xong tập tin và trước khi thoát khỏi chương trình, tập tin phải được đóng lại để cập nhật thông tin hoặc nội dung mới của tập tin. Hàm 3Fh Đọc nội dung tập tin vào bộ nhớ DS:DX ← Địa chỉ vùng nhớ chứa dữ liệu đọc được Vào BX ← Thẻ tập tin cần đọc CX ← số byte cần đọc Ra AX : Số byte đọc được Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 54
- Hệ thống ngắt mềm Hàm 40h Ghi dữ liệu trong bộ nhớ vào tập tin DS:DX ← Địa chỉ vùng nhớ chứa dữ liệu cần ghi Vào BX ← Thẻ tập tin cần đọc CX ← số byte cần ghi Ra AX : Số byte ghi được Các hàm 3Fh và 40h cũng có thể được sử dụng đọc hoặc ghi dữ liệu cho ngoại vi, vì DOS quản lý việc truy xuất ngoại vi bằng thẻ Hàm 41h Xóa tập tin trên đĩa Vào DS:DX ← Địa chỉ chuỗi tên tập tin Ra AX : Mã lỗi (nếu có) Hàm 42h Đời con trỏ tập tin hiện hành Vào AL ← Hướng dời CX:DX ← Cự ly dời = (CX*65536) + DX BX ← Thẻ tập tin Ra DX:AX : Vị trí con trỏ mới = (DX*65536)+AX Cấu trúc dữ liệu trong tập tin: 0 1 2 3 4 5 6 7 8 9 10 11 12 ‘C’ ‘h’ ‘a’ ‘o’ ‘ ‘ ‘C’ ‘a’ ‘c’ ‘ ‘ ‘B’ ‘a’ ‘n’ EOF Con trỏ tập tin hiện hành Hàm 43h Đọc hoặc thay đổi thuộc tính tập tin trên đĩa DS:DX ← Địa chỉ chuỗi tên tập tin Vào Nếu Đọc thuộc tính: AL ← 0 Nếu Thay đổi thuộc tính: AL ← 1vàCX ← thuộc tính mới Ra Nếu Đọc thuộc tính: CX : chứa thuộc tính tập tin Hàm 4Ch Kết thúc chương trình và trở về DOS Vào Không Ra Không Hàm 56h Đổi tên tập tin DS:DX ← Địa chỉ chuỗi tên tập tin cũ Vào ES:DI ← Địa chỉ chuỗi tên tập tin mới Ra Không Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 55
- Hệ thống ngắt mềm 4.4 CÁC VÍ DỤ: 4.4.1. Chương trình nhận 1 ký tự từ bàn phím, sau đó cất ký tự nhận được vào 1 biến. DSEG SEGMENT msg DB ‘Hay nhap 1 ky tu tu ban phim: $’ kytu DB ? ; Biến chứa ký tự nhận được DSEG ENDS CSEG SEGMENT ASSUME CS: CSEG, DS: DSEG start: MOV AX, DSEG MOV DS, AX MOV AH, 09 ; Hàm 9 in chuỗi ký tự ra màn hình LEA DX, msg ; DX chứa địa chỉ chuỗicần in INT 21h ; gọi ngắt thực hiện MOV AH, 01 ; Hàm nhập 1 ký tự, AL chứa Ký tự INT 21h MOV kytu, AL ; Cất Ký tự vào biên MOV AH, 4Ch ; thoát khỏi chương trình INT 21h CSEG ENDS END start 4.4.2. Chương trình nhận 1 ký tự từ bàn phím, sau đó in ra màn hình ký tự kế sau của ký tự nhận được. DSEG SEGMENT msg1 DB ‘Hay nhap 1 ky tu tu ban phim: $’ msg2 DB 10,13,‘Ky tu ke sau ky tu nhan duoc la: $’ kytu DB ? DSEG ENDS CSEG SEGMENT ASSUME CS: CSEG, DS: DSEG start: MOV AX, DSEG MOV DS, AX MOV AH, 09 ; Hàm 9 in chuỗi ký tự ra màn hình LEA DX, msg1 ; DX chứa địa chỉ chuỗi msg1 INT 21h ; gọi ngắt thực hiện MOV AH, 01 ; Hàm nhập 1 ký tự, AL chứa Ký tự INT 21h MOV kytu, AL ; cất ký tự vào biến MOV AH, 09 ; Hàm 9 in chuỗi ký tự ra màn hình LEA DX, msg2 ; DX chứa địa chỉ chuỗi msg2 INT 21h ; gọi ngắt thực hiện Ths. Nguyễn Hứa Duy Khang, Ks. Trần Hữu Danh 56