intTypePromotion=1
zunia.vn Tuyển sinh 2024 dành cho Gen-Z zunia.vn zunia.vn
ADSENSE

Ngắt asm cơ bản

Chia sẻ: Trần Việt Tân | Ngày: | Loại File: PDF | Số trang:13

106
lượt xem
5
download
 
  Download Vui lòng tải xuống để xem tài liệu đầy đủ

Tài liệu tin học tham khảo "ngôn ngữ máy ASSEMBLY"

Chủ đề:
Lưu

Nội dung Text: Ngắt asm cơ bản

  1. ĐHQG – HN CNTT Ngôn ngữ máy ASSEMBLY Các ngắt của hệ thống hỗ trợ cho lập trình ASSSEMBLY combine có hai chức năng: Có 4 hàm hay dùng nhất: +cho phép đặt segment vào 1 địa chỉ mong muốn (theo yêu Hàm 1: Chờ 1 ký tự từ bàn phím: cầu) của bộ nhớ RAM Mov ah, 1 ;AL chứa mã ASCII ký tự mã vào tên_segment SEGMENT at địa_chỉ_dạng_vật_lý Int 21h {thân} Hàm 2: Đưa 1 ký tự dạng ASCII ra màn hình tại vị trí con tên_segment ENDS trỏ đang đứng +cho chương trình đa tệp: cách gộp các segment có cùng tên Cách 1: Nhờ ngắt của BIOS nằm ở các tệp khác nhau khi liên kết. Ví dụ: Tệp 1 có DATA Mov al, mã ASCII của ký tự SEGMENT; Tệp 2 có DATA SEGMENT.khác Mov ah, oeh _COMMON tức là độ dài của segment sau liên kết bằng độ Int 10h dài segment lớn nhất Cách 2: _PUBLIC tức là độ dài của segment sau liên kết bằng tổng Mov dl, mã ASCII của ký tự độ dài cả 2 segment Mov ah, 2 _PRIVATE tức là độ dài của segment sau liên kết bằng độ Int 21h dài của chính nó (không quan hệ với nhau, đây là chế độ Hàm 3: Hiện 1 xâu ký tự kết thúc bằng dấu $ ra màn default) hình _STACK giống như _PUBLIC Mov dx, offset tên biến xâu _CLASS sắp xếp các segment lại gần nhau sau khi liên kết Mov ah, 9 (Sau khi liên kết thì những segment nào cùng một nhóm thì ở Int 21h gần nhau) Hàm 4: Trở về DOS _GROUP gộp các segment có cùng kiểu lại với nhau cho dễ Mov ah, 4ch ;[int 20h] dàng qui chiếu Int 21h tên_ nhóm GROUP tên_các_segment (cách nhau bởi Các DIRECTIVE điều khiển SEGMENT dạng đơn giản: dễ dấu , ) viết, dễ liên kết nhưng chưa bao hết mọi tình huống về điều _ASSUME cho biết tên segment thuộc loại segment nào khiển SEGMENT _ASSUME tên_thanh_ghi SEG : tên_seg .Model thuê vùng nhớ RAM thích hợp cho chương trình Cấu trúc một chương trình Assembly thường thấy: Khai báo MACRO, STRUCT, UNION, RECORD, SEGMENT code+data≤ 64KB .Model kiểu_tiny Dạng đơn giản code≤ 64KB;data≤ 64KB .Model kiểu_small .Model kiểu code≤ 64KB;data≥ 64KB .Model kiểu_compact .Stack độ lớn code≥ 64KB;data≤ 64KB .Model kiểu_medium [.Data code≥ 64KB;data≥ 64KB song khi .Model kiểu_large khai báo biến] khai báo1 array không ≤ 64KB .Code code≥ 64KB;data≥ 64KB song khi .Model kiểu_large nhãn_chương_trình: khai báo1 array không >64KB mov ax, @data .Stack Độ lớn (Byte) → Xác lập độ lớn stack cho chương trình mov ds, ax .Data Xác lập vùng nhớ cho dữ liệu của chương ... trình khai báo biến nằm ở segment này thân chương trình .Data Khai báo biến (có 3 loại biến) ... Với các loại biến số thì kiểu db có độ dài 1 byte mov ah, 4ch dw có độ dài 2 byte int 21h dd có độ dài 4 byte [các chương trình con] dp/df có độ dài 6 byte END nhãn_chương_trình dq có độ dài 8 byte dt có độ dài 10 byte Dạng chuẩn Với các loại biến xâu có các cách khai báo như sau: _Stack segment tên_biến_xâu db ‘các ký tự’ db độ_dài dup(?) tên_biến_xâu db độ_lớn dup(‘1 ký tự’) _Stack ends tên_biến_xâu db độ_lớn dup(?) Data segment Với các loại biến trường số (array) có các cách khai báo như khai báo biến sau: Data ends tên_biến_trường kiểu_thành_phần (các số cách nhau bởi Code segment dấu ,) Assume cs:code ds:data ss:stack tên_biến_trường kiểu_thành_phần độ_lớn dup(giá trị 1 số) nhãn_chương_trình: tên_biến_trường kiểu_thành_phần độ_lớn dup(?) mov ax, data .Code Xác lập vùng nhớ truy xuất ngẫu nhiên dùng cho phần mov ds, ax mã máy ... .Code thân chương trình nhãn_chương_trình: ... mov ax, @data mov ah, 4ch mov ds, ax int 21h ... [các chương trình con] thân chương trình ENDS ... END nhãn_chương_trình mov ah, 4ch *Chương trình con: int 21h 1, Cơ chế khi 1 chương trình con bị gọi: [các chương trình con] Bước 1: Tham số thực đưa vào STACK end nhãn_chương_trình Bước 2: Địa chỉ của lệnh tiếp theo được đưa vào STACK Các DIRECTIVE điều khiển SEGMENT dạng chuẩn: Bước 3: Hệ điều hành quản lý địa chỉ đầu của chương trình _SEGMENT; _GROUP; _ASSUME con do vậy Hệ điều hành sẽ đưa địa chỉ đó vào CS:IP → rẽ _SEGMENT Xác lập các segment cho chương trình nhánh vào chương trình con tên_segment SEGMENT align combine use ‘class’ Bước 4: Thực hiện thân chương trình con cho đến khi gặp lệnh {thân segment} RET thì vào STACK lấy địa chỉ lệnh tiếp theo (đã cất ở Bước 2) tên_segment ENDS và cho vào CS:IP, rồi quay về chương trình đã gọi nó trong đó: Bước 5: Tiếp tục thực hiện chương trình đang đợi tên_segment là 1 identifier (không chứa dấu cách, dấu \ ; : ...) 2, Cú pháp của chương trình con Assembly: align là cách xác lập khoảng cách giữa segment đang khai báo Tên_chương_trình_con PROC [NEAR/FAR] với segment trước nó Bảo vệ các thanh ghi sẽ bị phá vỡ ở thân chương trình align Thân chương trình con byte khoảng cách 1 byte Hồi phục các thanh ghi mà chương trình con phá vỡ word khoảng cách 2 byte RET paka khoảng cách 16 byte Tên_chương_trình_con ENDP page khoảng cách 256 byte 1
  2. ĐHQG – HN CNTT Ngôn ngữ máy ASSEMBLY a, Vấn đề NEAR – FAR: IFB NEAR chương trình con cùng nằm trên 1 segment với chương Khối_lệnh ENDIF trình gọi nó → địa chỉ lệnh tiếp theo cất vào STACK (Bước 2) Lệnh IFNB giống như lệnh IFB nhưng ngược điều kiện chỉ cần 2 byte offset Chức năng: Dịch khối lệnh khi = FAR chương trình con nằm khác segment với chương trình con IFIDN , gọi nó → địa chỉ lệnh tiếp theo cất vào STACK (Bước 2) cần Khối_lệnh đến 4 byte offset ENDIF * Với khai báo segment dạng đơn giản thì directive model sẽ Lệnh IFDIF giống như lệnh IFIDN nhưng ngược điều kiện xác định hiện chương trình con NEAR hay FAR Chức năng: Dịch khối lệnh khi nhãn theo sau đó đã được khai → chương trình con là NEAR . Model tiny báo → chương trình con là NEAR . Model small IFDEF nhãn . Model compact → chương trình con là NEAR Khối_lệnh . Model medium → chương trình con là FAR ENDIF → chương trình con là FAR . Model large Lệnh IFNDEF giống như lệnh IFDEF nhưng ngược điều kiện → chương trình con là FAR . Model huge *Macro là 1 cơ chế giúp người lập trình tạo 1 lệnh mới trên cơ * Với khai báo dạng chuẩn thì mặc định là NEAR sở tập lệnh sẵn có của Assembly b, Chương trình con Assembly không có đối số → cơ chế - Trước khi được dùng thì phải khai báo kích hoạt chương trình con Assembly không có Bước 1 Cú pháp: 3, Chuyển giao tham số: Tên_Macro MACRO[đối] Cách 1: Nhờ thanh ghi Bảo vệ các thanh ghi sẽ bị phá vỡ ở thân chương trình Chương_trình_chính Chương_trình_con Thân MACRO ...... ...... Hồi phục các thanh ghi mà chương trình con phá vỡ mov ax, 10 mov bx, ax ENDM call Chương_trình_con ...... - Cách dùng lệnh mới đã xác lập ở MACRO: Sau khi macro đã ...... được xác lập thì tên của Macro trỏ thành một lệnh mới của (khi đó bx = 10) ASM Cách 2: Nhờ biến nhớ - Cách dùng: Gọi tên macro và thay vì đối sẽ là tham số thực Chương_trình_chính Chương_trình_con Chương trình Macro hiện xâu ra màn hình: ...... ...... HIENSTRING MACRO XAU mov value, 20 mov bx, value Push ax, bx call Chương_trình_con ...... Lea dx, XAU ...... Mov ah, 9 (khi đó bx = 20) Int 21h Cách 3: Thông qua STACK (dùng khi liên kết với ngôn ngữ lập Pop dx, ax trình bậc cao) ENDM 4, Bảo vệ thanh ghi: Chương trình Macro xóa màn hình: Khi thân chương trình con sử dụng các lệnh làm giá trị thanh CLRSCR MACRO ghi thay đổi như and, xor, ... thì phải bảo vệ các thanh ghi đó Push ax trước khi dùng Mov ah, 0fh Cách 1: Dùng các lệnh POP, PUSH Int 10h Cách 2: Chuyển vào biến hoặc thanh ghi khác sau đó hồi phục Mov ah, 0 Tệp include Int 10h Tệp INCLUDE cho phép người lập trình viết gọn chương trình Pop ax - Thiết lập 1 tệp ngoài (gọi là tệp INCLUDE) mà trong tệp này ENDM chứa khối lệnh Assembly .ASM tính ưu việt của macro - Sau đó dùng lệnh INCLUDE để chèn khối lệnh đó vào tệp a, So sánh Macro với chương trình con: chương trình đang viết. Cú pháp: Tốc độ: Khi chạy chương trình thì Macro nhanh hơn vì không .............. phải dùng lệnh CALL và RET INCULDE X:\đường dẫn\tệp INCLUDE Tiết kiệm bộ nhớ: Chương trình con chiếm ít bộ nhớ hơn .............. Macro cho phép chuyển giao tham số thông qua đối và cho - Cơ chế của chương trình dịch Assembly khi gặp INCLUDE: phép sử dụng các Directive lặp khidịch chương trình. Các chương trình dịch của Tubor Assember khi gặp INCLUDE thì Directive điều khiển điều kiện khi dịch chương trình. thực hiện các bước: b, So sánh Macro với tệp INCLUDE: * Mở tệp INCLUDE theo sau Directive Include Cơ chế: Giống nhau khi dịch * Sao chép và chèn toàn bộ khối lệnh Assembly có trong tệp Tốc độ: Khi chạy chương trình thì Macro nhanh hơn vì không INCLUDE vào vị trí Directive Include đứng phải mở đóng tệp * Tiến hành dịch khối lệnh đó Macro cho phép có nhãn nhảy trong lệnh của Macro nhờ - Cách tìm tệp INCLUDE để chèn Directive Local. Trong thân Macro cho phép có các Macro khác * Nếu tệp đứng sau Directive Include có tên đĩa, đường dẫn thì Chương trình dạng *.com và *.exe chương trình dịch tìm đến, nếu không có thì đó là thư mục hiện Chương trình .EXE có 3 segment {code, data và stack}. Có hành, còn nếu không có nữa thì sai thể không cùng nằm trên 1 segment * Nếu sai thì chỉ có cách sửa lại chương trình nguồn. Khi dịch Chương trình .COM có 3 segment {code, data và stack} nằm chương trình dùng thêm tham số TASM -i A:\...\*.ASM cùng trên 1 segment. Khi chạy chương trình .COM cần 256 - Hạn chế của INCLUDE là không được phép có nhãn nhảy byte đầu của segment đó để nhảy. Do vậy, lệnh đầu của trong khối lệnh của tệp INCLUDE khi gọi nó 2 lần chương trình .COM sẽ đặt ở offset → người lập trình phải khai macro và các vấn đề liên quan báo cho hệ điều hành Directive ORG 1, Các lệnh lặp khối lệnh khi dịch chương trình: Khai báo chương trình dạng .COM có 1 segment và là Code REPT dịch khối lệnh theo số lần đi sau REPT Segment → biến cũng được khai báo ở Code Segment REPT n .Code Khối_lệnh Nhãn_chương trình: ENDM Jmp nhãn_khác IRP dịch khối lệnh theo số lượng danh sách [nếu có khai báo biến] IRP tên_đối Khai báo biến Khối_lệnh Nhãn_khác: ENDM ...... - Các Directive điều khiển điều kiện khi dịch chương trình mov ah, 4ch Chức năng: Dịch khối lệnh khi điều kiện đúng TRUE int 21h IF IF Dạng thường thấy của chương trình .COM thuần túy Khối_lệnh Khối_lệnh_1 [Khai báo MACRO, STACK, UNION, RECORD] ENDIF ELSE Khối_lệnh_2 Dạng đơn giản Dạng chuẩn ENDIF .Model tiny .Code segment Lệnh IFE giống như lệnh IF nhưng ngược điều kiện (hoặc small) ORG 100h Chức năng: Dịch khối lệnh khi biểu thức = 0 2
  3. ĐHQG – HN CNTT Ngôn ngữ máy ASSEMBLY .Code assume cs:code,ds:code,ss:code Bước 2: Địa chỉ lệnh tiếp theo → STACK ORG 100h Nhãn_chương_trình: Bước 3: Hệ điều hành quản lý địa chỉ đầu của chương trình Nhãn_chương_trình: Jmp nhãn_khác con phục vụ ngắt. Song địa chỉ đầu của chương trình con phục Jmp nhãn_khác Khai báo biến vụ ngắt nằm trong ô nhớ tương ứng của bảng vectơ ngắt → Khai báo biến Nhãn_khác: máy tính vào vectơ ngắt lấy địa chỉ đầu của chương trình con Nhãn_khác: ........ phục vụ ngắt đưa vào cs:ip → rẽ nhánh vào chương trình con ......... int 20h phục vụ ngắt int 20h [các chương trình con] Bước 4: Thực hiện các lệnh của chương trình con cho đến khi [các chương trình con] code ends gặp IRET thì vào STACK lấy địa chỉ lệnh tiếp theo (đã cất ở END nhãn_chương_trình END nhãn_chương_trình bước 2) → cs:ip và trở về chương trình đang dở Directive public Bước 5: Trước khi tiếp tục chương trình đang dở thì vào Chức năng: Báo cho chương trình dịch biết những nhãn ở STACK lấy cờ đã cất Model này cho phép các tệp khác cũng có thể dùng Bảng vectơ ngắt: là vùng nhớ RAM chứa địa chỉ đầu của Cú pháp: Public tên_nhãn chương trình con phục vụ ngắt. Máy tính có 256 ngắt → có 256 Khai báo kiểu nhãn chương trình con phục vụ ngắt. Địa chỉ ô bằng n * 4 (mỗi địa .Với hằng: Public tên_hằng = hằng chỉ 4 byte) Public Port Các bước để xác lập chương trình con phục vụ ngắt: Port = 038h Bước 1: Viết chương trình con theo yêu cầu của thuật toán .Với biến: Public tên_biến Cú pháp: Tên_chtrình_con_pvụ_ngắt PROC [NEAR/FAR] Khai báo biến Bảo vệ các thanh ghi .Với tên chương trình con: Thân chương trình Public tên_chương_trình_con Phục hồi các thanh ghi tên_chương_trình_con PROC IRET ........... Tên_chtrình_con_pvụ_ngắt ENDP RET Bước 2: Sau khi viết xong chương trình con phục vụ ngắt thì tên_chương_trình_con ENDP tìm địa chỉ đầu của chương trình này đưa vào vị trí tương ứng Directive public của bảng vectơ ngắt Chức năng: Báo cho chương trình dịch biết Module này xin Khởi động máy tính với hệ điều hành DOS phép được dùng các nhãn mà các Module khác đã cho phép Với máy tính của INTEL, khi bật máy thì thanh ghi CS = F000h; Cú pháp: Extrn tên_nhãn: kiểu IP = FFF0h và sẽ nhảy vào thực hiện lệnh ở ô nhớ F000:FFF0. .Nhãn là tên hằng: Extrn tên_nhãn: ABS Lệnh này là lệnh jmp và nó nhảy đến chương trình khởi động Extrn Post kiểu máy tính đều nằm ở ROM-BIOS .Nhãn là biến nhớ: Extrn x: word (hoặc byte hoặc dword) ROM-BIOS là vùng nhớ chỉ đọc, không ghi được và chứa 2 loại .Nhãn là chương trình con: chương trình khởi động máy và chương trình phục vụ ngắt của Extrn tên_chương_trình_con:PROC BIOS Directive global Các chương trình khởi động máy tính: Chức năng: Không phải chương trình nào cũng có Directive Test CPU: kiểm tra các thanh ghi. Tống vào các giá trị 00, 55 này, nó thay cho Public và Extrn và FF vào các thanh ghi và kiểm tra lại có bằng 00, 55 và FF Cú pháp: GLOBAL tên_nhãn: kiểu không. Đồng thời kiểm tra một số lệnh ASM nếu có lỗi thì hiện Khai báo biến FATA ERROR. Liên kết C với Assembly Kiểm tra ROM-BIOS: trong ROM có 1 byte CHECKSUM (tổng các INLINE ASM là chèn khối lệnh ASM vào chương trình được viết byte của ROM) khi khởi động thì có 1 chương trình cộng các bằng C byte của ROM lại lưu kết quả vào 1 byte và so sánh byte này Cú pháp: khối lệnh C với CHECKSUM. Nếu bằng nhau thì tức là ROM tốt, ngược lại là ASM lệnh ASM tồi. ........... Kiểm tra một số linh kiện quan trọng của mainboard ASM lệnh ASM 8259 là chip phục vụ ngắt khối lệnh C 8250 UART (COM) Dịch và liên kết 8253 Timer TCC -ms :IC\TC\INCLUDE -LC 8237 DMA Hạn chế: Các lệnh ASM được chèn thì dịch nhờ bởi chương Kiểm tra RAM (giống hệt CPU và thanh ghi) tức là cho toàn bộ trình dịch của TC. Do đó 1 số lệnh khó của ASM dịch không các byte của RAM các giá trị 00, 55, FF liệu RAM có chấp nhận đúng. Không cho phép có các nhãn nhảy trong ASM → khối các giá trị này không lệnh chèn vào yếu (vì không có LOOP, nhảy có và không có Xác lập bảng vec tơ ngắt của BIOS điều kiện) Đưa mọi địa chỉ đầu của các chương trình con phục vụ ngắt Viết tách biệt tệp cho c và tệp cho asm vào bảng vec tơ ngắt Phải giải quyết 3 vấn đề: Đưa các thông số máy tính đang dùng vào vùng nhớ biến BIOS 1, Vấn đề đa tệp: (khai báo Public) với Module của C, bất kỳ Kiểm tra liệu có ROM mở rộng: với màn hình và ổ đĩa thì về khai báo nào của C đều là khai báo Public. Khai báo External phần cứng cho các Card điều khiển không giống nhau → không ngôn ngữ C phải xin phép dùng các nhãn đã cho phép từ tệp thể viết 1 driver chung và nạp vào ROM-BIOS chuẩn → thỏa ngoài. Với Module ASM giống như đa tệp thuần túy hiệp của các hãng: Ai sản xuất phần cứng thì viết driver cho nó 2, Vấn đề dấu (-) (underscore) người viết chương trình ASM và nạp vào ROM và ROM đó sẽ được đặt trên Card đó phải thêm dấu – vào trước trên các nhãn dùng chung với C và Int 19h: Lôi boot sector xuống RAM và trao quyền cho chương thêm ở mọi nơi mà tên đó xuất hiện trình nằm trong boot sector 3, Vấn đề giá trị quay về của hàm ASM: qui định với giá trị Trong boot sector là sector 512 byte chứa tham số đĩa và chứa 2 byte thì trước khi RET ax = bao nhiêu thì tên hàm ASM có giá chương trình mồi trị bấy nhiêu. Với giá trị 4 byte trước khi RET dx:ax có giá trị Chương trình mồi lôi 2 tệp ẩn xuống RAM (hệ điều hành DOS) bao nhiêu thì hàm ASM có giá trị bấy nhiêu Kiểm tra thiết bị ngoại vi cơ chế khi một ngắt và chương trình con được kích hoạt Lôi COMMAND.COM vào vùng nhớ RAM – là chương trình dịch Chương trình con bình thường: các lệnh của DOS → Mã máy CALL CONFIG.SYS Bước 1: Tham số thực → STACK AUTOEXEC.BAT Bước 2: Địa chỉ lệnh tiếp theo → STACK C:\> Bước 3: Hệ điều hành quản lý địa chỉ đầu của chương trình con → Hệ điều hành đưa địa chỉ đầu của chương trình con → cs:ip → rẽ nhánh vào chương trình con Bước 4: Thực hiện các lệnh của chương trình con → RET thì vào STACK lấy địa chỉ lệnh tiếp theo (đã cất ở bước 2) → cs:ip và trở về chương trình đang dở Bước 5: Tiếp tục chương trình đang dở Chương trình con phục vụ ngắt: Int n (tác động linh kiện) Bước 1: Flag → STACK;Tham số thực → STACK 3
  4. ĐHQG – HN CNTT Ngôn ngữ máy ASSEMBLY mov ah,1 int 21h cmp al,'c' je ps mov ah,4ch int 21h Bài tập 1: include C:\HTDAT\INCLUDE\lib2.asm Hiện 1 xâu ký tự “Hello TASM!” ra màn hình code ends Cách 1: end ps .MODEL small So sánh 2 số nhập vào từ bàn phím xem số nào bé hơn .STACK 100h Cách 2: .DATA hien_string MACRO xau Message db ‘Hello TASM!$’ push ax dx .CODE mov dx,offset xau ProgramStart: mov ah,9 Mov AX,@DATA int 21h Mov DS,AX pop dx ax Mov DX,OFFSET Message ENDM Mov AH,9 ;--------------------------------- Int 21h .model small Mov AH,4Ch .stack 100h Int 21h .data END ProgramStart sohex dw ? Cách 2: temp dw ? _STACK segment stack ‘stack’ m1 db 0ah,0dh,'Vao so thu1: $' db 100h dup(?) m2 db 0ah,0dh,'Vao so thu2: $' _STACK ends m3 db 0ah,0dh,'So be la: $' DATA segment .code Message db ‘Hello TASM!’,0 ps: DATA ends mov ax,@data CODE segment mov ds,ax Assume CS:CODE, DS:DATA, SS:_STACK hien_string m1 ProgramStart: call VAOSO Mov AX,DATA mov ax,sohex Mov DS,AX mov temp,ax Mov SL,OFFSET Message hien_string m2 cld call VAOSO L1: mov bx,sohex Lodsb hien_string m3 And AL,AL cmp ax,bx Jz Stop jl L1 Mov AH,0eh xchg ax,bx Int 10h L1: Jmp L1 call HIENSO Stop: mov ah,1 Mov AH,1 int 21h Int 21h mov ah,4ch Mov AH,4Ch int 21h Int 21h ;-------------------------------------------- CODE ends VAOSO PROC END ProgramStart push ax bx cx dx Bài tập 2: mov bx,10 So sánh 2 số nguyên nhập từ bàn phím xem số nào bé xor cx,cx hơn mov sohex,cx Cách 1: VS1: include C:\HTDAT\INCLUDE\lib1.asm mov ah,1 ; Ham nhan 1 ki tu va --->al _stack segment stack 'stack' int 21h db 100h dup(?) cmp al,0dh _stack ends je VS2 data segment sub al,30h m1 db 10,13,'Vao so thu nhat:$' mov cl,al m2 db 10,13,'Vao so thu hai:$' mov ax,sohex m3 db 10,13,'So be la:$' mul bx m4 db 10,13,'Co tiep tuc khong (c/k)?:$' add ax,cx data ends mov sohex,ax code segment jmp VS1 assume cs:code,ds:data,ss:_stack VS2: ps: pop dx cx bx ax mov ax,data ret mov ds,ax VAOSO ENDP clrscr ;---------------------------------------------- hienstring m1 HIENSO PROC call Vao_so_N push ax bx cx dx mov bx,ax mov bx,10 hienstring m2 xor cx,cx call Vao_so_N HS1: cmp ax,bx xor dx,dx jl L1 div bx ; tuc lay dx:ax chia cho bx kq thuong-->ax va du-- xchg ax,bx >dx L1: add dx,30h ; de dua ra dang ASCCI hienstring m3 push dx ; tong 1 chu vao stack call Hien_so_N inc cx hienstring m4 cmp ax,0 4
  5. ĐHQG – HN CNTT Ngôn ngữ máy ASSEMBLY jnz HS1 mov ds,ax HS2: clrscr pop ax hienstring m1 mov ah,0eh call vao_so_N int 10h hienstring m2 loop HS2 call Hien_so_N pop dx cx bx ax hienstring m3 ret call S_N_T HIENSO ENDP mov ax,fv end ps call hien_so_N Bài tập 3: hienstring m4 Tính trung bình cộng 2 só nguyên nhập từ bàn phím mov ah,1 INCLUDE C:\INCLUDE\LIB1.ASM int 21h _STACK segment cmp al,'c' db 100h dup(?) je ps _STACK ends mov ah,4ch DATA segment int 21h M1 db ‘Hay vao so thu 1: $’ include C:\HTDAT\INCLUDE\lib3.asm M2 db 0ah,0dh,‘Hay vao so thu 2: $’ include C:\HTDAT\INCLUDE\lib2.asm M3 db 0ah,0dh,‘Trung binh cong cua 2 so code ends nguyen la: $’ end ps M4 db ‘-$’ Chương trình tính giai thừa của một số n nhập từ bàn M5 db ‘.5$’ phím M6 db 0ah,0dh,’ Co tiep tuc khong (c/k) ?: Cách 2: $’ code segment DATA ends assume cs:code,ds:code CODE segment org 100h assume cs:code,ds:data,ss:_stack start: jmp do ps: msg1 db 'nhap vao mot so:$' mov ax,data msg2 db 'ket qua la:$' mov ds,ax giaithua dw 1 clrscr so dw 0 HienString M1 m db 'ok $' call VAO_SO_N do : mov bx,ax mov ah,09h HienString M2 mov dx,offset msg1 call VAO_SO_N int 21h HienString M3 call nhapso Add ax,bx call cr_lf And ax,ax mov bx,1 Jns L1 mov cx,ax HienString M4 lap: Neg ax mov ax,giaithua L1: mul bx Shr ax,1 inc bx Pushf mov giaithua,ax Call HIEN_SO_N loop lap Popf mov ax,giaithua Inc L2 push ax HienString M5 push dx L2: mov ah,09h HienString M6 mov dx,offset msg2 Mov ah,1 int 21h Int 21h pop dx Cmp al,’c’ pop ax Je TT call inra Mov ah,4ch mov ah,01h Int 21h int 21h TT: int 20h Jmp ps ;-------------------------- INCLUDE C:\INCLUDE\LIB2.ASM cr_lf proc near CODE ends push ax END ps push dx Bài tập 4: mov ah,02h Nhập một số nguyên dương n từ bàn phím và tìm giai mov dx,0dh thừa của nó int 21h Cách 1: mov dx,0ah include C:\HTDAT\INCLUDE\lib1.asm int 21h _stack segment stack 'stack' pop dx db 100h dup(?) pop ax _stack ends ret data segment cr_lf endp fv dw ? ;--------------------------- fac dw ? nhapso proc near m1 db 10,13,'Vao so n:$' push dx m2 db 10,13,'Giai thua cua $' push cx m3 db ' la:$' push bx m4 db 10,13,'Co tiep tuc khong(c/k)?: ' xor dx,dx data ends mov so,0 code segment mov cx,1 assume cs:code,ds:data,ss:_stack lap1: call nhap ps: cmp al,0dh mov ax,data je exit 5
  6. ĐHQG – HN CNTT Ngôn ngữ máy ASSEMBLY sub al,30h Mov DS,AX xor ah,ah CLRSCR xor dx,dx HienString M1 mov dx,ax Call VAO_SO_N mov ax,so HienString M2 cmp cx,1 Call VAO_SO_N je nota HienString M3 mov bl,10 Mov BX,AX mul bl Mov so,1 nota: add ax,dx L1: mov so,ax Inc so inc cx Mov AX,so jmp lap1 Cmp AX,BX exit: mov ax,so Jg Stop pop bx Mov CX,AX pop cx Shr CX,1 pop dx L2: ret Cmp CX,1 nhapso endp Jle L3 ;--------------------------- Xor DX,DX inra proc Div CX mov bx,10 And DX,DX xor cx,cx Jz L1 none_zero: Mov AX,so xor dx,dx Loop L1 div bx L3: push dx Call HIEN_SO_N inc cx HienString M4 or ax,ax Jmp L1 jnz none_zero Stop: write: pop dx HienString M5 add dl,'0' Mov AH,1 mov ah,02 Int 21h int 21h Cmp AL,’c’ loop write Je TT ret Mov AH,4Ch inra endp Int 21h TT: ;--------------------------- Jmp PS public nhap INCLUDE C:\INCLUDE\LIB2.ASM nhap proc near CODE ends sta : END PS push dx Bài tập 6: mov ah,08 Nhập 2 số vào từ bàn phím và in ra tích của chúng int 21h EXTRN cmp al,0dh je exit1 CR_LF:PROC,PRINT_CHAR:PROC,GET_IN_NUMBER:PROC,WRITE_ cmp al,30h CHAR:PROC jb sta ;---------------------------------- cmp al,39h DATA_SEG SEGMENT PUBLIC ja sta DATA_1 DB 'ENTER TWO STRING:$' mov dl,al DATA_2 DB 'NUMBER1:$' ; xor ah,ah DATA_3 DB 'NUMBER2:$' PRODUCT DB 'PRODUCT IS:$' mov ah,02h TEMP_VAR DW 0 int 21h TEMP DW 0 exit1: NUMBER DW 0 pop dx DATA_SEG ENDS ret ;------------------------------- nhap endp STACK SEGMENT STACK ;---------------------------- DB 64 DUP('STACK') code ends STACK ENDS end start ;------------------------------ Bài tập 5: CODE_SEG SEGMENT PUBLIC Tìm số nguyên tố nhỏ hơn hoặc bằng số giới hạn cho ASSUME CS:CODE_SEG,DS:DATA_SEG,SS:STACK trước START: MOV AX,DATA_SEG ;khoi tao thanh ghi DX INCLUDE C:\INCLUDE\LIB1.ASM MOV DS,AX _STACK segment MOV AH,09 ;yeu cau nhap db 100h dup(?) MOV DX,OFFSET DATA_1 _STACK ends INT 21H DATA segment CALL CR_LF M1 db ‘Hay vao so gioi han: $’ MOV AH,09 ; so thu 1 M2 db 0ah,0dh,’ Cac so nguyen to MOV DX,OFFSET DATA_2 tu 2 den $’ INT 21H M3 db ‘la: $’ CALL PRINT_CHAR M4 db 0ah,0dh,’ Co tiep tuc CMP AX,99 khong (c/k) ?: $’ JA EXIT So dw dw MOV TEMP_VAR,AX DATA ends CALL CR_LF CODE segment MOV AH,09 ; so thu 2 Assume CS:CODE, DS:DATA, SS:_STACK MOV DX,OFFSET DATA_3 PS: INT 21H Mov AX,DATA CALL PRINT_CHAR 6
  7. ĐHQG – HN CNTT Ngôn ngữ máy ASSEMBLY CMP AX,99 DIV BX JA EXIT PUSH DX CALL CR_LF INC CX MUL NUMBER ;AX:=AX*NUMBER OR AX,AX PUSH AX JNZ LOOP_2 MOV AH,09 JE PRINT MOV DX,OFFSET PRODUCT PRINT: POP DX INT 21H ADD DX,30H POP AX MOV AH,02H CALL WRITE_CHAR INT 21H EXIT: MOV AH,4CH LOOP PRINT INT 21H RET CODE_SEG ENDS WRITE_CHAR ENDP END START ;---------------------------- ;---------------------------------- Bài tập 7: CR_LF PROC FAR Tính tổng hai số nhập từ bàn phím PUSH AX CODE_SEG SEGMENT BYTE PUBLIC PUSH DX ASSUME CS:CODE_SEG,DS:CODE_SEG MOV AH,02 ORG 100H MOV DX,0AH START: JMP FIRST INT 21H MSG DB 'NHAP VAO 2 SO DE CONG :$' MOV DX,0DH MSG1 DB 'SO THU NHAT :$' INT 21H MSG2 DB 'SO THU HAI :$' POP DX MSG3 DB 'TONG CUA CHUNG LA :$' POP AX NUMBER1 DB 0 RET NUMBER2 DB 0 CR-LF ENDP ;----------------------------------- soam db ? GET_IN_NUMBER PROC dauso1 db ? PUSH DX dauso2 db ? NHAY: MOV AH,08 INT 21H FIRST: MOV AH,09H CMP AL,0DH MOV DX,OFFSET MSG JE EXIT_1 INT 21H CMP AL,30H call cr_lf JB NHAY MOV AH,09H CMP AL,39H MOV DX,OFFSET MSG1 JA NHAY INT 21H MOV DL,AL MOV AH,02 mov soam,0 INT 21H mov dauso1,0 EXIT_1: POP DX CALL GET_AN_INT_NUM MOV AX,4CH cmp soam,1 INT 21H jne so1khongam RET mov dauso1,1 GET_IN_NUMBER ENDP so1khongam: ;------------------------------------ CMP AX,255 PRINT_CHAR PROC NEAR Jb tieptuclam PUSH DX int 20h PUSH BX MOV TEMP,0 tieptuclam: MOV NUMBER1,AL MOV CX,1 CALL CR_LF LOOP_1: CALL GET_IN_NUMBER CMP AL,0DH MOV AH,09H JE EXIT_2 MOV DX,OFFSET MSG2 SUB AL,30H INT 21H MOV DX,AX XOR AH,AH mov soam,0h MOV AX,TEMP mov dauso2,0 CMP CX,2 CALL GET_AN_INT_NUM JB NONE_ZERO cmp soam,1 MOV BX,10 jne so2khongam MUL BX mov dauso2,1 NONE_ZERO: so2khongam: ADD AX,DX CMP AX,255 MOV TEMP,AX JA EXIT INC CX MOV NUMBER2,AL CMP CX,2 CALL CR_LF JA EXIT_2 JMP LOOP_1 MOV AH,09 EXIT_2: MOV AX,TAM MOV DX,OFFSET MSG3 POP BX INT 21H POP DX RET ;---------------------------------------------------------------- PRINT_CHAR ENDP mov cl,dauso1 ;---------------------------- add cl,dauso2 WRITE_CHAR PROC NEAR cmp cl,1 PUSH BX PUSH CX je khacdau ;HAI SO KHAC DAU XOR DX,DX MOV BX,10 XOR AX,AX MOV CX,1 MOV BL,NUMBER1 LOOP_2: ADD AL,BL 7
  8. ĐHQG – HN CNTT Ngôn ngữ máy ASSEMBLY PUSH AX POP DX cmp dauso1,1 SUM_UP: ADD AX,DX jne khongam MOV TEMP_VAR,AX call indau INC CX jmp khongam CMP CX,3 ;------------------------------------------------------------------ JA EXIT_2 khacdau: mov cl,number1 JMP LOOP_2 cmp cl,number2 ;SO1>SO2 ? EXIT_2: MOV AX,TEMP_VAR je writeZero POP DX ja laydauso1 POP CX ;-------------------------------------------------------- POP BX XOR AX,AX RET MOV BL,NUMBER1 GET_AN_INT_NUM ENDP SUB AL,BL ;---------------------------------------------- PUSH AX ; ;---------------------------------------------- cmp dauso2,1 GET_A_DEC_DIGIT PROC jne khongam LOOP_1: CALL INDAU PUSH DX JMP KHONGAM MOV AH,08H INT 21H laydauso1: XOR AX,AX CMP AL,0DH MOV AL,NUMBER1 JE EXIT_1 SUB AL,NUMBER2 ;------------------------ PUSH AX CMP AL,'-' cmp dauso1,1 JNE TIEP jne khongam JMP INSO CALL INDAU ;------------------------ TIEP: CMP AL,30H khongam: JB LOOP_1 CMP AL,39H POP AX JA LOOP_1 CALL WRITE_INT_NUMBER jmp exit INSO: MOV DL,AL writezero: mov ax,0 MOV AH,02 call write_int_number INT 21H EXIT_1: POP DX EXIT: RET INT 20 GET_A_DEC_DIGIT ENDP ;---------------------------------------------- ;------------------------------------------- ; ;---------------------------------------------- ;------------------------------------------- indau proc WRITE_INT_NUMBER PROC NEAR push ax MOV BX,10 push dx XOR CX,CX mov ah,02 NONE_ZERO: mov dl,'-' XOR DX,DX int 21h DIV BX pop dx PUSH DX pop ax INC CX ret OR AX,AX indau endp JNZ NONE_ZERO ;---------------------------------------------- WRITE_DIGIT_LOOP: GET_AN_INT_NUM PROC POP DX JMP $+4 ADD DL,48 ;=30H='0' TEMP_VAR DW 0 MOV AH,02 PUSH BX INT 21H PUSH CX LOOP WRITE_DIGIT_LOOP PUSH DX RET XOR DX,DX WRITE_INT_NUMBER ENDP MOV TEMP_VAR,0 ;--------------------------------- MOV CX,1 ; mov soam,0h ;--------------------------------- CR_LF PROC NEAR LOOP_2: CALL GET_A_DEC_DIGIT PUSH AX CMP AL,0DH PUSH DX JE EXIT_2 MOV AH,02 ;-------------------------------- MOV DL,0DH cmp al,'-' INT 21h jne tieptuc MOV DL,0AH mov soam,1h INT 21H jmp loop_2 POP DX ;------------------------------------------------------- POP AX tieptuc: SUB AL,30H RET XOR AH,AH CR_LF ENDP MOV DX,AX ;--------------------------------- MOV AX,TEMP_VAR CODE_SEG ENDS CMP CX,1 END START JE SUM_UP Bài tập 8: MOV BL,10 Chương Trình xác định số cổng COM và địa chỉ cổng PUSH DX COM MUL BL hien_string MACRO xau 8
  9. ĐHQG – HN CNTT Ngôn ngữ máy ASSEMBLY push ax dx DISKLITE -> chay chuong trinh mov dx,offset xau DISKLITE /U -> unload disklite* mov ah,9 CODE SEGMENT int 21h ASSUME CS:CODE,DS:CODE pop dx ax ORG 100h ENDM START: ;--------------------------------- JMP INIT ;nhay toi thu tuc khoi tao _STACK SEGMENT STACK 'STACK' MAGIC_CODE DB 'DISKLITE VERSION 1.0' db 100h dup(?) MAGIC_LEN LABEL BYTE _STACK ENDS NUM_IN EQU 11 ;so chu so de in data segment DISPLAY_BASE DW 0B800h m1 db 'Khong co cong COM. $' OLD_CHARS DB NUM_IN*2 DUP(?) m2 db 0ah,0dh,'So luong cong COM la: $' DISPLAY_DRV DB 'A',70h,':',70h,' ',70h ;in ten o dia m3 db 0ah,0dh,'Dia chi cong COM1 la: $' DISPLAY_TM DB '0',70h,'0',70h,':',70h,'0',70H,'0',70h,':',70h data ends DB 2 DUP('0',70h) code segment NUM_FLOPPIES DB ? assume cs:code,ds:data,ss:_STACK SECOND DB 0 ps: MINUTE DB 0 mov ax,data HOUR DB 0 mov ds,ax TICKER DB 0 ;so nhip dong ho D_DISK EQU (80-NUM_IN-1)*2 ;offset de ghi ten o dia mov ax,40h D_TIME EQU (82-NUM_IN)*2 ;offset ghi thoi gian mov es,ax ;dia chi byte trang thai moto o mem mov bx,11h MOTOSTATUS EQU 43Fh mov al,es:[bx] ;dia chi cong dia cung and al,0eh ; lay 3 bit chua so luong cong COM (0 0 0 0 | x x HARDPORT EQU 1F7h x 0) ;dia chi co dia cung ; 0 e HARDFLAGS EQU 48Ch ;(Neu flags and 8)=8 thi dang roi jnz l1 ;dia chi co IN_DOS hien_string m1 DAPTR EQU THIS DWORD jmp stop DAPTR_OFS DW ? l1: DAPTR_SEG DW ? hien_string m2 ;cac thuc tuc ngat cu shr al,1 OLDINT13_PTR EQU THIS DWORD add al,30h OLD_INT13 DW ? ;dia chi ngat 13H mov ah,0eh DW ? int 10h OLDINT1C_PTR EQU THIS DWORD hien_string m3 OLD_INT1C DW ? ;dia chi ngat 1C mov bx,2 ; cong COM 2 DW ? mov ax,es:[bx] INT13 PROC FAR push ax ASSUME CS:CODE,DS:NOTHING mov al,ah PUSHF ;luu thanh ghi co call HIENHEX PUSH AX pop ax PUSH CX call HIENHEX PUSH DX stop: PUSH SI mov ah,1 PUSH DI int 21h PUSH DS mov ah,4ch PUSH ES int 21h CALL GET_DISPLAY_BASE ;tinh dia chi doan bo nho man ; chuong trinh con HIENHEX va trong CTC nay lai chua CTC hinh HIEN CALL SAVE_SCREEN ;Luu 11 ky tu HIENHEX PROC CALL DISPLAY_DRIVE push ax cx CALL DISPLAY_TIME push ax POP ES mov cl,4 POP DS shr al,cl POP DI call HIEN POP SI pop ax POP DX and al,0fh POP CX call HIEN POP AX pop cx ax POPF ret PUSHF HIENHEX ENDP CALL DWORD PTR CS:OLD_INT13 HIEN PROC PUSHF cmp al,10 PUSH AX jl H PUSH CX add al,7 PUSH SI H: PUSH DI add al,30h PUSH DS mov ah,0eh PUSH ES int 10h LEA SI,OLD_CHARS ret MOV DI,D_DISK HIEN ENDP MOV CX,NUM_IN code ends CALL WRITE_S end ps POP ES Bài tập 9: POP DS Hiển thị tên ổ đĩa và thời gian đọc đĩa POP DI COMMENT * POP SI PROGRAM DISKLITE POP CX chuong trinh se hien thi ten o dia va thoi gian doc dia POP AX moi khi co truy nhap dia POPF Sudung: RET 2 9
  10. ĐHQG – HN CNTT Ngôn ngữ máy ASSEMBLY INT13 ENDP MOV DS,AX ;ky tu man hinh nam tai DS:SI INT1C PROC FAR MOV AX,CS ASSUME CS:CODE,DS:NOTHING MOV ES,AX ;old_chars nam tai ES:DI PUSH AX MOV CX,NUM_IN ;PUSH CX REP MOVSW PUSH DX RET PUSH DI SAVE_SCREEN ENDP ;PUSH SI ;thu tuc display_drive ghi ten o dia PUSH DS ;thay doi AX,SI,CX,DI ;PUSH ES DISPLAY_DRIVE PROC NEAR ;LDS DI,[DAPTR] ;nap IN_DOS vao DS:DI MOV AL,DL ;CMP BYTE PTR DI,0 ;co DOS co ban khong CMP AL,80h ;co phai o cung khong XOR AX,AX JB DISPLAY ;khong thi tiep tuc MOV DS,AX SUB AL,80h ;khong thi tru 80h MOV AL,BYTE PTR DS:[MOTOSTATUS] ;co o dia nao quay ADD AL,NUM_FLOPPIES ;cong voi so o dia khong DISPLAY: AND AL,3 ADD AL,'A' CMP AL,0 LEA SI,DISPLAY_DRV JNE CONTINUE ;neu ban thi tiep tuc MOV CS:[SI],AL ;MOV DX,HARDPORT ;cong dia cung chua byte so 7 la co MOV CX,3 bao ban MOV DI,D_DISK ;offset in ten dia ;IN AL,DX ;kiem tra cong dia cung CALL WRITE_S ;SHR AL,7 ;kiem tra bit 7 RET ;CMP AL,1 ;neu ban DISPLAY_DRIVE ENDP MOV AL,BYTE PTR DS:[HARDFLAGS] ;kiem tra co dia ;thu tuc display_time in so gio cung ;thay doi AX,CX,SI,DX AND AL,8 DISPLAY_TIME PROC NEAR CMP AL,8 ;neu co=8 la roi LEA SI,DISPLAY_TM ;dia chi cua gio de in JNE CONTINUE ;khong thi tiep tuc MOV DL,'0' XOR AL,AL MOV CS:[SI],DL MOV SECOND,AL MOV AL,HOUR MOV MINUTE,AL XOR AH,AH MOV HOUR,AL CMP AX,10 ;gio co lon hon muoi khong MOV TICKER,AL JB LESS_H JMP NOT_INC MOV CL,10 CONTINUE: DIV CL ;ket qua trong AL,so du trong AH XOR DL,DL ADD AL,'0' INC TICKER MOV CS:[SI],AL MOV AL,TICKER MOV AL,AH ;lay so du trong AH CMP AL,18 ;so nhip 18.2 lan trong mot giay LESS_H: JB NOT_INC ;neu Chua bang thi in ra man hinh INC SI MOV TICKER,DL ;neu qua thi dat lai ticker=0 INC SI INC SECOND ;tang giay ADD AL,'0' MOV AL,SECOND MOV CS:[SI],AL CMP AL,60 ;neu qua 60 giay thi tang phut ADD SI,4 ;dat SI vao offset cua minute JB NOT_INC MOV CS:[SI],DL ;dat truoc hang chuc=0 MOV SECOND,DL MOV AL, MINUTE INC MINUTE ;tang phut XOR AH,AH MOV AL,MINUTE CMP AX,10 ; phut co lon hon 10 khong CMP AL,60 JB LESS_M JB NOT_INC MOV CL,10 MOV MINUTE,DL DIV CL ;ket qua trong AL,so du trong AH INC HOUR ADD AL,'0' NOT_INC: MOV CS:[SI],AL ;CALL DISPLAY_TIME ;thu MOV AL,AH ;lay so du trong AH ;POP ES LESS_M: POP DS INC SI ;POP SI INC SI POP DI ADD AL,'0' POP DX MOV CS:[SI],AL ;POP CX ADD SI,4 ;dat SI vao offset cua second POP AX MOV CS:[SI],DL JMP DWORD PTR CS:OLD_INT1C MOV AL,SECOND INT1C ENDP XOR AH,AH ;thu tuc get_display_base xac dinh doan bo nho man hinh CMP AX,10 ; giay co lon hon 10 khong ; thay doi AX JB LESS_S GET_DISPLAY_BASE PROC NEAR MOV CL,10 INT 11h ;lay co thiet bi DIV CL ;ket qua trong AL,so du trong AH AND AX,30h ADD AL,'0' CMP AX,30h ;man hinh don sac MOV CS:[SI],AL MOV AX,0B800h MOV AL,AH ;lay so du trong AH JNE GET_BASE LESS_S: MOV AX,0B000h INC SI GET_BASE: INC SI MOV DISPLAY_BASE,AX ADD AL,'0' RET MOV CS:[SI],AL GET_DISPLAY_BASE ENDP LEA SI,DISPLAY_TM ;thu tuc savescreen luu manh hinh lai MOV CX,NUM_IN-3 ;thay doi AX,si,di,ds,es,cx MOV DI, D_TIME SAVE_SCREEN PROC NEAR CALL WRITE_S MOV SI,D_DISK ;lay dia chi bo nho man hinh RET MOV DI,OFFSET OLD_CHARS DISPLAY_TIME ENDP MOV AX,DISPLAY_BASE ;Thu tuc write_s in chuoi ra man hinh 10
  11. ĐHQG – HN CNTT Ngôn ngữ máy ASSEMBLY ;thay doi AX,ES,DS MOV AH,49h WRITE_S PROC NEAR INT 21h MOV AX,DISPLAY_BASE ;lay int 13 MOV ES,AX ;dia chi man hinh ES:DI MOV AX,3513h MOV AX,CS INT 21h MOV DS,AX ;dia chi display_tm tai DS:SI MOV CS:OLD_INT13,BX REP MOVSW MOV CS:OLD_INT13[2],ES RET ;dat int 13 WRITE_S ENDP MOV AX,2513h ;bat dau khoi tao PUSH CS INIT: ;bat dau thuong tru POP DS OLDPSP DW ? MOV DX,OFFSET INT13 BLOCMCB EQU 'M' ; bao hieu chua het MCB INT 21h LASTMCB EQU 'Z' ; da het MCB ;lay int 1C MCB STRUC ;cau truc cua MCB MOV AX,351Ch IDCODE DB ? INT 21h PSP DW ? MOV CS:OLD_INT1C,BX SIZE DW ? MOV CS:OLD_INT1C[2],ES MCB ENDS ;dat int 1C MOV AX,251Ch ;kiem tra xem da resident chua PUSH CS MOV AH,51h POP DS INT 21h ;lay PSP cua chuong trinh,gia tri cho trong MOV DX,OFFSET INT1C BX INT 21h MOV DX,BX ; giu gia tri vao DX MOV DX,OFFSET INIT_TSR CALL WRITE_MSG ;lay dia chi MCB dau ;ket thuc va noi tru MOV AH,52h MOV DX,OFFSET INIT INT 21h ;ES:BX-2 tro toi dia chi cua MCB dau tien INT 27h SUB BX,2 MOV AX,ES:[BX] YET_INST: ;da TSR roi thi kiem tra va ket thuc chuong trinh MOV ES,AX POP DI XOR BX,BX ;ES:BX la MCB dau POP ES MOV DI,OFFSET MAGIC_CODE ;ES:DI se chua MOV AX,ES:[BX].PSP Magic_code neu da thuong tru MOV OLDPSP,AX ;nap PSP cua TSR vao OLDPSP FIND_CODE: ;Tim xem da thuong tru chua CALL READPARAM CMP DX,ES:[BX].PSP ;xem PSP(MCB) co bang INT 20h PSP(PROG) JE TIEP ;co thi nhay sang MCB khac GET_NUM_DISK PROC NEAR MOV AX,DS ;dia chi cua chuong trinh thuong tru PUSH AX SUB AX,DX PUSH CX ADD AX,ES:[BX].PSP ;addr=PSP(MCB)+ INT 11h (segment(PROG)-PSP(PROG)) MOV CL,6 PUSH ES ;cat ES SHR AX,CL MOV ES,AX ;ES se chua doan chuong trinh thuong AND AL,3 tru neu da resident INC AL PUSH DI ;cat DI CMP AL,1 ;neu la 1 o dia MOV SI,DI ;DS:SI se chua magic_code cua JA GET_F ;thi ket thuc chuong trinh MOV AL,2 ;co hai o MOV CX,OFFSET MAGIC_LEN-OFFSET MAGIC_CODE GET_F: ;tinh chieu dai chuoi MOV NUM_FLOPPIES,AL REPE CMPSB ;kiem tra xem hai chuoi co bang POP CX nhau POP AX JCXZ YET_INST ;da co thuong tru ,ket thuc RET chuong trinh GET_NUM_DISK ENDP POP DI ;tra lai DI POP ES ;tra lai ES TIEP: READPARAM PROC NEAR CMP ES:[BX].IDCODE,LASTMCB ;da het MCB chua MOV SI,80h ;Dia chi duoi dong lenh JE NOT_INST MOV CL,[SI] ;so do chieu dai duoi lenh MOV AX,ES ;khong thi JCXZ NO_PARAM ;neu khong co thi bao loi va ket ADD AX,ES:[BX].SIZE ;cong ES voi SIZE+1 cua MCB thuc INC AX READ_PARAM: ;khong thi lap voi CX=so tham so MOV ES,AX ;ES:BX la MCB ke tiep INC SI ;tham so dau tien JMP FIND_CODE MOV BL,[SI] CMP BL,' ' NOT_INST: ;neu chua TSR thi khoi tao JE CON_READ ;neu la ky tu trang thi doc tiep CALL GET_NUM_DISK CMP BL,'/' ;co dung lenh khong JZ CON_READ ;dung thi tiep tuc ;xac dinh dia chi co in_dos CMP BL,'U' ;lenh vao la /U thi unload TSR MOV AH,34h JZ REMOVE ;dung thi loai TSR ra khoi bo nho INT 21h CMP BL,'u' MOV CS:DAPTR_OFS,BX ;offset cua co DOS JNZ W_PARAM MOV CS:DAPTR_SEG,ES ;segment cua co DOS REMOVE: CALL UNLOAD ;dung thi unload TSR ;giai phong khoi moi truong truoc khi TSR RET CON_READ: MOV ES,DX ;ES doan cua PSP cua chuong trinh se LOOP READ_PARAM thuong tru NO_PARAM: XOR BX,BX ;ES:BX chua dia chi PSP MOV DX,OFFSET YET_TSR MOV AX,ES:[BX].ENVSEG ;nap dia chi moi truong vao CALL WRITE_MSG ;khong co tham so thi in thong AX bao MOV ES,AX RET 11
  12. ĐHQG – HN CNTT Ngôn ngữ máy ASSEMBLY W_PARAM: push es ds si di ax MOV DX,OFFSET WRONG_PARAM push cs cs CALL WRITE_MSG pop ds es RET cmp ax,0FEFEh READPARAM ENDP je ALREADY lea di,Make UNLOAD PROC NEAR ;thu tuc de loai TSR ra khoi bo nho cmp ax,0BABAh PREFIX STRUC ;cau truc cua PSP je EQUAL0 DUMMY DB 2Ch DUP(?) cmp ax,0ABABh ENVSEG DW ? ;dia chi cua moi truong je EQUAL1 PREFIX ENDS jmp CONTINUE ;lay dia chi cua khoi moi truong MOV DX,OLDPSP ;nap OLDPSP vao DX ALREADY: MOV AX,351Ch ;kiem tra xem pop ax di si ds es INT 21h ;ngat 1CH co bi thay doi khong mov ax,0EFEFh MOV AX,ES ;AX chua dia chi cua ngat 1CH iret CMP AX,DX EQUAL0: JNE CHANGED ;neu khong bang thi ket thuc xor al,al stosb MOV AX,3513h ;kiem tra xem pop ax di si ds es INT 21h ;ngat 13H co bi thay doi khong iret MOV AX,ES ;AX chua dia chi cua ngat 13H EQUAL1: CMP AX,DX mov al,1 JNE CHANGED ;neu khong bang thi ket thuc stosb BEGIN_UNLOAD: ;neu khong thay doi thi loai TSR pop ax di si ds es ;giai phong bo nho ,luc nay ES da chua segment PSP cua iret TSR ;PUSH ES CONTINUE: MOV AH,49h lea si, Make ;POP ES ;ES la dia chi doan cua TSR lodsb INT 21h cmp al,0 ;dat lai ngat cu pop ax di si ds es PUSH DS ;cat DS je PASSBY CLI cmp ah,2 MOV AX,2513h ;dat lai ngat 13 je READ LDS DX,ES:OLDINT13_PTR cmp ah,3 INT 21h je READ PASSBY: MOV AX,251Ch ;dat lai ngat 1c jmp cs:Oldint13h LDS DX,ES:OLDINT1C_PTR INT 21h READ: cmp dl,0 STI je GOON POP DS ;tra lai DS cu cmp dl,1 MOV DX,OFFSET SUCCESS ;da loai ra khoi bo nho jne PASSBY CALL WRITE_MSG GOON: RET cmp ch,0 CHANGED: ;vec to ngat da bi doi je TRACK0 MOV DX,OFFSET UN_SUCCESS cmp ch,79 CALL WRITE_MSG je TRACK79 RET jmp PASSBY UNLOAD ENDP TRACK0: WRITE_MSG PROC NEAR add ch,79 PUSH AX jmp PASSBY MOV AH,9 INT 21h TRACK79: POP AX cmp ah,3 RET jne COMEBACK WRITE_MSG ENDP mov ah,1 ;khai bao cac chuoi de thong bao stc INIT_TSR DB 'DISKLITE VERSION 1.0',13,10 COMEBACK: DB ' COPYRIGHT (C) LE ANH TUAN 1994$' Iret YET_TSR DB 'CHUONG TRINH DA THUONG TRU$' WRONG_PARAM DB 'SAI THAM SO$' INIT: SUCCESS DB 'CHUONG TRINH DA DUOC UNLOAD$' mov si,80h UN_SUCCESS DB 'KHONG THE UNLOAD DUOC CHUONG lodsb TRINH$' push ax CODE ENDS mov ax,0FEFEh END START int 13h Bài tập 10: cmp ax,0EFEFh Chương trình sửa bad track 0 của đĩa mềm pop ax .model tiny jne INSTALL .code cmp al,1 org 100h jbe CHANGETRACK start: mov si,82h jmp INIT lodsw Oldint13h label dword cmp ax,0752Fh Int13hofs dw ? je NORMAL Int13hseg dw ? cmp ax,0552Fh Make db 1 je NORMAL lea dx,Error NEWINT13H: call WRITE 12
  13. ĐHQG – HN CNTT Ngôn ngữ máy ASSEMBLY ret CHANGETRACK: mov ax,0ABABh int 13h lea dx,Mess2 call WRITE ret NORMAL: mov ax,0BABAh int 13h lea dx,Mess1 call WRITE ret INSTALL: mov ax,3513h int 21h mov int13hofs,bx mov int13hseg,es lea dx,newint13h mov ax,2513h int 21h lea dx,Mess call WRITE lea dx,Mess2 Call WRITE lea dx,INIT int 27h WRITE: mov ah,9 int 21h ret Mess db 'Program repares bad track0 disk.',13,10,'Written by Hoang Tuan Dat.',13,10,'Finish install.',13,10,'$' Mess1 db 13,10,'Now you can not read bad track0 disk',13,10,'$' Mess2 db 13,10,'Now you only can read bad track0 disk',13,10,'$' Error db 'Input valid',13,10,'$' end Start 13
ADSENSE

CÓ THỂ BẠN MUỐN DOWNLOAD

 

Đồng bộ tài khoản
2=>2