Đó là chương trình gồm nhiều file, thích hợp cho các chương trình lớn và phức tạp. Chúng
được dịch một cách độc lập nhưng được hợp dịch (link) với nhau khi chạy. Sau đây là những ưu
điểm của việc viết chương trình gồm nhiều file:
- Cho phép nhiều người lập trình cùng tham gia phát triển một chương trình lớn.
- Dễ dàng cho việc sửa lỗi, khi dịch module nào phát hiện ra lỗi thì chỉ cần sửa và dịch lại module đó.
- Mỗi module thường giải quyết một vấn đề ngắn gọn nên dễ tìm sai sót.
Để chia xẻ các biến toàn cục hoặc các chương trình con được sử dụng chung giữa các module người ta sử dụng các lệnh điều khiển PUBLIC, EXTRN và GLOBAL.
a. Lệnh điều khiển PUBLIC
Chức năng: Lệnh điều khiển PUBLIC chỉ cho chương trình dịch hợp ngữ biết nhãn nào nằm trong module này được phép sử dụng ở các module khác.
Cú pháp: PUBLIC tên nhãn Khai báo nhãn
Trong đó tên nhãn có thể là: - Tên chương trình con - Tên biến
- Tên hằng (theo sau bởi lệnh EQU) Ví dụ:
Nhãn là tên biến nhớ .DATA
PUBLIC gTong, gSoHang, gMang, gMangLength gTong dd ?
gSoHang dw ?
gMangLength EQU 100
gMang db gMangLength DUP(?)
Nhãn là tên của chương trình con
.CODE
PUBLIC gTinhTong, gTimMax gTinhTong PROC NEAR
….
gTinhTong ENDP
;--- gTimMax PROC FAR
….
gTimMax ENDP
;---
Chú ý: chương trình dịch hợp ngữ không phân biệt chữ hoa hay thường trong các nhãn. Tất cả các chữđều hiểu như chữ hoa. Nếu muốn có sự phân biệt đó thì:
- dùng tùy chọn /ml khi dịch cho tất cả mọi ký hiệu
- dùng tùy chon /mx khi dịch cho các nhãn được khai báo PUBLIC, EXTRN, hoặc GLOBAL.
b. Lệnh điều khiển EXTRN
Chức năng: Lệnh điều khiển EXTRN báo cho chương trình dịch hợp ngữ biết nhãn nào đã
được khai báo PUBLIC ở các module khác được sử dụng trong module này. Nói cách khác các nhãn đã được PUBLIC ở các module khác sẽđược sử dụng trong module này mà không cần khai báo lại nếu chúng được khai báo EXTRN.
Cú pháp: EXTRN tên nhãn: kiểu Trong đó kiểu có các dạng như sau:
Kiểu Giải thích
ABS Giá trị tuyệt đối, dùng để khai báo các nhãn được xác định bởi EQU hoặc =
BYTE Giá trị nhãn là 1 byte WORD Giá trị nhãn là 2 byte DWORD Giá trị nhãn là 4 byte FWORD Giá trị nhãn là 6 byte
QWORD Giá trị nhãn là 8 byte TBYTE Giá trị nhãn là 10 byte
DATAPTR Con trỏ NEAR hoặc FAR phụ thuộc vào MODEL của bộ nhớ
NEAR Chỉ chương trình con dạng khai báo NEAR FAR Chỉ chương trình con dạng khai báo FAR
PROC Xác định nhãn là thủ tục; còn NEAR hoặc FAR phụ thuộc vào lệnh điều khiển .MODEL
UNKNOWN Cho nhãn không biết kích cỡ
Các kiểu dữ liệu theo sau nhãn được khai báo EXTRN phải xác định đúng, nếu không sẽ
gây ra sai sót. Ví dụ:
Ở module 1 có chương trình con được khai báo như sau:
PUBLIC TinhTong TinhTong PROC FAR ………
Ret
TinhTong ENDP
Ở module 2 sử dụng chương trình con TinhTong được khai báo trong module 1.
.CODE
EXTRN TinhTong: FAR …
Call TinhTong
Để sử dụng EXTRN để khai báo cho chương trình dịch hợp ngữ biết những nhãn nào đã
được khai báo PUBLIC ở phần trước được sử dụng trong module này.
.DATA
EXTRN gTong:DWORD, gSoHang:WORD, gMang:BYTE,gMangLength:ABS EXTRN TinhTong: NEAR, TimMax: FAR
…. Call TinhTong …. Call TimMax … c. Lệnh điều khiển GLOBAL
Lệnh GLOBAL được hỗ trợ bởi chương trình dịch TASM (Turbo Assembler) của hẵng Borland. Lệnh điều khiển này còn có thể thay thế hai lệnh PUBLIC và EXTRN. Nếu ta khai báo GLOBAL cho các nhãn có kèm theo khai báo dạng nhãn thì GLOBAL trong trường hợp này sẽ
thay thế cho PUBLIC, còn khi khai báo nhãn đi sau GLOBAL mà chỉ xác định kiểu nhãn thì GLOBAL sẽ thay thế EXTRN.
Ví dụ:
.DATA
GLOBAL gSoHang:WORD, gMang:BYTE Count DW ?
… .CODE
GLOBAL TinhTong: NEAR, TimMax: FAR TimMax PROC FAR
Call TinhTong
…
Các nhãn TinhTong, TimMax được khai báo do đó lệnh điều khiển GLOBAL đối với các nhãn này có ý nghĩa như PUBLIC, còn các nhãn gSoHang, gMang chỉ nêu kiểu mà không khai báo thì GLOBAL đối với chúng là EXTRN.
Một trường hợp vô cùng thuận lợi với việc sử dụng lệnh điều khiển GLOBAL là việc sử
dụng GLOBAL trng file INCLUDE. Giả sử ta có một tập hợp các nhãn mà ta muốn sử dụng ở tất cả các module của chương trình gồm nhiều module. Ta có thể làm được như vậy nhờ việc gộp tất cả các nhãn vào file INCLUDE và sau đó đưa file này vào các module. Trong trường hợp này ta không thể sử dụng PUBLIC hoặc EXTRN vì EXTRN không thể làm việc được với các nhãn có xác định kích thước khai báo. Còn lệnh PUBLIC chỉ làm việc với các module trong đó các nhãn
được khai báo mà không xác định kiểu. Do vậy, chỉ có GLOBAL là thỏ mãn cả hai điều kiện trên. Ví dụ về một chương trình nằm trên hai file (hai module) khác nhau. Với:
- Module của chương trình chính là main.asm có chức năng xác định địa chỉ OFFSET của hai xâu kí tự, gọi chương trình con làm nhiệm vụ nối hai xâu kí tựđó lại và hiển thị xâu kết quả.
- Module chương trình con là KetNoi.ASM làm nhiệm vụ kết nối hai xâu và xếp vào vùng nhớ kết quả.
Dưới đây là chương trình chính:
.MODEL SMALL .STACK 100h .DATA Xau1 DB “Hello”,0 Xau2 DB “Mr Bin”, 13,10,’$’,0 GLOBAL XauKQ:BYTE XauKQ DB 50 DUP (?) .CODE EXTRN KetNoi:PROC Start: Mov AX,@Data Mov DS,AX
Mov BX,offset Xau2; BX chứa OFFSET của Xau2
Call KetNoi ; nối hai xâu
Mov DX,Offset XauKQ ; In ra màn hình Mov AH,9
Int 21h
Mov AH,4Ch ; Trở về DOS Int 21h
End Start
Module của chương trình con KetNoi
.MODEL SMALL .STACK 100h .DATA GLOBAL XauKQ:BYTE .CODE PUBLIC KetNoi KetNoi PROC Cld
Mov DI, SEG XauKQ ; ES:DI trỏ đến xâu kq
Mov ES,DI
Mov DI, OFFSET XauKQ
Mov SI,AX; DS:SI trỏ đến Xau1
Lap1:
Lodsb ; lấy 1 kí tự đưa vào AL
And AL,AL ; cho ZF=1 Jz DoKetNoi
Stosb ; Lưu kí tự từ AL vào xâu Jmp Lap
DoKetNoi:
Mov SI,BX; DS:SI; trỏ đến Xau2
Lap2:
Lodsb ; lấy kí tự đưa vào AL Stosb ; Cất kí tự vào XauKQ And AL,AL ; cho ZF=1
Jnz Lap2 ; giá trị khác 0 thì nhảy
Ret ; trở về chương trình chính KetNoi ENDP
END
Để chạy hai module trên ta thực hiện theo các thao tác sau: Dịch hai module một cách tách biệt
TASM Main TASM KetNoi