Vấn đề này không phải là mới lạ trong lập trình, nó là một trong những tiện ích khá hay mà trình dịch mang lại. Đối với mỗi trình dịch thì cách định nghĩa macro cũng khác nhau, bài viết này tôi chỉ nói về cách định nghĩa sử dụng macro và một số macro bổ ích cho trình dịch ASEM51 thông dụng nhất hiện nay.
Lợi ích của nó là gì, một ví dụ đơn giản trước khi bắt đầu, đó là phép so sánh lớn hơn trong ASM, việt nhớ các cờ Carry, hay cờ Z, cờ OV cho mỗi lệnh đôi khi gây ra lẫn lộn, vậy nếu định nghĩa thành công 1 lần thì sẽ dùng được ở các lần khác với 1 từ gợi nhớ, chứ không phải là các bit
Ví dụ về định nghĩa và sử dụng Macro Jump If Great Than, sẽ nhảy đến 1 nhãn nếu giá trị của thanh ghi A lớn hơn...
Cụ thể, những lợi ích sử dụng macro như sau:
[+] Chương trình nguồn sử dụng Macro dễ đọc hơn, dùng mã gợi nhớ, có thể nhìn chương trình một cách tổng quát
[+] Chương trình nhìn ngắn gọn hơn (thực tế mã sinh ra không ít hơn)
[+] Giảm thiểu các lỗi, chỉnh sửa hàng loạt
[+] Không bận tâm đến xử lý chi tiết quá mức
Định nghĩa Macro:
Ví dụ đơn giản nhất, cất thanh ghi DPTR và ngăn xếp:
Tiếp theo, việc truyền tham số cho Macro giúp chúng ta tùy biến mỗi Macro cho nhiều tình huống trong chương trình:
Ví dụ về Macro có tham số, Skip If Equa, nếu giá trị của A khác giá trị của tham số, thì bỏ qua lệnh tiếp theo, (giống lệnh của Pic CPFSEQ
)
Tiếp theo là sử dụng các nhãn cục bộ trong Macro
Ví dụ về sử dụng nhãn cục bộ, định nghĩa macro giảm giá trị của thanh ghi DPTR (chỉ có lệnh INC DPTR mà không có, nên cái này gội là ...tự chế
)
Ngoài ra còn có 1 số macro được định nghĩa sẵn, và công việc của chúng ta là sử dụng cho đúng mục đích
[+] REAPEAT
ví dụ, về Macro lặp lại 100 lần lệnh nop
[+] IF THEN
Ngoài ra còn 1 lưu ý, nếu bạn định nghĩa Macro mà sau đó, nội dung xuống dòng phải có 1 dấu *
và sau đây là một số Macro thông dụng đã sưu tập được
PS: Tham khảo sách của thầy Tống Văn On, Họ Vi Điều Khiển 8051 ..v..v
Lợi ích của nó là gì, một ví dụ đơn giản trước khi bắt đầu, đó là phép so sánh lớn hơn trong ASM, việt nhớ các cờ Carry, hay cờ Z, cờ OV cho mỗi lệnh đôi khi gây ra lẫn lộn, vậy nếu định nghĩa thành công 1 lần thì sẽ dùng được ở các lần khác với 1 từ gợi nhớ, chứ không phải là các bit
Ví dụ về định nghĩa và sử dụng Macro Jump If Great Than, sẽ nhảy đến 1 nhãn nếu giá trị của thanh ghi A lớn hơn...
PHP Code:
;//định nghĩa
%*DEFINE (JGT (VALUE, LABEL)) ( CJNE A, #%VALUE+1, $+3
JNC %LABEL
)
;//sử dụng
%JGT(55h, GREAT_THAN)
...
GREAT_THAN:
...
[+] Chương trình nguồn sử dụng Macro dễ đọc hơn, dùng mã gợi nhớ, có thể nhìn chương trình một cách tổng quát
[+] Chương trình nhìn ngắn gọn hơn (thực tế mã sinh ra không ít hơn)
[+] Giảm thiểu các lỗi, chỉnh sửa hàng loạt
[+] Không bận tâm đến xử lý chi tiết quá mức
Định nghĩa Macro:
PHP Code:
%*DEFINE (Biểu đồ gọi) (nội dung Macro)
PHP Code:
;//Định nghĩa
%*DEFINE (PUSH_DPTR) ( PUSH DPH
PUSH DPL
)
;//sử dụng
%PUSH_DPTR
PHP Code:
%DEFINE (tên macro (danh sánh tham số)) (Nội dung macro)
)PHP Code:
;//định nghĩa
%*DEFINE (SIE(VALUE)) ( CJNE A,#%VALUE, $+3
)
;//Sử dụng
%SIE(20h)
SJMP BANG
KHONG_BANG:
...
BANG:
...
PHP Code:
;//Chú ý là nội dung nằm giữa cặp dấu [] là tùy chọn, có thể có hoặc không
%*DEFINE (tên macro[(danh sách tham số)])
[LOCAL danh sách nhãn] (nội dung Macro)
)PHP Code:
;//Định nghĩa
%*DEFINE (DEC_DTPR) LOCAL SKIP
(DEC DPL
MOV A,DPL
CJNE A,#0FFH, %SKIP
DEC DPH
%SKIP: )
;//sử dụng
%DEC_DPTR
[+] REAPEAT
ví dụ, về Macro lặp lại 100 lần lệnh nop
PHP Code:
%REPEAT(100)(NOP)
;//điều này chẳng mang lại lợi lộc gì lớn lao ngoài trừ ngoài chuyện
;//bạn không mất công ngồi gõ 100 lần cái lệnh này
;//có nghĩa là trình dịch viết giúp bạn 100 lấn đấy thôi
;//cũng có nghĩa là mã sinh ra cũng có 100 cái lệnh này
PHP Code:
NUM EQU 1
%IF(NUM) THEN (
;//code ở đây, nếu NUM được định nghĩa khác 0
) ELSE (
;//code này được sử dụng nếu NUM được định nghĩa là 0
)
PHP Code:
%*DEFINE (EXAM(VALUE,LABLE))
*(CJNE A,#%VALUE,%LABEL)
PHP Code:
;//[*] Nhảy đến "LABEL" nếu A nhỏ hơn "VALUE"
%DEFINE (JLT (VALUE, LABEL))
*(cjne a,#%VALUE, $+3
jc %LABEL)
;//--------------------------------------------
;//[*] Nhảy đến "LABEL" nếu A lớn hơn "VALUE"
%DEFINE (JGT (VALUE, LABEL))
*(cjne a,#%VALUE+1, $+3
jnc %LABEL)
;//--------------------------------------------
;//[*] Nhảy đến "LABEL" nếu A nhỏ hơn hoặc bằng "VALUE"
%DEFINE (JLE (VALUE, LABEL))
*(cjne a,#%VALUE-1, $+3
jc %LABEL)
;//[*]Nhảy đến "LABEL" nếu A lớn hơn hoặc bằng "VALUE"
%DEFINE (JGE (VALUE, LABEL))
*(cjne a,#%VALUE, $+3
jnc %LABEL)
;//[*] Nhảy đến "LABEL" nếu A nằm ngoài (Out Of Range) dải "lower" & "upper"
%DEFINE (JOR (lower,upper, LABEL))
*(cjne a,#%lower, $+3
jc %LABEL
cjne a,#%upper+1, $+3
jnc %LABEL )
;//[*]và một số ví dụ
