Tải bản đầy đủ (.doc) (7 trang)

Tài liệu Ngăn xếp - Thủ tục - Macro doc

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (169.78 KB, 7 trang )

Bài thực hành số 3
Ngăn xếp – Thủ tục – Macro
Mục đích
 Hiểu được cơ chế hoạt động của ngăn xếp, quá trình gọi một thủ tục.
 Biết cách sử dụng ngăn xếp, khai báo và gọi thủ tục.
 Biết cách tạo và sử dụng macro.
Tóm tắt lý thuyết
Ngăn xếp
1. Một số lưu ý:
− Ngăn xếp (Stack) là vùng nhớ đặc biệt được truy cập theo cơ chế “vào trước ra sau”
(LIFO – Last In First Out), nghĩa là dữ liệu nào đưa vào sau sẽ được lấy ra trước.
− Ngăn xếp gồm nhiều phần tử, mỗi phần tử là một từ (2 bytes).
− Vị trí của ngăn xếp trong bộ nhớ được xác định bởi cặp thanh ghi SS:SP (SS chứa địa
chỉ đoạn, SP chứa địa chỉ ô của đỉnh ngăn xếp). Khi chưa sử dụng, ngăn xếp rỗng, vị
trí được xác định bởi SP lúc đó là đáy ngăn xếp.
2. Khai báo:
.STACK <kích thước của ngăn xếp>
Ví dụ: khai báo một vùng ngăn xếp có kích thước 256 bytes:
.STACK 100h
3. Các thao tác:
• Đưa trị vào (đỉnh) ngăn xếp:
PUSH <nguồn> ; đưa nguồn (thanh ghi hay từ nhớ
; 16 bit) vào đỉnh ngăn xếp
PUSHW <hằng> ; đưa trực tiếp một hằng16 bit vào
; đỉnh ngăn xếp
PUSHF ; đưa nội dung thanh ghi cờ vào đỉnh ; ngăn xếp
• Lấy trị (ở đỉnh) ra khỏi ngăn xếp:
POP <đích> ; lấy giá trị (2 bytes) ở đỉnh ngăn xếp
; đưa vào đích (thanh ghi (trừ thanh
; ghi IP) hay từ nhớ 16 bit)
POPF ; lấy giá trị (2 bytes) ở đỉnh ngăn xếp


; đưa vào thanh ghi cờ
Chú ý : Các lệnh PUSH, PUSHF, POP và POPF không ảnh hưởng tới các cờ.
Ví dụ: Chương trình xuất chuỗi ngược dùng stack:
.model small
.stack 100h
.data
msg1 DB 'Nhap vao 1 chuoi: $'
msg2 DB 10,13,'Chuoi nghich
dao la: $'
.code
mov ax,@data
mov ds,ax
mov ah,9
lea dx,msg1
int 21h
mov cx,0
nhap:
mov ah,1
int 21h
cmp al,13
je thongbaoxuat
xor ah,ah
push ax
inc cx
jmp nhap
thongbaoxuat:
mov ah,9
lea dx,msg2
int 21h
xuat:

pop ax
mov dl,al
mov ah,2
int 21h
loop xuat
mov ah,4ch
int 21h
END
1. Khai báo

2. Nhập lần lượt a,b,c đưa vào ngăn xếp:
Nhập ký tự ‘a’:
00 61

Nhập ký tự ‘b’:
00 62
00 61

Nhập ký tự ‘c’:
00 63
00 62
00 61

3. Xuất các giá trị trong ngăn xếp
Xuất ký tự ‘c’:
00 63
00 62
00 61

Xuất ký tự ‘b’:

00 62
00 61

Xuất ký tự ‘a’:
00 61

000h

0FCh
0FCh
SS:SP 

0FCh
0FCh
SS:SP 
000h

0FCh
0FCh
SS:SP 
000h
100h
000h

0FCh
0FCh
100h
SS:SP 

0FCh

0FCh
SS:SP 
000h
100h

0FCh
0FCh
SS:SP 
000h
100h

0FCh
0FCh
SS:SP 
000h
100h
100h
100h
Thủ tục
1. Khai báo:
<Tên thủ tục>PROC<Kiểu>;kiểu là NEAR(mặc định) hay FAR
; thân thủ tục
……………
RET
<Tên thủ tục> ENDP
Thủ tục thường được viết ở cuối chương trình.
2. Gọi thủ tục:
CALL <Tên thủ tục>
CALL <Địa chỉ> ; địa chỉ là thanh ghi hoặc vùng nhớ chứa địa chỉ
; thủ tục

3. Hoạt động của lời gọi thủ tục:
Khi thực hiện lời gọi thủ tục (CALL) thì:
− Địa chỉ ô của lệnh kế lệnh CALL (*) sẽ được cất vào ngăn xếp
− Địa chỉ ô của lệnh đầu tiên trong thủ tục được đưa vào IP
Khi thực hiện lệnh RET để quay về trình gọi thì:
− Địa chỉ trong ngăn xếp được lấy ra và được vào IP.
Do đó, nếu trong thủ tục có thao tác với ngăn xếp thì trong thủ tục, trước khi thao tác với
ngăn xếp ta nên lưu lại địa chỉ (*) ở trên (chính là giá trị hiện thời trong ngăn xếp) để
quay trở về trình gọi. Xem mô tả trong ví dụ sau.
Ví dụ: Nhập xuất chuỗi kí tự
.model small
.stack 100h
.code
CALL Nhap
CALL Xuat
mov ah,4ch
int 21h
;
Nhap PROC
pop bx
mov ah,2
mov dl,’?’
int 21h
xor cx,cx
nhap:
mov ah,1
int 21h
cmp al,13
je ketthucnhap
push ax

inc cx
jmp nhap
ketthucnhap:
push bx
RET
Nhap ENDP
;
Xuat PROC
pop bx
mov ah,2
mov dl,13
int 21h
mov dl,10
int 21h
jcxz ketthucxuat
xuat:
pop dx
int 21h
loop xuat
ketthucxuat:
push bx
RET
Xuat ENDP
END
1. Khai báo

2. Gọi thủ tục Nhap
CALL Xuat

IP = địa chỉ ô lệnh “pop bx”

3. Lưu lại địa chỉ quay về

BX = địa chỉ lệnh “CALL Xuat”
4. Nhập ký tự a,b:
00 62
00 61

5. Trả lại địa chỉ quay về
BX = địa chỉ lệnh “CALL Xuat”
CALL Xuat
00 62
00 61

6. Kết thúc thủ tục Nhập:
00 62
00 61
IP = địa chỉ ô lệnh “CALL Xuat”
Lời gọi thủ tục xuất (CALL Xuat) cũng
hoạt động tương tự như trên.
000h

0FCh
0FCh
100h
SS:SP 

0FCh
0FCh
SS:SP 
000h

100h
000h

0FCh
0FCh
100h
SS:SP 

0FCh
0FCh
SS:SP 
000h
100h
000h

0FCh
0FCh
100h
SS:SP 
000h

0FCh
100h
0FCh
SS:SP 
Macro
1. Một số lưu ý:
− Khi chúng ta có nhiều đoạn code giống nhau, chúng ta có thể sử dụng macro để thay
thế, giống như chúng ta dùng define ở trong C.
− Bản chất là thay thế lời gọi macro bằng các lệnh trong thân macro.

− Các macro nên phục hồi những thanh ghi mà nó sử dụng trừ những thanh ghi chứa
kết quả.
2. Khai báo:
<tên macro> MACRO <các đối số>
; thân macro
……………
ENDM
3. Hai cách sử dụng macro
• Tạo macro trực tiếp trong chươnng trình:
− Các macro thường được khai báo ở đầu chương trình trước phần .code.
− Ví dụ: Xuất một chuỗi ra màn hình sử dụng macro
.model small
.stack 100h
.data
chuoi1 db “hello”,10,13,’$’
chuoi2 db “bye”,10,13,’$’
@xuatchuoi macro chuoi
lea dx,chuoi
mov ah,9
int 21h
endm
.code

@xuatchuoi chuoi1
@xuatchuoi chuoi2

end
• Xây dựng thư viện các macro:
− Tạo 1 thư viện (tập tin) chứa các macro
− include vào chương trình (thường trước phần .code) bằng lệnh include

− Ví dụ: Xuất một chuỗi ra màn hình sử dụng thư viện macro
THUVIEN.INC
@xuatchuoi macro chuoi
lea dx,chuoi
mov ah,9
int 21h
endm
TestMacro.asm
.model small
.stack 100h
.data
chuoi1 db “hello”,10,13,’$’
chuoi2 db “bye”,10,13,’$’
INCLUDE THUVIEN.INC
.code

@xuatchuoi chuoi1
@xuatchuoi chuoi2

end
4. Các thành phần cục bộ của macro:
− Trong macro, ta cũng có thể khai báo các biến, nhãn cục bộ để tránh gây ra lỗi khi
gọi macro nhiều lần.
− Cú pháp :
LOCAL <danh sách các nhãn, các biến cục bộ>
− Ví dụ: Xuất một chuỗi hằng ra màn hình sử dụng macro với biến cục bộ
.model small
.stack 100h
@xuatchuoi macro chuoi
LOCAL chuoicucbo, nhancucbo

.data
chuoicucbo db chuoi,’$’
.code
lea dx,chuoicucbo
mov ah,9
int 21h
endm
.code

nhancucbo:

@xuatchuoi <“hello”,10,13>
@xuatchuoi ”bye”

end
Lưu ý: nếu cần truyền chuỗi phức tạp thì ta cần sử dụng <…> để báo cho trình biên dịch biết đây
là một đối số.
Tài liệu tham khảo
1. Nguyễn Minh Tuấn, Giáo trình hợp ngữ - Chương 6, ĐHKHTN, 2002
2. Randal Hyde, The art of assembly language programming – Chapter 11,12.
3. Norton Guide
4. Dan Rollins, TechHelp v.6.0
Bài tập
Bài 1: Viết chương trình kiểm tra một biểu thức đại số có chứa các dấu ngoặc (như (), [] và {}) là
hợp lệ hay không hợp lệ .
Ví dụ:
(a + [b – { c * ( d – e ) } ] + f)
là hợp lệ nhưng
(a + [b – { c * ( d – e )] } + f)
là không hợp lệ.

Bài 2: Tính giá trị biểu thức đã nhập ở bài tập 2 theo thứ tự từ trái sang phải.
Bài 3: Viết lại các bài tập tuần trước dưới dạng các thủ tục
Bài 4: Xây dựng một thư viện các macro
Mở rộng
1. Có những cách nào để truyền tham số cho thủ tục ? để nhận kết quả trả về ?
2. Thử viết một thủ tục đệ quy.
3. Tìm hiểu cách phân chia chương trình thành nhiều file và cách biên dịch, liên kểt chúng.
Hướng dẫn
Bài 1. dùng ngăn xếp để PUSH các dấu ngoặc trái ( ‘(‘, ’{‘, ‘[‘ ) vào ngăn xếp. Nếu gặp dấu ngoặc
phải ( ‘)’, ‘}’, ‘]’ ) thì POP từ stack ra. Nếu không POP được, hoặc POP ra không đúng loại với dấu
ngoặc phải -> không hợp lệ . Ngược lại là biểu thức hợp lệ.

×