Chương 3 : Lập trình hợp ngữ 1 Giá trình Vi xử lý
Chương 3
LẬP TRÌNH HỢP NGỮ
3.1. TỔNG QUAN VỀ TRÌNH DỊCH HỢP NGỮ
3
3
.
.
1
1
.
.
1
1
.
.G
G
i
i
ớ
ớ
i
it
t
Modul chứa 1 hoặc nhiều segment hay các segment cục bộ . Một modul có thể là một
“file” ở nhiều trường hợp cá biệt .
Một chương trình Modul Absolute đơn được hòa vào toàn bộ các Segment Absolute và
Segment Relocatable từ tất cả các mode nhập.
Chương trình chỉ chứa các mã nhị phân thay cho các lệnh (với các địa chỉ và các hằng
dữ liệu ) được hiểu bởi máy tính.
3
3
.
.
1
1
.
.
2
2
.
.H
H
o
o
ạ
ạ
t
t
b
b
i
i
ê
ê
n
nd
d
ị
ị
c
c
h
h(
(
A
A
s
s
s
s
e
e
)
)Có nhiều trình biên dịch với mục đích khác nhau có tác dụng là dễ hiểu các ứng dụng vi
điều khiển. ASM51 là tiêu biểu chuẩn biên dịch của họ MSC-51. ASM51 là trình biên dịch
mạnh có tác dụng hữu hiệu trên hệ thống phát triển INTEL và họ IBM PC của máy vi tính.
ASM51 được gọi hiện lên từ sự chỉ dẫn của hệ thống bởi:
ASM51 Source file (Assembly Control).
Trình biên dịch nhận một file nguồn với tư cách là ngõ nhập (PROGRAM.SCR) và họ
phát ra một file đối tượng (PROGRAM.OBJ) và file listing (PROGRAM.LST).
Canquynhon.blogtiengviet.net Đại học Quy Nhơn
Chương 3 : Lập trình hợp ngữ 2 Giá trình Vi xử lý Hình 3.1: Hợp dịch một chương trình nguồn
Vì hầu hết các biên dịch xem xét chương trình nguồn 2 lần trong lúc thi hành sự dịch
ngôn ngữ máy, nên chúng được mô tả qua 2 Pass biên dịch là Pass1 và Pass2.
Trong pass1, file nguồn được xem xét từng dòng và bảng ký hiệu xây dựng.
Bộ đếm Location mặc nhiên chọn 0 hoặc được đặt bởi chỉ thị ORG (đặt Origin).
Cũng như file được xem xét, bộ đếm Location được tăng lên bằng độ dài mỗi lệnh.
Chỉ thị data định nghĩa (đặc biệt hoặc DW) tăng bộ đếm Location bằng với số byte định
rõ, các chỉ thị nhớ lưu trữ (DSO tăng bộ đếm Location bởi số byte dự trữ). Mỗi lần một
nhãn được tìm thấy ở sự bắt đầu của một đường, thì nó được đặc trong bảng ký hiệu theo
giá trị hiện hành của bộ đếm Location. Các ký hiệu được định nghĩa bởi dùng các chỉ thị
tương đương (EQU) được đặc trong bảng ký hiệu, được cất giữ và sau đó dùng trong pass2.
Trong Pass2, file Object và file Listing được tạo ra, các thuật nhớ được biến đổi thành
Opcode và đặt trong các file output. Các toán hạng được xác định giá trị và đặt phía sau
Opcode lệnh. Ở nơi các ký hiệu xuất hiện trong toán hạng, các ký hiệu của chúng sẽ được
lấy lại từ bảng ký hiệu (được tạo ra trong suốt Pass1 và dùng trong sự sắp xếp dữ liệu đúng
ắ
ắ
p
pđ
đ
ặ
ặ
t
tt
t
r
r
o
o
n
n
g
gt
t
r
r
Canquynhon.blogtiengviet.net Đại học Quy Nhơn
Chương 3 : Lập trình hợp ngữ 3 Giá trình Vi xử lý
Các lệnh máy là các kỹ xảo của lệnh có thể thực thi (ví dụ như ANL). Các chỉ thị của
trình biên dịch là các lệnh để trình biên dịch định cấu trúc chương trình, các dữ liệu, ký
hiệu, hằng, … (ví dụ Org ). Các sự điều khiển trình biên dịch set các mode của trình biên
dịch và điều khiển sự chạy chương trình Assembly (ví dụ STILLE ).
Các chú thích hoạt động của lệnh.
Các lệnh phải ghi theo nguyên tắc rõ ràng để được trình biên dịch hiểu.
Sự sắp xếp của chúng như sau:
(Label:) mnemonic [operand][:operand][ ][:comment]
3
3
.
.
1
1
.
.
3
3
.
.
1
1V
V
ù
F
F
i
i
e
e
l
l
d
d)
)
:
:Một nhãn tượng trưng cho địa chỉ của lệnh (hoặc dữ liệu ) theo sau nhãn. Khi các rẽ
nhánh đến lệnh này, nhãn được dùng trong vùng toán hạng của nhánh (hoặc lệnh nhảy).
Các “nhãn“ là một kiểu ký hiệu, sau nhãn phải có dấu hai chấm (:) còn sau ký hiệu thì
không.
Các kiểu ký hiệu được quy cho các giá trị hoặc quy cho việc dùng các chỉ thị như: EQU,
SEGMENT, BIT, DATA, … Các ký hiệu có thể là địa chỉ, hằng, data, tên các segment hoặc
sự xây dựng khác được hiểu bởi người lập trình. Sau đây là một ví dụ để phân biệt nhãn và
ký hiệu:
PRA EQU 500 : PRA là ký hiệu tượng trưng giá trị 500
START :MOV A , #0FFH :START là nhãn tương trưng địa chỉ lệnh MOV
Một ký hiệu hoặc một nhãn phải bắt đầu một chữ cái dấu “?”, hoặc dấu “-“; phải được
h
u
u
ậ
ậ
t
tn
n
h
h
ớ
ớ(
(
M
M
n
n
e
e
m
m
o
o
n
.
.
1
1
.
.
3
3
.
.
3
3V
V
ù
ù
n
n
g
gt
t
o
o
á
á
F
F
i
i
e
e
l
l
d
d
)
)
:
:Vùng toán hạng theo sau vùng thuật nhớ. Vùng này chứa địa chỉ hay dữ liệu được dùng
bởi lệnh. Một nhãn có thể dùng để tượng trưng cho hằng dữ liệu. Các khả năng cho phép
vùng toán hạng phụ thuộc lớn vào các hoạt động. Một vài hoạt động không có toán hạng
như : RET, NOP trong khi các hoạt động khác cho phép nhiều toán hạng được phân ra bằng
dấu phẩy.
Canquynhon.blogtiengviet.net Đại học Quy Nhơn
Chương 3 : Lập trình hợp ngữ 4 Giá trình Vi xử lý
3
3
.
.
t
t
h
h
í
í
c
c
h
h(
(
C
C
o
o
m
m
m
m
e
e
n
n
t
t
.
.
5
5C
C
á
á
c
ck
k
ý
ýh
h
i
i
ệ
ệ
u
u
i
i
ệ
ệ
t
t(
(
S
S
p
p
e
e
c
c
i
i
a
a
l
lA
A
s
s
)
)
:
:Các ký hiệu biên dịch đặc biệt được dùng trong các mode định vị thanh ghi cụ thể
chúng bao gồm các thanh ghi A, R0 – R7, DPTR, PC,C, AB, hay các ký hiệu $ được dùng
để quy vào giá trị hiện hành của bộ đếm Location.
Ví dụ : lệnh JNZ TI , $ tương đương với lệnh sau : HERE : JNZ T1, HERE
3
3
.
.
1
1
.
.
3
3
.
.
6
6Đ
Đ
ị
ị
(
(
I
I
n
n
d
d
i
i
r
r
e
e
c
c
t
tA
A
d
d
d
d
r
r
7D
D
ữ
ữl
l
i
i
ệ
ệ
u
ut
t
ứ
ứ
c
ct
t
h
D
a
a
t
t
a
a)
)
:
:
Các lệnh dùng sự định vị tức thời cung cấp dữ liệu vào vùng toán hạng, ký hiệu # đặt
trước dữ liệu tức thời. Ví dụ:
CONSTANT EQU 100
MOV A, 0FFH
ORL 40H, # CONSTANT
Các dữ liệu tức thời (ngoại trừ lệnh MOV DPTR, #data) đều yêu cầu dữ liệu 8 bit. Dữ
liệu tức thời được đánh giá như hằng số 16 bit và sau đó byte thấp được sử dụng. Tất cả các
bit trong byte cao giống nhau (00H hoặc FFH) hoặc 1 thông báo lỗi “ giá trị sẽ không lấp
đầy 1 byte” được tạo ra. Ví dụ:
MOV A, #0FF00H
MOV A, #00FFH
Lỗi : MOV A, #0FE00H
MOV A, #01FFH
c
c
h
h
ỉ
ỉd
d
ữ
ữl
l
i
i
ệ
ệ
u
u(
(
D
D
a
a
3
3
.
.
1
1
.
.
3
3
.
.
9
9Đ
Đ
ị
ị
a
ac
c
h
h
ỉ
ỉ
s
s
s
s
)
)
:
:Một trong những điểm mạnh của 8951 là khả năng truy xuất các bit riêng lẻ, không cần
các hoạt động trang bị trên byte. Các lệnh truy xuất các bit định vị phải cung cấp một địa chỉ
trong bộ nhớ dữ liệu nội (00H – 7FH) hoặc địa chỉ bit trong các SFR (80H - FFH).
Có 3 cách để xác định địa chỉ bit trong ô nhớ dữ liệu: Dùng địa chỉ bit trực tiếp, dùng
hoạt động điểm giữa địa chỉ byte và địa chỉ bit, dùng ký hiệu biên dịch đã được định nghĩa.
Ví dụ:
SETB 0E7H : Dùng địa chỉ trực tiếp.
SETB ACC, 7 :Dùng hoạt động điểm.
JNZ TI ,$ : Dùng ký hiệu được định nghĩa “TI”.
3
3
.
.
1
1
.
.
3
3
.
(
C
C
o
o
d
d
e
eA
A
d
d
d
d
r
r
e
e
s
s
s
s
)
)
:
:
C
C
á
á
c
cs
s
ự
ựn
n
h
h
ả
ả
y
yv
v
à
à
e
e
r
r
i
i
c
cJ
J
u
u
m
m
p
pa
a
n
n
d
dC
C
T
T
Í
Í
N
N
H
HT
T
O
O
Á
Á
N
NB
B
I
I
Ể
Ể
U
U
E
E
M
M
B
B
L
L
E
ET
T
I
I
M
M
E
E(
(
A
A
s
s
s
s
e
e
s
s
s
s
i
i
o
o
n
n
E
E
v
v
a
a
l
l
u
u
a
a
.
.
C
C
á
á
c
cc
c
ơ
ơs
s
ở
ởs
s
ố
ố
)
)
:
:Cơ sở các hằng số phải được theo sau các số nhị phân “B”, theo sau số Octal “O”, hoặc
“Q”, theo sau số thập phân “D” hay không có gì , theo số Hexa “H”. Ví dụ:
MOV A, # 15 : Thập phân
MOV A , 1111B : Nhị phân
MOV A , 30H : Hex
MOV A , 315D : Thập phân
MOV A , 317Q : Octal
3
3
.
.
2
2
.
.
2
2
.
.C
C
á
(
C
C
h
h
a
a
r
r
a
a
c
c
t
t
e
e
r
rS
S
t
t
r
r
i
i
n
á
c
ck
k
ý
ýh
h
i
i
ệ
ệ
u
us
s
ố
ốh
h
ọ
O
p
p
e
e
r
r
a
a
t
t
i
i
o
o
n
n
s
s
)
)
:
:+ : Cộng
_ : Trừ
. : Nhân
/ : Chia
MOD : Phép lấy dư
ạ
t
tđ
đ
ộ
ộ
n
n
g
gl
l
o
o
g
g
i
i
c
c(
(
L
s
)
)
:
:Các hoạt động logic là OR, AND, XOR, NOT. Hoạt động được áp dụng trên các bit
tương ứng trong mỗi toán hạng. Sự hoạt động phải được phân ra từ các toán hạng bởi một
khoảng cách ký tự hoặc nhiều khoảng ký tự.
Ví dụ 3 lệnh MOV sau đây giống nhau:
THERE EQU
MINUS _THERE EQU- 3
MOV A, #(NOT THERE) + 1
MOV A, MINUS _ THERE
MOV A, #11111101B
3
3
.
.
2
2
.
.
5
5C
C
b
b
i
i
ệ
ệ
t
t(
(
s
s
p
p
e
e
c
c
i
i
a
a
l
lO
O
2
.
.
6
6C
C
á
á
c
ct
t
o
o
á
á
n
nt
t
ử
ử
MOV A, 5 NE 4
Cả ba lệnh trên đều đúng nên cả ba tương đương với lệnh sau: MOV A,# 0FFH
3
3
.
.
3
3
.
.C
C
Á
Á
C
CC
C
H
H
Ỉ
ỈT
T
Sự xác định ký hiệu (SEGMENT, EQU, SET, DATA, NDATA, BIT,
CODE)
Sự khởi gán lưu trữ hay để dành trước sự lưu trữ (DS, DBIT, DB, DW)
Sự kết nối chương trình (PUBLIC, EXTRN, NAME)
Sự chọn segment (PSEG, CSEG, DSEG, ISEG, BSEG, XSEG)
3
3
.
.
3
3
.
.
1
1S
S
ự
ựđ
đ
i
i
ề
ề
h
h
á
á
i
ib
b
i
i
ê
ê
n
nd
d
ị
ị
c
c
h
h
:
:
h
hn
n
g
g
h
h
ĩ
ĩ
a
ak
k
ý
ýh
h
i
i
ệ
ệ
u
u
t
t
i
i
o
o
n
n
)
)
:
:- Dạng chỉ dẫn của segment như sau: symbol SEGMENT segmenttype (loại segment)
Trong đó symbol là tên của segment có thể đổi chỗ được. Các kiểu segment có thể
CODE (segment mã), XDATA (vùng dữ liệu ngoài), DATA (vùng dữ liệu nội) có thể truy
xuất bằng sự định vị trực tiếp từ (00H-7FH), IDATA (toàn bộ vùng dữ liệu nội), BIT (vùng
BIT từ 20H-2FH dữ liệu nội).
- Chỉ lẫn EQU gán giá trrị số cho tên của ký hiêu được định nghĩa.
Symbol EQU Expression (biểu thức).
Ví dụ : EPROM SEGMENT CODE cho biết EPROM của một segment kiểu code.
Dạng chỉ thị EQU : symbol EQU Expression
MESSAGE DB ‘hello’
Dạng chỉ thị BIT : symbol BITExpression
Lưu ý rằng nếu ta dùng chỉ thị BIT như FLAGS BIT 05H thì ta có thể SETB FLAGS
mà không được dùng lệnh MOV.
Canquynhon.blogtiengviet.net Đại học Quy Nhơn
Chương 3 : Lập trình hợp ngữ 9 Giá trình Vi xử lý
k
k
h
h
ở
ở
i
ig
g
á
á
n
n
/
/
d
d
à
à
n
n
h
hl
ớt
t
r
r
ư
ư
ớ
ớ
c
c(
(
S
S
t
t
o
o
r
r
a
a
g
g
e
/
R
R
e
e
s
s
e
e
r
r
v
v
a
a
t
t
i
i
o
o
n
n
)
)Các chỉ thị của Storage Initilization khởi gán và Storage Reservation để dành một vùng
nhớ trong từ, byte hoặc các đơn vị bit. Vùng được dành trước khi bắt đầu tại vùng nhớ được
chỉ rõ bởi giá trị hiện hành của bộ đếm vùng nhớ trong segment tích cực đang hiện hành.
MOV DPTR, #XBUFFER ; Đưa địa chỉ 4000H và DPTR
LOOP : CLR A
MOVX @DPTR, A ; Xoá nội dụng từ địa chỉ 4000H trở đi
INC DPTR ; Tăng thêm 1 ( trường hợp đầu trở thành 4001H)
MOV A, DPL
CJNZ A, #LOW (XBUFFER+XLENGTH+1), LOOP
MOV A, DPH
CJNZ A,HIGH (XBUFFER+XLENGTH+1),LOOP
(Continue)
Nếu so sánh hai cách dùng trên dành cho byte thấp và byte cao DPTR, Vì lệnh CJNZ
chỉ làm nhiệm vụ đối với thanh ghi A hoặc thanh ghi Rn, do đó byte thấp hoặc byte cao của
bộ đếm dữ liệu phải được MOV vào A trước khi đến lệnh CJNZ. Vòng lặp chỉ kết thúc khi
bộ đếm dữ liệu đã được đọc địa chỉ XBUFFER+XLENGTH+1
Khai báo DBIT (Define Bit)
Sự thành lập : [label:] DBIT expression
Chỉ thị DBIT dành trước vùng nhớ các đơn vị bit, nó có thể được dùng trong 1 segment
bit. Khi phát biểu này được bắt gặp trong chương trình thì bộ đếm vị trí của segment hiện
hành được cộng thêm giá trị của biểu thức. Lưu ý là trong segment BIT, đơn vị của bộ đếm
đơn vị là bit thay vì là byte. Các chỉ dẫn sau tạo ra 3 cờ trong một segment bit tuyệt đối:
BSEG ; segment bit truyệt đối
KBFLAG DBIT 1 ; trạng thái của bàn phím
PRFLAG DBIT 1 ; trạng thái của máy in
Canquynhon.blogtiengviet.net Đại học Quy Nhơn
Chương 3 : Lập trình hợp ngữ 11 Giá trình Vi xử lý
DKFLAG DBIT 1 ; trạng thái của đĩa
Khai báo byte DB (Define Byte)
Sự thành lập chỉ dẫn DB : [label:] DB Expression, [Expression], [ ]
Chỉ dẫn DB khởi gán bộ mã nên segment CODE phải tích cực. Danh sách biểu thức là
một chuỗi của một hay nhiều giá trị byte (mỗi cách có thể là một biểu thức) được phân ra
3.3.4. Liên Kết chương trình
Liên kết chương trình cho phép các môdul được hợp dịch riêng rẽ truyền thông với nhau
bằng cách cho phép các tham chiếu liên modul và đặt tên cho các modul.
Chỉ dẫn PUBLIC
Dạng chỉ dẫn PUBLIC symbol [, symbol]…
Cho phép một danh sách các ký hiệu đã được xác định được biết và được sử dụng ở bên
ngoài của modul được hợp dịch hiện hành. Như vậy một ký hiệu được khai báo bởi
PUBLIC phải được định nghĩa trong modul hiện hành và được tham chiếu bởi một modul
khác ví dụ:
PUBLIC INCHAR, OUTCHR, INLINE, OUTSTR
Chỉ dẫn EXTRIN
Dạng chỉ dẫn EXTRIN segment_type (symbol [, symbol]…)
Liệt kê các ký hiệu được tham chiếu trong modul hiện hành các ký hiệu này được định
nghĩa trong các modul khác
3.4. CẤU TRÚC CHƯƠNG TRÌNH
Mục đích của việc lập trình có cấu trúc áp dụng cho lập trình hợp ngữ. Mặc dù các ngôn
ngư cấp cao (như Pascal, C, ) đẩy mạnh việc lập trình có cấu trúc thông qua các phát biểu
của chúng (WHILE, FOR ) và các quy ước ký hiệu trong khi hợp ngữ không có các đặc
trưng vốn có như vậy. Việc sử dụng cấu trúc mang lại hiệu quả lớn.
Thông thường sử dụng 3 phương pháp
Lưu đồ (flowchart)
Giải mã (pseudo code)
Hợp ngữ (assembly languare)
Ta có thể xem giải mã như là một ngôn ngữ của máy tính. Ý tưởng này đã sử dụng khôn
chính thức. Lợi ích của việc sử dụng giải mã tạo ra sự tôn trong triệt để đối với cấu trúc
đồng thời kết hợ với ngôn ngữ không chính thức. ví dụ :
IF [condition í true]
THEN [do statement 1]
ELSE BEGIN
[do statement 2]
SUM: CLR A
LOOP: CJNE R7, #0, STATEMENT
JMP EXIT
STATEMENT: ADD A, @R0
DEC R7
JMP LOOP
EXIT: RET
Hoặc cách 2:
SUM: CLR A
INC R7
MORE: CJNE R7, SKIP
RET
SKIP: ADD A, @R0
INC R0
SJMP MORE
3.4.2.2. Phát biểu REPEAT/UNTIL
REPEAT [statement]
UNTIL [condition]
Hình 3.3: Lưu đồ cấu trúc REPEAT/UNTIL
Canquynhon.blogtiengviet.net Đại học Quy Nhơn
Chương 3 : Lập trình hợp ngữ 15 Giá trình Vi xử lý
Ví dụ: Viết chương trình tìm kiếm 1 chuỗi kết thúc bằng NULL (trỏ bởi R0) và xác
định phải z hiện diện tong chuỗi không?
STATEMENT: MOV A, @R0
INC R0
JZ EXIT
CJNE A, #’Z’, STATEMENT
EXIT: RET
CALL INCH
CJNE A, #’0’, SKIP1
ACT0:
…
JMP EXIT
SKIP1: CJNE A, #’1’, SKIP2
ACT1:
…
JMP EXIT
SKIP2: CJNE A, #’2’, SKIP3
Canquynhon.blogtiengviet.net Đại học Quy Nhơn
Chương 3 : Lập trình hợp ngữ 17 Giá trình Vi xử lý
ACT2:
…
JMP EXIT
SKIP3: CJNE A, #’3’, EXIT
ACT3:
…
EXIT: (continue)
3.5. QUY TẮC HỢP NGỮ
3.5.1. Nhãn và chương trình con
Sử dụng các nhãn bằng các từ gợi nhớ dễ hiểu như SKIP, WAIT nhưng trang sử dụng
các từ khóa của chương trình như END, R0… và đứng sau nhãn bằng dấu : sau khi thực
hiện xong các lệnh yêu cần kết thúc bằng lênh RET ví dụ :
EXIT : MOV @R0, #0
POP ACC ; phục hồi các thanh ghi
POP07H ; từ stack
POP 00H
RET