Thực hành Assembly - Bài 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.
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 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. Khai báo: .STACK Ví dụ: khai báo một vùng ngăn xếp có kích thước 256 bytes: .STACK 100h Các thao tác: Đưa trị vào (đỉnh) ngăn xếp: PUSH ; đưa nguồn (thanh ghi hay từ nhớ ; 16 bit) vào đỉnh ngăn xếp PUSHW ; đư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 ; 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: 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 .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 Khai báo 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 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 Thủ tục Khai báo: PROC ;kiểu là NEAR(mặc định) hay FAR ; thân thủ tục …………… RET ENDP Thủ tục thường được viết ở cuối chương trình. Gọi thủ tục: CALL CALL ; địa chỉ là thanh ghi hoặc vùng nhớ chứa địa chỉ ; thủ tục 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ự 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 à .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 Khai báo Gọi thủ tục Nhap CALL Xuat IP = địa chỉ ô lệnh “pop bx” Lưu lại địa chỉ quay về BX = địa chỉ lệnh “CALL Xuat” Nhập ký tự a,b: 00 62 00 61 Trả lại địa chỉ quay về BX = địa chỉ lệnh “CALL Xuat” CALL Xuat 00 62 00 61 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. Macro 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ả. Khai báo: MACRO ; thân macro …………… ENDM 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 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 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 @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 Nguyễn Minh Tuấn, Giáo trình hợp ngữ - Chương 6, ĐHKHTN, 2002 Randal Hyde, The art of assembly language programming – Chapter 11,12. Norton Guide 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 Có những cách nào để truyền tham số cho thủ tục ? để nhận kết quả trả về ? Thử viết một thủ tục đệ quy. 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ệ.
File đính kèm:
- Thực hành Assembly - Bài 3 Ngăn xếp - Thủ tục - Macro.doc