Giáo trình Hợp ngữ với nội dung gồm 8 chương đem tới cho các bạn nội dung sau: Gọi ngắt và trình debug; hợp ngữ dùng trong PC; phương pháp lập trình, ngăn xếp và thủ tục, mođun chương trình và các kiểu định vị địa chỉ, sử dụng phân đoạn toàn phần, chương trình ứng dụng... Mời các bạn cùng tham khảo giáo trình.
Trang 1F 7 G
GIÁO TRÌNH
HỢP NGỮ NGUYỄN HỮU LỘC
2002
Trang 2MỤC LỤC
LỜI MỞ ĐẦU 4
CHƯƠNG 1: GIỚI THIỆU CHUNG 5
I CÁC THANH GHI TRONG VI XỬ LÝ HỌ INTEL: 5
1 Các thanh ghi thông dụng: 6
2 Các thanh ghi phân đoạn 7
3 Các thanh ghi chỉ mục và con trỏ: 7
4 Thanh ghi trạng thái (FLAG) 8
II ĐỊA CHỈ Ô NHỚ: 8
III MỘT SỐ LỆNH CƠ BẢN: 9
CHƯƠNG 2: GỌI NGẮT VÀ TRÌNH DEBUG 11
I CÁC LỆNH GỌI NGẮT: 11
II TRÌNH DEBUG: 12
III VÀI CHƯƠNG TRÌNH ỨNG DỤNG : 15
CHƯƠNG 3: HỢP NGỮ DÙNG TRONG PC 19
I DÒNG LỆNH: 19
II DỮ LIỆU: 20
1 Hằng: 20
2 Biến: 21
III CẤU TRÚC CHƯƠNG TRÌNH: 22
CHƯƠNG 4: PHƯƠNG PHÁP LẬP TRÌNH 27
I TỔNG QUAN: 27
II CÁC LỆNH LIÊN QUAN ĐẾN RẼ NHÁNH: 27
1 Các lệnh rẽ nhánh có điều kiện: 28
2 Các lệnh rẽ nhánh không điều kiện: 29
III CÁC CẤU TRÚC ĐIỀU KHIỂN: 29
CHƯƠNG 5: NGĂN XẾP VÀ THỦ TỤC 38
I NGĂN XẾP: 38
II THỦ TỤC: 38
III SỬ DỤNG PTR VÀ LABEL: 40
IV VÀI CHƯƠNG TRÌNH ỨNG DỤNG: 41
1 Hiện số thập phân: 41
2 Hiện số nhị phân và thập lục phân 44
3 Đọc từ bàn phím 46
Trang 3CHƯƠNG 6: MOĐUN CHƯƠNG TRÌNH & CÁC KIỂU ĐỊNH VỊ ĐỊA CHỈ 51
I MOĐUN CHƯƠNG TRÌNH 51
1 Định hướng biên dịch extrn 51
2 Định hướng biên dịch public 52
3 Lập thư viện - tạo vĩ lệnh (macro) 54
II CÁC KIỂU ĐỊNH VỊ ĐỊA CHỈ 56
III CHƯƠNG TRÌNH ỨNG DỤNG 60
IV TẠO TẬP TIN COM 67
1- Dạng của một chương trình COM 68
2- Ưùng dụng tập tin com 69
CHƯƠNG 7: SỬ DỤNG PHÂN ĐOẠN TOÀN PHẦN 76
I- SỬ DỤNG CÁC ĐỊNH HƯỚNG BIÊN DỊCH 76
1 Segment 76
2 Định hướng biên dịch assume 79
II - DẠNG CỦA CHƯƠNG TRÌNH EXE SỬ DỤNG TRONG CÁC PHƯƠNG PHÁP CŨ: 79
III- VÍ DỤ CHƯƠNG TRÌNH COM 83
CHƯƠNG 8: CHƯƠNG TRÌNH ỨNG DỤNG 85
I IN NỘI DUNG VĂN BẢN RA MÁY IN: 85
1 Sử dụng hàm 40h ngắt 21h (DOS) để thực hiện 85
2 Sử dụng hàm 01h ngắt 17h (ROMBIOS) 85
II ĐẾM SỐ TỪ TRONG MỘT TẬP TIN 86
III- ĐỔI NGƯỢC CHUỖI 89
IV CHƯƠNG TRÌNH HIỂN THỊ THỜI GIAN 90
V CHƯƠNG TRÌNH THƯỜNG TRÚ BỘ NHỚ 97
Phụ lục A: MỘT SỐ CHƯƠNG TRÌNH PHỤC VỤ CỦA DOS 105
Phụ lục B: MỘT SỐ CHƯƠNG TRÌNH PHỤC VỤ CỦA ROM-BIOS 108
TÀI LIỆU THAM KHẢO 110
Trang 4LỜI MỞ ĐẦU
Hợp ngữ là một môn học dành cho sinh viên các chuyên ngành kỹ thuật Là một ngôn ngữ can thiệp sâu vào hệ thống máy tính, hợp ngữ thường được sử dụng trong những phần việc tương đối tinh tế như điều khiển hệ thống, vi điều khiển
Tuy vậy với những người lần đầu tiên làm quen với ngôn ngữ này, việc tiếp thu quả thật rất khó khăn bởi lẽ ngôn ngữ này gần với ngôn ngữ máy và sử dụng các ký tự gợi nhớ nên khó hiểu hơn sử dụng các ngôn ngữ cấp cao như Pascal, C v.v Ngoài ra, người học không những phải biết phần mềm mà còn phải hiểu phần cứng ở mức độ nào đó nữa Điều này tạo ra một áp lực rất lớn gây khó khăn cho người học
Trong nhiều năm giảng dạy môn này, tôi nhận thấy hiện có rất nhiều sách, tài liệu tham khảo viết về hợp ngữ song để có một tài liệu đáp ứng yêu cầu của sinh viên trong việc tiếp thu môn hợp ngữ tuần tự từ dễ đến khó có phương pháp thì thật hiếm
Do vậy tôi thực hiện giáo trình này với mong ước có một tài liệu đáp ứng yêu cầu trên Trong giáo trình, tôi có đưa vào rất nhiều ví dụ và ứng dụng từ thấp đến cao để sinh viên có thể tiếp thu dễ dàng môn học này
Tuy vậy tài liệu này không sao tránh khỏi những sai sót, rất mong các đồng nghiệp, sinh viên và bạn đọc góp ý
Hoàn thành giáo trình này, tôi xin chân thành cám ơn đến các đồng nghiệp trong Khoa Vật lý Trường Đại học Dalat đã động viên, góp ý và tạo điều kiện cho tôi trong quá trình thực hiện Tôi cũng xin ghi nhận sự đóng góp của nhiều thế hệ sinh viên khoa vật lý, khoa toán - tin để giáo trình này được sắp xếp ngày càng dễ hiểu và hợp lý hơn
Nguyễn Hữu Lộc
Trang 5CHƯƠNG 1: GIỚI THIỆU CHUNG
Tại sao chúng ta phải học lập trình với hợp ngữ trong khi hiện nay có rất nhiều ngôn ngữ cấp cao như C hoặc Pascal dùng để lập trình dễ dàng hơn? Có thể nói có nhiều câu trả lời cho câu hỏi này Nhưng ban đầu, chúng
ta có thể xét đối với hợp ngữ thì mỗi lệnh tương ứng với một lệnh ngôn ngữ máy Nói cách khác, nếu mỗi dòng lệnh trong chương trình là một lệnh hợp ngữ và một từ máy tương ứng với một lệnh máy như vậy n dòng trong chương trình sẽ tạo ra một chương trình máy gồm n từ Như vậy hợp ngữ có thể xem là ngôn ngữ rất gần với ngôn ngữ máy, chúng ta có thể tiếp cận đến tất cả các ngóc ngách của máy và quan trọng hơn là chúng ta thực hiện chương trình viết bằng hợp ngữ nhanh hơn so với viết bằng những ngôn ngữ cấp cao khác Tuy vậy cũng cần thấy rằng rất nhiều ngôn ngữ cấp cao hổ trợ giao diện với hợp ngữ, nói cách khác là chúng ta có thể viết 1 đoạn hợp ngữ trong chương trình viết bằng ngôn ngữ cấp cao như C hoặc Pascal Điều này cho phép chúng ta lập trình hiệu quả hơn với những phần việc sát với hệ thống và đòi hỏi thời gian nhanh
Trong kiến trúc máy tính nhiều cấp, việc chuyển một chương trình của người sử dụng từ một ngôn ngữ này sang chương trình dùng ngôn ngữ
khác gọi là chương trình dịch Ngôn ngữ sử dụng để viết chương trình ban đầu gọi là ngôn ngữ nguồn còn ngôn ngữ sau khi dịch gọi là ngôn ngữ đích
Người ta phân biệt các chương trình dịch ra làm hai loại tùy theo mối quan hệ giữa ngôn ngữ nguồn và ngôn ngữ đích Khi ngôn ngữ nguồn gồm những ký tự gợi nhớ lệnh của ngôn ngữ máy thì chương trình dịch sẽ gọi
là hợp dịch (assembler) và ngôn ngữ nguồn là hợp ngữ (assembly language)
Trong khi đó ngôn ngữ nguồn là ngôn ngữ cấp cao như C hoặc Pascal thì
chương trình dịch sẽ gọi là biên dịch
I CÁC THANH GHI TRONG VI XỬ LÝ HỌ INTEL:
Trang 6Bộ vi xử lý 8088 có thể địa chỉ hóa đến 220 byte bắt đầu từ địa chỉ 0 Những lệnh của 8088 có thể thực hiện với những từ 8 bit hay byte cũng như với những từ 16 bits
8088 sử dụng những địa chỉ 20 bits để truy cập đến 220 byte ô nhớ Vì các thanh ghi có chiều dài là 16 bits nên các địa chỉ dùng 20 bits sẽ có khó khăn trong thực hiện Để giải quyết vấn đề này, những nhà sản xuất bộ vi xử lý đã sử dụng 4 thanh ghi phân đoạn (một dùng cho lệnh, một cho dữ liệu, một cho ngăn xếp và một dự trữ)
Những thanh ghi có thể xem là những ô nhớ nằm bên trong bộ vi xử lý có thời gian truy xuất cao, với 8088, chúng ta có 14 thanh ghi chia ra làm 4 loại:
- Các thanh ghi làm việc;
- Các thanh phân đoạn;
- Các thanh ghi bước nhảy (offset);
- Thanh ghi trạng thái (Cờ: FLAG)
1 Các thanh ghi thông dụng:
Bao gồm 4 thanh ghi Mỗi thanh ghi đều có những chức năng riêng mặc dù chúng cũng là những nơi lưu trữ những kết quả trung gian:
AX là thanh ghi 16 bit gọi là thanh ghi tích lũy (Accumulator) sử dụng khi thực hiện các phép tính số học
BX là thanh ghi 16 bit gọi là thanh ghi nền (Base register)
CX là thanh ghi 16 bit gọi là thanh ghi đếm (Counter)
DX là thanh ghi 16 bit gọi là thanh ghi dữ liệu (Data)
Nên biết rằng mỗi thanh ghi này đều có thể phân ra làm hai thanh ghi 8 bit sử dụng riêng rẽ được:
Trang 72 Các thanh ghi phân đoạn
Gồm 4 thanh ghi:
CS viết tắt từ "Code Segment", là nơi lưu trữ địa chỉ của phân đoạn bộ nhớ tại đó các lệnh trong chương trình nạp vào (mã máy)
DS viết tắt từ "Data Segment", là nơi lưu trữ địa chỉ của phân đoạn bộ nhớ tại đó đặt dữ liệu (data) của chương trình
SS viết tắt từ "Stack Segment", là nơi lưu trữ địa chỉ của phân đoạn ngăn xếp
ES viết tắt từ "Extra Segment", là nơi lưu trữ địa chỉ của phân đoạn dự trữ thường dùng ghi giữ dữ liệu
3 Các thanh ghi chỉ mục và con trỏ:
Các thanh ghi này giữ giá trị bước nhảy (offset ) kết hợp với địa chỉ phân đoạn Tổng cộng có 5 thanh ghi:
SI viết tắt từ "Source Index" Thanh ghi này là thanh ghi 16 bit sử dụng khi thực hiện các phép toán với chuỗi (dãy ký tự); thường được dùng kết hợp với thanh ghi phân đoạn DS
DI viết tắt từ "Destination Index" Thanh ghi này cũng là thanh ghi
16 bit sử dụng khi thực hiện các phép toán với chuỗi (dãy ký tự); thường được dùng kết hợp với thanh ghi phân đoạn DS Tuy nhiên trong trường hợp chuyển chuỗi thì nó sẽ kết hợp với thanh ghi phân đoạn ES
BP hoặc "Base Pointer" Thanh ghi 16 bit này kết hợp với thanh ghi phân đoạn
SS (SS:BP) để đưa dữ liệu vào trong ngăn xếp khi gọi chương trình con (CALL)
SP hoặc "Stack Pointer" Thanh ghi 16 bit này cũng kết hợp với thanh ghi phân đoạn SS (SS:SP) để chỉ ra phần tử cuối của ngăn xếp
IP gọi là con trỏ lệnh (Instruction Pointer) Thanh ghi 16 bit này kết hợp với thanh ghi phân đoạn CS (CS:IP) để chỉ đến lệnh tiếp theo sẽ thực hiện Nội dung của
Trang 8thanh ghi này không thể thay đổi trực tiếp; nó chỉ bị thay đổi một cách gián tiếp thông qua các lệnh nhảy bước, qua các chương trình con và qua các ngắt
4 Thanh ghi trạng thái (FLAG)
Thanh ghi trang thái là thanh ghi gồm 16 bit (Cờ) Giá trị của từng bit một trong thanh ghi này độc lập với các bit khác trong cùng thanh ghi Người ta thường xử lý từng bit một và một số bit có ảnh hưởng đến hoạt động của chương trình Những bit này gọi là các chỉ báo (indicator) có thể chia ra làm 2 loại:
Các chỉ báo trạng thái:
4 Nhớ phụ (Auxiliairy carry) AF
Các chỉ báo điều khiển
Các bit 1, 5, 12, 13, 14, 15 của thanh ghi trạng thái 16 bit không được sử dụng
II ĐỊA CHỈ Ô NHỚ:
Bộ nhớ của 1 máy tính bao gồm 1 dãy tuần tự các ô nhớ được đánh số trong đó lưu giữõ 1 giá trị số nào đó Số tương ứng của 1 ô nhớ gọi là địa chỉ, mỗi ô nhớ giữ 8 bit Trên những máy tính IBM PC, bộ nhớ được chia thành các vùng 65536 byte gọi là phân
đoạn, địa chỉ của 1 ô nhớ sẽ bao gồm 2 phần: số phân đoạn và bước nhảy (offset) tính từ vị
trí ban đầu của phân đoạn; nó sẽ có dạng:
Phân đoạn: bước nhảy
(Segment:Offset)
Trang 9Các lệnh chiếm một hoặc nhiều ô nhớ kế tiếp trong bộ nhớ, điều này phụ thuộc vào độ phức tạp của lệnh
III MỘT SỐ LỆNH CƠ BẢN:
MOV: là một trong những lệnh chính của hợp ngữ Nội dung của toán hạng bên
phải sẽ chuyển sang toán hạng bên trái
Ví dụ:
LEA:(Load Effective Address) tương tự như MOV ,OFFSET
Ví dụ:LEA DX,MSG thay vì MOV DX, OFSET MSG
ADD: cộng 2 số 8 bit hoặc 16 bit, kết quả đưa vào bộ nhớ hoặc thanh ghi
ADC: thực hiện lệnh cộng như ADD sau đó thêm giá trị có trong chỉ báo CARRY
vào kết quả nhận được
MUL: nhân toán hạng cho trước với một lượng đặt trong thanh AX hoặc AL
(accumulator) Kết quả sẽ đặt vào AH và AL nếu các toán hạng là byte và đặt trong
DX và AX nếu toán hạng là từ (word)
Ví dụ:
DIV: chia 1 từ (số bị chia trong AX) bởi 1 toán hạng 8 bit (số chia) hoặc chia 1 từ
đôi - double word (trong DX, AX) bởi một toán hạng 16 bit Thương số sẽ đặt trong
AL và số dư đặt trong AH nếu toán hạng là một byte và thương số sẽ đặt trong AX và số dư đặt trong DX nếu sử dụng 1 từ-word
Trang 10CMP: cho phép so sánh nội dung hai thanh ghi hoặc ô nhớ So sánh là thực hiện 1
phép trừ tuy nhiên mục đích đạt được không phải là kết quả của phép trư ø mà chủ yếu là so sánh hai toán hạng do vậy sau lệnh so sánh thường thấy lệnh nhảy bước có điều kiện phụ thuộc vào các chỉ báo trong quá trình so sánh
LOOP: lặp lại lúc này thanh ghi CX giảm 1 đơn vị và thực hiện một sự rẽ nhánh
đến một nhãn cho trước cho đến khi CX bằng 0
Ví dụ:
RCL: dịch chuyển tất cả các bit về phía trái một vị trí hoặc nhiều vị trí Những bit
ra khỏi bên TRÁI sẽ vào chỉ báo CARRY trước khi đưa lại vào bên phải của toán hạng
Trang 11CHƯƠNG 2: GỌI NGẮT VÀ TRÌNH DEBUG
I CÁC LỆNH GỌI NGẮT:
Một máy tính thường có rất nhiều loại thiết bị ngoại vi quan trọng như bàn phím, màn hình, đĩa, máy in, v.v Muốn điều khiển các thiết bị này đòi hỏi chúng ta phải viết chương trình bằng các lệnh máy dài dòng và phức tạp Nhờ sự giúp đỡ của hệ điều hành MSDOS hoặc ROM-BIOS chúng ta có thể tác động một thiết bị ngoại vi bằng cách chỉ sử dụng 1 hàm được đánh số vào chương trình kèm theo một số các thông số Tất cả điều này đều thực hiện thông qua các thanh ghi Những hàm này gọi là ngắt
Lệnh INT là lệnh gọi ngắt được đánh số tại vị trí toán hạng được xem như gọi một chương trình con Một ngắt có thể bao gồm nhiều dịch vụ, số của dịch vụ được đưa vào thanh ghi AH trước khi gọi ngắt
Ví dụ 1: Hiện 1 ký tự ASCII lên màn hình
Ví dụ 3: Hiện 1 thông báo lên màn hình
Chao DB 'Chao cac ban $'
Trang 12Chúng ta có thể tham khảo các hàm này trong tài liệu "Cẩm nang cho người lập trình máy vi tính IBM PC" - tác giả Peter Norton
II TRÌNH DEBUG:
Một trong hai cách để viết chương trình bằng hợp ngữ là sử dụng phần mềm DEBUG Chúng ta cần phải có một tập tin tên DEBUG.EXE sử dụng trong hệ điều hành MSDOS
Có thể xem DEBUG là một công cụ giúp chúng ta lập trình bằng hợp ngữ ban đầu vì những lý do sau:
- DEBUG sử dụng dễ hơn MASM
- Chúng ta có thể thử nghiệm các chương trình nhỏ dễ dàng trước khi đưa chúng vào trong những chương trình lớn, phức tạp hơn
DEBUG có 19 lệnh Các lệnh này dùng mẫu tự đầu của từ tiếng Anh để gợi nhớ ý nghĩa của lệnh
A Assemble Hợp dịch 1 chương trình
C Compare So sánh 2 vùng của bộ nhớ
D Dump Trình bày một vùng của bộ nhớ bằng hex và
ASCII
E Enter Nhập mã máy vào bộ nhớ
F Fill Lắp đầy một vùng nhớ
G Go Thực hiện một chương trình
H Hexadecimal Cộng và trừ 2 số hex
I Input Nhập và trình bày từ cổng
L Load Nhập một tập tin từ đĩa vào bộ nhớ
M Move Chuyển một khối nhớ
N Name Đặt tên một tập tin
P Proceed Thực hiện thủ tục hay một ngắt
R Register Trình bày giá trị thanh ghi
Trang 13S Search Tìm một chuỗi byte trong bộ nhớ
T Trace Cho chương trình chạy từng lệnh một
Để khởi động trình DEBUG, người ta đánh lệnh sau:
DEBUG
- Một gạch ngang (hyphen) xuất hiện thông báo cho chúng ta biết DEBUG đang đợi lện tiếp
Những lệnh DEBUG thường sử dụng:
Q (Quit): Dừng thực hiện DEBUG, về lại hệ điều hành
D (Dump Memory): Hiện nội dung một vùng nhớ
- Nội dung của các thanh ghi trong hệ cơ số 16 (hexadécimal)
- Nội dung của thanh ghi trạng thái
Trang 14A (Assemble): nhập lệnh hợp ngữ Chú ý, DEBUG chỉ dùng số trong hệ cơ số
16 chứ không dùng hệ cơ số nào khác
Ví dụ: A 100 6800:0100 MOV AX,FFFF
G (Go): Thực hiện chương trình
N (Name): Đặt tên tập tin
Trang 15T (Trace): thực hiện chương trình tuần tự từng lệnh một có thông báo nội dung của các thanh ghi thay đổi sau mỗi lệnh
III VÀI CHƯƠNG TRÌNH ỨNG DỤNG :
Chương trình 1: Hiện 1 ký tự (♦) lên màn hình
Trang 16* Sinh viên có thể đặt tên rồi lưu vào đĩa
Cách 2: Sử dụng giả lệnh DB
Trang 19CHƯƠNG 3: HỢP NGỮ DÙNG TRONG PC
Hiện nay khi viết chương trình bằng hợp ngữ, chúng ta thường sử dụng trình dịch MICROSOFT MACRO ASSEMBLER (MASM) Cũng giống tất cả các ngôn ngữ lập trình khác như Basic, Pascal, C đều phải thông qua dịch thì máy tính mới hiểu được lệnh sau khi đã tạo ra mã nguồn trong một môi trường kết hợp soạn thảo Để soạn thảo một chương trình bằng hợp ngữ chúng ta chỉ cần sử dụng một trình soạn thảo văn bản ASCII ví dụ như Sidekick, phần soạn thảo trong Norton Commander v.v và sau đó sẽ lưu giữ vào tập tin ASCII trên đĩa Bước tiếp theo là dịch mã nguồn sang mã máy nhờ trình dịch (Assembler)
Chương trình được lưu trên đĩa là một tập tin có phần mở rộng ASM được soạn thảo bằng một phần mềm soạn thảo văn bản (ASCII) trong đó các chữ cái viết HOA đều được xử lý như những chữ cái viết thường trừ trường hợp đặt trong 1 chuỗi (dãy ký tự)
Các chương trình bao gồm những dòng lệnh Mỗi dòng lệnh là một lệnh được dịch sang mã máy bằng các trình dịch
Batdau: MOV CX,5 ; đặt số đếm ban đầu
Các vùng khác nhau phải ngăn cách bởi ít nhất một khoảng trống (space) hoặc TAB, các toán hạng trong một lệnh phải các nhau bởi 1 dấu phẩy (trong trường hợp này không cần thiết phải có khoảng trống)
Trang 20Các tên được lập trình viên tự do đặt để xác định nhãn, biến, thủ tục, v.v Tên gồm các ký tự theo yêu cầu sau: Ký tự thứ nhất là chữ cái, số ký tự tối đa là 31 và không có khoảng trống trong tên
Những phép toán là những ký tự gợi nhớ lệnh: MOV, ADD, INC hoặc giả lệnh (pseudo-instruction): DB, PROC
Những toán hạng trong một lệnh sẽ ngăn cách bằng một dấu phẩy Nếu có 2 toán hạng thì toáng hạng thứ nhất là đích còn toán hạng thứ hai là nguồn
Chúng ta cũng thấy có thể đưa thêm chú thích để dễ theo dõi đọc chương trình Dấu ";" phải được sử dụng trước khi ghi chú thích
II DỮ LIỆU:
1 Hằng:
Hằng là một giá trị xác định bằng một lệnh hay đúng hơn là một giả lệnh hợp ngữ, giá trị này được lập trình viên định nghĩa là không thay đổi trong quá trình thực hiện chương
Giả lệnh EQU là lệnh hợp ngữ dùng để định nghĩa một hằng ứng với một tên được lập trình viên đặt cho
Ví dụ: Dung EQU 1
Những hằng tức thời (immédiate) là:
Những chữ sốá do lập trình viên đặt ra có thể sử dụng trong các hệ cơ số khác nhau Do vậy nên thêm chữ cái "h" sau những số dùng trong hệ cơ số 16, và thêm chữ cái "b" sau tất cả các số nhị phân vì trình dịch hợp ngữ mặc nhiên chỉ làm việc trong hệ cơ số 10 (thập phân) (cần chú ý là trình DEBUG chỉ làm việc với hệ cơ số 16)
Ví dụ: 1B4Dh, 1100b
Những chữ số trong hệ cơ số 16 (hexadecimal) bắt đầu bằng một chữ cái thì phải thêm vào một số "0" nếu không trình dịch hợp ngữ sẽ xem như một TÊN và thông báo lỗi
Trang 21Những ký tự: Những ký tự hoặc chuỗi (dãy ký tự) đều phải được đánh dấu nháy đơn hoặc đôi
Ví dụ: "A", 'Hello'
2 Biến:
Các biến sẽ chiếm các vùng nhớ trong quá trình dịch nhờ sử dụng các lệnh giả
Lệnh giả DB khai báo vùng nhớ theo byte, lập trình viên có thể đặt tên cho
phần đầu vùng nhớ Lệnh giả này cũng xác định vùng nhớ được dùng cho chữ số hay các
chữ cái
Chú ý: nếu có nhiều phần tử dùng trong lệnh này thì những phần tử
này phải được ngăn cách bằng những dấu phẩy
Loại BYTE được dùng cho các số có giá trị trong khoảng từ 0 đến
Trang 22Lệnh giả DW khai báo vùng nhớ gồm các từ (word)
Lệnh giả DD khai báo vùng nhớ gồm các từ đôi (double word)
Lệnh giả DF, DP -> 6byte, DQ -> 8byte; DT-> 10byte
Chuỗi ký tự: Lệnh giả DB cũng được sử dụng để định nghĩa chuỗi ký Một chuỗi ký tự luôn được đặt trong dấu nháy; nếu chuỗi được cho hiện lên màn hình thì phải kết thúc bằng dấu '$'
Ví dụ:
Thongbao DB 'Chào các bạn $'
Baoloi DB 'Có lỗi, đề nghị làm lại $'
Mảng: Mảng là một tập hợp các dữ liệu cùng loại (byte, word ) Mảng sẽ giúp cho lập trình viên dễ dàng lập các vòng lặp đơn giản trong một chương trình, mục đích là truy cập tuần tự đến các dữ liệu cần thiết theo thứ tự
III CẤU TRÚC CHƯƠNG TRÌNH:
Các chương trình viết bằng mã máy bao gồm các phần mã phép toán, dữ liệu, ngăn xếp Mỗi phần chiếm một phân đoạn nhớ Chương trình viết bằng hợp ngữ cũng theo cấu trúc như vậy Lúc ấy dữ liệu và ngăn xếp được ghi thành các phân đoạn trong chương trình Mỗi phân đoạn của chương trình sẽ được dịch sang một phân đoạn nhớ trong quá trình dịch
Trang 231 Loại nhớ:
Người ta có thể sử dụng định hướng biên dịch (directive) để xác định loại nhớ: CÚ PHÁP: .MODEL loại nhớ
Thường người ta sử dụng các loại sau:
SMALL, MEDIUM, COMPACT, LARGE
SMALL: Các mã phép toán đặt trong một phân đoạn
Các dữ liệu đặt trong một phân đoạn
MEDIUM: Các mã phép toán đặt trong nhiều phân đoạn (hơn 1)
Các dữ liệu đặt trong một phân đoạn
COMPACT: Các mã phép toán đặt trong một phân đoạn Các dữ liệu đặt trong nhiều phân đoạn (hơn 1)
LARGE: Các mã phép toán đặt trong nhiều phân đoạn (hơn 1)
Các dữ liệu đặt trong nhiều phân đoạn (hơn 1) Không thể có các mảng chiếm nhiều hơn 64Kbyte
2 Phân đoạn dữ liệu:
Phân đoạn dữ liệu trong một chương trình bao gồm tất cả những biến xác định Người ta sử dụng định hướng biên DATA để định nghĩa vùng cho biến và hằng
3 Phân đoạn ngăn xếp:
Người ta thường dành một phần của bộ nhớ để tạo ngăn xếp
.STACK kích thước Kích thước được đặt tùy ý theo byte
Trang 24Ví dụ CODE
; các lệnh của chương trình chính
; những thủ tục khác
Tóm lại:Để viết một chương trình chúng ta có thể có cấu trúc đơn giản chung như sau
Trang 255 Các công cụ cần thiết:
Có rất nhiều cách để mã hoá một chương trình hợp ngữ Cách đầu tiên là mã hoá trực tiếp các lệnh trong bộ nhớ bằng trình DEBUG Cách thứ hai là mã hoá mã
"nguồn" trong một tập tin rồi sẽ dịch để tạo ra một chương trình thực hiện được Cách này là cách mà người ta thường dùng nhất và gồm các bước sau:
a- Chuẩn bị lập trình, tạo cấu trúc, xác lập các phép tính, và xác định lưu đồ thuật toán Bước này chỉ cần viết trên giấy
b- Viết chương trình bằng các lệnh nhờ một phần mềm soạn thảo văn bản ASCII như EDLIN, Sidekick hoặc một phần mềm soạn thảo bất kỳ miễn sao ghi lại được một tập tin theo mã
Tập tin phải có phần mở rộng là ASM
c- Dịch mã nguồn sang "mã máy" bằng các sử dụng trình dịch hợp ngữ (MASM) Trong bước này thường xuất hiện các thông báo lỗi, trong trường hợp đó phải sửa lỗi rồi lại tiếp tục dịch cho đến khi không còn một lỗi nào nữa
Sau bước này chúng ta sẽ thu nhận được một tập tin có phần mở rộng là OBJ
d- Để tạo một chương trình thực hiện được, chúng ta sử dụng trình khác là LINK.EXE
Sau bước này chúng ta sẽ thu nhận được một tập tin có phần mở rộng là EXE
e- Kiểm tra lại chương trình có thực hiện tốt không bằng cách gõ phần tên tập tin và nhấn ENTER
Mẹo nhỏ:
o Chúng ta có thể viết những chương trình nhỏ chạy trong trình DEBUG từng lệnh một để hiểu rõ cách xử lý từng lệnh một sau đó có thể ghép lại trong một chương trình lớn hơn nhằm tạo tập tin mã nguồn như nêu trên
o Chúng ta có thể thực hiện các bước trên tuần tự một cách tự động nếu sử dụng tập tin bó lệnh với phần mở rộng là BAT
Trang 26Cũng cần nên biết rằng khi một chương trình thường trú trong bộ nhớ, DOS sẽ dành 256 byte cho phần bắt đầu PSP (Program Segment Prefix) PSP giữ toàn bộ các thông tin của chương trình DS và ES giữ địa chỉ của PSP trước khi thực hiện chương trình Như vậy DS không giữ địa chỉ của phân đoạn dữ liệu Để giải quyết vấn đề này nếu có sử dụng địa chỉ phân đoạn dữ liệu ntrong chương trình thì phài sử dụng thêm 2 dòng lệnh sau:
Sau đó để thực hiện chương trình, gõ CHAO ↵
Trang 27CHƯƠNG 4: PHƯƠNG PHÁP LẬP TRÌNH
I TỔNG QUAN:
Lập trình bằng hợp ngữ cũng giống như rất nhiều ngôn ngữ lập trình khác không khó nhưng cần phải tổ chức tốt Thường chúng ta thấy các chương trình đưa ra thật khó đọc và không tuân theo luật lệ nào cả, mỗi lập trình viên làm theo kiểu của họ và kết quả là chương trình chỉ có thể hiểu được bởi chỉ chính tác giả của nó mà thôi
Có rất nhiều phương pháp được đưa ra ngõ hầu tạo ra một số qui tắc để lập trình Trong số các phương pháp này, có một phương pháp bắt chước cách lập trình bằng ngôn ngữ cấp cao như C, Pascal trong đó có nhiều lệnh CHUẨN cho phép lập trình đến 90% vấn đề:
Có thể thấy rằng các lệnh hợp ngữ có chức năng của:
IF lặp lại nhờ nhãn IF1, THEN1, ELSE1, ENDIF1; lệnh IF tiếp theo nhờ IF2, THEN2, ELSE2, ENDIF2, ;
FOR sẽ lặp lại nhờ nhãn FOR1
II CÁC LỆNH LIÊN QUAN ĐẾN RẼ NHÁNH:
CMP đích, nguồn
TEST đích, nguồn
Trang 28Lệnh so sánh CMP thực hiện giống phép trừ SUB nhưng kết quả lại không giữ lại, nghĩa là toán hạn nguồn và đích đều không bị ảnh hưởng Những bit trong thanh ghi trạng thái đều bị tác động như khi thực hiện phép trừ Lệnh này thường được sử dụng để tìm ra mối quan hệ giữa hai toán hạng (so sánh)
Lệnh TEST thực hiện giống phép VÀ logic (AND) nhưng kết quả không giữ lại Điều này có nghĩa là toán hạng đích và nguồn không đổi chỉ có các bit trong thanh ghi trạng thái sẽ thay đổi Chúng chủ yếu sử dụng để xác định là 1 bit nào đó có giá trị là 1 hoặc là 0
1 Các lệnh rẽ nhánh có điều kiện:
Những lệnh rẽ nhánh có điều kiện đều thực hiện sau những lệnh tác động đến thanh ghi trạng thái Những lệnh đến sau rẽ nhánh sẽ nằm trong khoảng từ -128 đến +127 byte tính từ lệnh kế tiếp lệnh rẽ nhánh Do vậy để mở rộng phạm vi rẽ nhánh có điều kiện, chúng ta có thể kết hợp với lệnh rẽ nhánh không điều kiện
Những lệnh rẽ nhánh có điều kiện này luôn kiểm tra các bit trong thanh ghi trạng thái đã được xác định nhờ lệnh trước đó Nếu điều kiện đúng, bước nhảy sẽ thực hiện đến địa chỉ đích Trình dịch hợp ngữ sẽ tính toán khoảng cách đến đích để xác định số byte khoảng cách từ lệnh kế tiếp sau rẽ nhánh có điều kiện đến đích
Điều kiện không dấu
A/NBE Trên / Không dưới lẫn bằng CF ou ZF = 0
AE/NB Trên hoặc bằng/ Không dưới CF=0
B/NAE Dưới / Không trên lẫn bằng CF=1
BE/NA Dưới hoặc bằng / Không trên CF ou ZF = 1
Trang 29Điều kiện có dấu
G/NLE Lớn hơn / không nhỏ hơn lẫn bằng ((SF xor OF) or ZF)= 0 GE/NL Lớn hơn hoặc bằng / không nhỏ hơn (SF xor OF)=0
L/NGE Nhỏ hơn / không lớn hơn lẫn bằng (SF xor OF)=1
LE/NG Nhỏ hơn hoặc bằng / Không lớn hơn ((SF xor OF) or ZF)= 1
Điều kiện zéro
NE/NZ Không bằng / Không zéro ZF = 0
2 Các lệnh rẽ nhánh không điều kiện:
Đó là những lệnh nhảy bước đến một vị trí nào đó trong chương trình
Lệnh nhảy không điều kiện có dạng:
Lệnh này có thể nhảy đến bất kỳ một vị trí nào trong chương trình
III CÁC CẤU TRÚC ĐIỀU KHIỂN:
Trang 30Nếu <điều kiện> Thì <lệnh 1>
Ví dụ: Nếu AX > 0 Thì AX -AX
b IF THEN ELSE
Nếu <điều kiện> Thì <Lệnh 1>
Còn lại <lệnh 2>
Lệnh 2Lệnh 1
Trang 31INT 21h
END_IF:
c CASE OF
Biểu thức chọn
Trường hợp
BX=1: AX <- 1 BX=2: AX <- 5 BX=3: AX <- 10 Còn lại
HetTruonghop Hợp ngữ
Trang 32JMP EndCase1 Other1:
ENDCase1:
d Các điều kiện phức:
Dạng: điều kiện 1 VÀ điều kiện 2
điều kiện 1 HOẶC điều kiện 2
* Điều kiện VÀ:
Điều kiện phức (VA)Ø đúng chỉ khi cả 2 điều kiện đều đúng Ngược lại, nếu một trong các trường hợp là sai thì điều kiện phức (VÀ) là sai
Ví dụ: Đọc một ký tự Nếu là chữ cái HOA thì sẽ cho hiện lên
Đọc một ký tự Nếu ( ký tự >='A' ) VÀ (ký tự <= 'Z' ) Thì Hiện ký tự
* Điều kiện HOẶC
Trang 33(Điều kiện 1 HOẶC điều kiện 2) là đúng nếu điều kiện 1 hoặc điều kiện 2 đúng Điều kiện phức sẽ sai nếu cả hai điều kiện đều sai
Ví dụ: Đọc một ký tự Nếu ký tự là 'C' hoặc 'c', cho hiện ký tự ấy Còn không thì dừng chương trình
Đọc một ký tự Nếu (ký tự='C') hoặc (ký tự='c') Thì hiện ký tự Còn không thì dừng chương trình
Trang 34Hợp ngữ có những lệnh đặc biệt cho phép tạo các vòng lặp trong một chương trình
LOOP đích
Lệnh LOOP làm giảm nội dung của thanh ghi CX một đơn vị và nhảy đến địa chỉ đích nếu nội dung CX không bằng 0 Nếu thanh ghi CX bằng 0, vòng lặp kết thúc và lệnh kế tiếp lệnh LOOP sẽ được thực hiện Địa chỉ đích cần nằm trong khoảng -128 và 127 byte Lệnh này không tác động đến các bit của thanh ghi trạng thái
JCXZ đích
Lệnh JCXZ thực hiện nhảy bước đến địa chỉ đích nếu thanh ghi CX bằng 0 Lệnh này thường sử dụng ở đầu một vòng lặp
a - Vòng lặp FOR:
Số vòng lặp là cố định
CHO số ban đầu THỰC HIỆN lệnh KẾT THÚC
; Đặt CX = số vòng lặp
Trang 35Điều kiện
lệnh Đúng
Trang 36c - Vòng lặp REPEAT UNTIL
Trang 37Thực hiện lập trình theo trình tự như trên đòi hỏi một sự cần mẫn nào đó nhưng lại giúp lập trình viên thấy được mọi thứ rất rõ ràng Chính vì vậy việc lập trình trở nên đơn giản hơn rất nhiều Mỗi lập trình viên có thể có một phương pháp lập trình song cần nên biết rằng nếu chúng ta làm việc theo nhóm hoặc một chương trình đươc phân thành nhiều mođun thì việc tuân theo những qui ước là cực kỳ cần thiết: ví dụ như tất cả các nhãn đặt ra phải gợi nhớ và tuân theo qui ước giúp cho những người khác dễ hiểu và sử dụng viết các mođun chung
Trang 38CHƯƠNG 5: NGĂN XẾP VÀ THỦ TỤC
Ngăn xếp lưu giữ nội dung các thanh ghi hoặc các biến
Lệnh để đưa dữ liệu vào ngăn xếp là:
PUSH nguồn
Lệnh PUSH giảm giá trị của thanh ghi xuống 2 đơn vị nếu nguồn là thanh ghi 16 bit và lúc ấy vị trí đỉnh của ngăn xếp sẽ ghi trong con trỏ ngăn xếp SP Lệnh để lấy dữ liệu ra khỏi ngăn xếp là:
POP đích
Lệnh POP trả lại nội dung lưu giữ trong ngăn xếp cho các thanh ghi Nội dung thanh ghi SP tăng lên 2 đơn vị nếu thanh ghi nhận dữ liệu 16 bit
II THỦ TỤC:
Các thủ tục (hoặc chương trình con) bao gồm một dãy các dòng lệnh nối tiếp nhau để thực hiện một công việc đã xác định Công việc này có thể được gọi đến nhiều lần trong một chương trình Thay vì cứ viết lập lại đoạn lệnh này trong chương trình, lập trình viên đặt tất cả các dòng lệnh này vào một khối gọi là thủ tục Sau đó khi cần lập trình viên cứ gọi thủ tục này bất cứ lúc nào tùy thích Các thủ tục được chia ra làm hai loại:
- Các thủ tục NEAR được khai báo trong cùng phân đoạn mã của chương trình gọi Địa chỉ trở về ghi trong ngăn xếp chỉ là IP (mã 16 bit)
Trang 39- Các thủ tục FAR sử dụng phân đoạn mã khác với phân đoạn mã của chương trình gọi Địa chỉ trở về ghi trong ngăn xếp là CS và IP (mã 16 bit)
Các thủ tục được gọi bằng lệnh CALL Lệnh này giữ địa chỉ trở về của chương trình trong ngăn xếp và giảm giá trị con trỏ ngăn xếp 2 đơn vị nếu thủ tục
là NEAR Sau đó nhảy bước đến vị trí đã xác định Con trỏ ngăn xếp sẽ giảm 4
nếu thủ tục là FAR
Một thủ tục được sử dụng với các định hướng biên dịch PROC ENDP Để có thể trở về chương trình chính, cuối mỗi thủ tục cần có thêm lệnh RET Điều
này giúp lấy lại địa chỉ đã ghi vào trong ngăn xếp và tăng giá trị con trỏ ngăn xếp
lên 2 nếu thủ tục là NEAR và lên 4 nếu thủ tục là FAR
Cấu trúc chung của một thủ tục như sau:
Tên PROC NEAR (hoặc FAR) ;
; thân thủ tục ; ; RET Tên ENDP
Gọi thủ tục
Trang 40III SỬ DỤNG PTR VÀ LABEL:
a- Nếu một địa chỉ ví dụ [BX] xuất hiện như một số hạng, 8088 phải biết chọn xử lý 1 hoặc 2 byte tại địa chỉ đó, để cho rõ ràng cần phải dùng BYTE PTR hoặc WORD PTR
Ví dụ 1: WORD_ARR LABEL WORD