intTypePromotion=1
ADSENSE

Tài Liệu Lập Trình Hợp Ngữ ĐHQG Hà Nội

Chia sẻ: Lê Văn Tình | Ngày: | Loại File: PDF | Số trang:13

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

Các ngắt của hệ thống hỗ trợ cho lập trình ASSSEMBLY Có 4 hàm hay dùng nhất: Hàm 1: Chờ 1 ký tự từ bàn phím: Mov ah, 1;AL chứa mã ASCII ký tự mã vào Int 21h Hàm 2: Đưa 1 ký tự dạng ASCII ra màn hình tại vị trí con trỏ đang đứng . Cách 1: Nhờ ngắt của BIOS Mov al, mã ASCII của ký tự Mov ah, …

Chủ đề:
Lưu

Nội dung Text: Tài Liệu Lập Trình Hợp Ngữ ĐHQG Hà Nội

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