Lập trình hướng đối tượng - Chương 2: Liên kết các ngôn ngữ bậc cao với ASM
Bạn đang xem 20 trang mẫu của tài liệu "Lập trình hướng đối tượng - Chương 2: Liên kết các ngôn ngữ bậc cao với ASM", để tải tài liệu gốc về máy bạn click vào nút DOWNLOAD ở trên
Tài liệu đính kèm:
- lap_trinh_huong_doi_tuong_chuong_2_lien_ket_cac_ngon_ngu_bac.pdf
Nội dung text: Lập trình hướng đối tượng - Chương 2: Liên kết các ngôn ngữ bậc cao với ASM
- Chương 2: LIÊN KẾT CÁC NGÔN NGỮ BẬC CAO VỚI ASM Mục đích: Tận dụng sức mạnh của các ngôn ngữ bậc cao và tốc độ của ASM. Cách liên kết: Bất kỳ một ngôn ngữ bậc cao nào liên kết với ASM đều phải tuân theo 2 cách sau: Cách 1 : Inline Assembly. cách 2: Viết tách tệp của ngôn ngữ bậc cao và tệp của ASM 2.1. Liên kết Pascal với ASM 2.1.1. Inline ASM Cơ chế. Chèn khối lệnh ASM vào chương trình được viết bằng Pascal. Cú pháp: Các câu lệnh Pascal ASM các câu lệnh ASM end; Các câu lệnh Pascal Ví dụ: So sánh 2 số và hiện số lớn hơn ra màn hình. SS.Pas Uses crt; Label L1 Var s1, s2 :Integer; Begin write (‘nhập so thu nhat :’ ); readln(s1); write (‘nhập so thu hai :’); readln(s2); ASM mov ax,s1 mov bx,s2 cmp ax, bx jg l1 xchg ax, bx 79
- l1: mov s1,ax end; write (‘so lon hơn la :’ , s1:5); readln; end. Cách dịch và liên kết: TP.exe: Đây là chương trình dịch của TP với các tuỳ chọn được xác lập bởi menu options. TPC.exe: Đây là chương trình dịch của TP với các tuỳ chọn được xác lập trên dòng lệnh dịch. Cú pháp: tpc -ml -IC:\tp\include -LC:\tp\lib ss Ưu điểm: Rất dễ liên kết và viết. Nhược điểm: Các lệnh ASM được dịch nhờ bởi chương trình dịch của TP có sai sót. 2.1.2. Viết tách biệt tệp ngôn ngữ Pascal và tệp ASM Các vấn đề nảy sinh cần giải quyết: có 4 vấn đề Vấn đề l: Đa tệp do đó phải khai báo PUBLIC và EXTRN với các nhãn dùng chung. Khái báo Pascal: Bất kể một khai báo nào của Pascal đều là Public do đó không cần phai khai báo tường minh public. Với các nhãn là biến nhớ thì Pascal luôn giành lấy để khai báo Public Với các nhãn là tên chương trình con thì ASM viết chương trình con nên Pascal sẽ sử dụng chương trình con -> Pascal phải xin phép sử dụng như sau: • Chương trình con là thủ tụC: Procedure tên_thủ_tục [đối]; extemal; 80
- • Chương trình con là hàm: Function tên_hàm [đối]: Kiểu; extemal; Khai báo của ASM. Giống như đa tệp thuần tuý ASM • Với nhãn là tên biến nhớ: Data extrn tên_biến_nhớ : kiểu Kiểu của ASM TP Byte Chai Word Integer Dword Real • Với nhãn là tên chương trình con : Code Public tên_chương_trình_con tên-chương trình-con Proc : Ret Tên_chương_trình_con endp Vấn đề 2: Vấn đề near/far của chương trình con Quy định chung của chương trình dịch TP - Nếu chương trình con cùng nằm trên 1 tệp với chương trình chính hoặc chương trình con nằm ở phần implementation của Unit thì chương trình con đó là near. - Nếu chương trình con nằm ở phần Interface của Unit thì chương trình đó là far. Ngoại lệ: - Directive {$F+}: Báo cho chương trình dịch TP biết chương trình con nào nằm sau Directive {$F+} là far. - Directive {$F-}: Báo cho chương trình dịch của TP biết những chương trình con nào nằm sau Directive {$F-}phải tuân thủ quy định chung của chương trình dịch TP Vấn đề 3: Cách chương trình dịch TP tìm tệp để liên kết: Directive { $L } Cú pháp : {$l tên_tệp [.obj]} 81
- Vấn đề 4: Tên hàm ASM mang giá trị quay về Muốn tên hàm ASM mang giá trị quay về dạng 2 byte phải đặt giá trị đó vào thanh ghi AX trước khi có lệnh Ret. Muốn tên hàm mang giá trị 4 bytes thì phải đặt giá trị đó vào thanh ghi DX:AX trước khi có lệnh Ret. Nhận xét: Người viết Pascal quan tâm đến vấn đề: 1, 2, 3. Người viết ASM quan tâm đến vấn đề: 1,4. Phương pháp l: Chương trình con không đối. Chuyển giao tham số thông qua khai báo biến toàn cục. Ví dụ: Tính an. vd1.pas - Nhập giá trị a, n - Gọi chương trình con tính an do asm viết - Hiện kết quả. vd2.asm: chương trình tính an . vd1.pas Uses crt; Var a,n: Integer {$F+} function a_mu_n: integer; external; ($L vd2 [. obi]} {$F-} Begin Clrscrl; writeln(' Chuong trinh tinh a mu n !); write (‘nhập so a:’ ); readln(a); write (‘Nhap so n:’ ); readln(n); write (a, ‘luy thua’ , n , ‘la :’ , a_mu_n : 5 ); readln; End. 82
- vd2. asm .model large .data EXTRN a:word, n:word .code Public a_mu_n a_mu_n proc mov bx,a mov cx,n mov ax,1 and cx,cx jz kt lap: imul bx loop lập kt: a_mu_n endp end Cách dịch và liên kết b1: Dịch tệp .asm sang .obj C:\asm> tasm vd2 -> vd2.obj b2: Dịch .pas và liên kết C:\asm>tpc –m1 với -> vd1.exe Phương pháp 2: Chương trình con có đối. Chuyển giao tham số thông qua Stack Nguyên lý: Chúng ta đều biết chương trình con không ASM không có đối. Tuy nhiên khi liên kết Pascal với ASM thì Pascal giả thiết chương trình con ASM có đối. Số lượng đối và kiểu đối do Pascal giả thiết.Với giả thiết đó khi gọi chương trình con, Pascal phải đưa tham số thực vào Stack (theo chiều từ trái qua phải). Cơ chế: function test(bl:integer, b2:integer, b3: integer): integer; extemal; : 83
- test (a,b,c) Bướcl : Tham số thực đưa vào Stack theo chiều từ phải qua trái Bước 2: Địa chỉ lệnh tiếp theo đưa vào Stack (4 byte) Bước 3: Hệ điều hành đưa địa chỉ đầu của chương trình con ASM vào CS:IP -> chuyển sang chương trình con . .model large .code Public test Test Proc Push bp mov bp,sp Thân chương trình con ASM pop bp ret n ; n là số lượng byte mà tham số thực chiếm trong Stack. Test endp Ví dụ: Tính an đối với hàm có đối lt1.pas Uses crt; Var a, n : integer; {$F+} function lt(b1: integer, n2: integer): Integer; external; {$L lt2} {$F-} Begin clrscr; write('Nhap so a:’ ); readln(a); write ('Nhap so n:’ ); readln(n); write ( 'ket qu a la : ' lt (a, n) : 5); readln; End. lt2. asm 84
- .model large .code Public lt lt Proc push bp mov bp,sp mov bx, [bp +8] mov cx,[bp + 6] mov ax, 1 and cx, cx jz kt lap: imul bx loop lap kt: pop bp ret 4 lt endp end Dịch như sau: Tasm lt2 -> lt.obj Tcp -ml ltl -> ltl.exe Bài tập: Trung bình cộng 2 số Cách1: Hàm không đối TBC.asm Uses crt; Var s1, s2, flag : Integer; {$F+} function tb(): Integer; external; {$L tbc2} 85
- {$F- } Begin clrscr; flag := 0; Write (' Nhap so thu nhat:' ); readln(s1); Write(' Nhap so thu hai:’ ); readln(s2); Write(' Trung binh cong 2 so la:’, 0.5*flag + tb:5); readln; End. tbc2.asm .model large .data extrn s1: word , s2: word, flag: word .code public tb tb proc mov ax,s1 mov bx,s2 add ax, bx sar ax, 1 jnc l1 mov flag, 1 Ll. ret tb end End Cách 2: Hàm có 3 đối TBC.asm Uses crt; Var s1, s2, flag : Integer; {$F+} function tb (f :integer, n1: integer, n2:integer): Integer; external; 86
- {$L tbc2} {$F-} Begin flag : = 0; write (‘Nhap so thu nhat:’ ); readln(s1); write(' Nhap so thu hai:’ ), readln(s2); Write ( ' Trung binh cong 2 so la :’, 0. 5 *flag + tb (flag, s1,s2):5); Readln; End. tbc2.asm .model large .code public tb tb proc push bp mov bp,sp mov ax, {bp+8} mov bx, {bp+6} add ax, bx sar ax, 1 jnc l1 mov cx, 1 mov {bp + 10},cx L1: pop bp ret 6 bo end End Bài tập 1 : Tính tổng của dãy số nguyên Trong đó: Pascal 87
- • Nhận số lượng các thành phần • Nhận các số của mảng • Hiện các số của mảng ra màn hình • Gọi ctc tính tổng do ASM tính • Hiện tổng ASM: Viết chương trình con tính tong Giải Viết một chương trình pascal T1.pas uses crt;, label L1; type //cho phép khai báo xác lập kiểu khai báo biến mới mới m=array[1 100] of integer; Var sltp i: Integer; a: m; tl:char; {$F+} //báo hàm xếp khai báo la far function sum(mang:m, n:integer): Integer //do ASM thực hiện {$L T2} //hàm đó nằm ở file T2.obj {$F-} //các hàm dùng sau theo chuẩn P Begin L1: Write (‘nhap so thanh phan sltp =’: ); readln(sltp); Write ('nhap vao day cua cac thanh phần ); for I = 1 to sltp do begin write ( 'a[‘, I,’ ] =’ ); readln (a[i]) ; end write (' Day so vua nhap vao la:' ); for I := 1 to sltp do write(a[i], ‘ ‘ ); writeln; 88
- write('co tiep tục không C/K ? ); tl : = readkey; if(tl= ‘c’ ) then gotoL1; readln; END. T2.ASM .Model large .code public sum sumproc //a: d/c cua a0 dc dua vao stack mat 4 byte do offset+seg, cat vao theo //chieu tu trai qua phai, push bp mov bp,sp mov cx, [bp + 6] les bx, [bp + 8] //lay 2 byte dua vao BX va 2 byte tiep theo vao ES Xor ax, ax lap: add ax, es: [bx] add bx,2 loop lap pop bp ret 6 //tra lai 6 byte 4 byte cho a, 2 byte cho sltp end Dịch và liên kết: bl : Dịch ASM sang .OBJ C:\tuan t2 → T2.obj T2 . obj nằm Ở {$L T2} . b2 : Dịch và liên kết P C:\tuan>tpc -ml tl ->tl.exe 89
- Sử dụng directive ARG Lý do: cho phép người viết chương trình con ASM (trong trường hơp có đối) viết đúng chương trình con ma không biết cấu trúc của Stack. Cúpháp: tên chương trình con PROC ARG tên đối : kiểu = Retbytes (tên đối dược xắp xếp từ phải sang trái) Bài tập 2: Tính tổng cấp số cộng khi biết n, d, u1 Pascal: cscl.pas Uses crt; Var n, d, u1 :Integer; {SF+} function csc(n1: integer, n2: integer, n3: integer):integer; external; {$L csc2} //tìm ở tệp csc2. obj, không có đường dẫn thì ở thư mục hiện hành {$F-} //báo theo chuan P Begin write('nhap vao n = '); readln(n); write('nhap vao d = ),' readln(d); write('nhap vao u1 = ); readln(d); write('tong cap so cong = , csc(n,d,u):5); End. Viet ASM: csc2. asm (khong dung directive) cach 1 : .model large .code public csc csc proc push bp mov bp,cs mov ax, [bp + 6] mov bx,[bp + 8] mov cx,[bp+10] mov dx,ax lap: add dx, bx 90
- add ax, dx loop lap Pop bp ret 6 csc endp end cách 2: .model large .code Public csc csc proc ARG n3:word, n2:word, n1::word= Retbytes push bp movbp, cs movax, n3 movbx, n2 movcx,n1 movdx,ax dec cx lap: add dx, bx add ax, dx loop lap pop bp ret Retbytes csc endp end 2.2 Liên kết c/c++ với ASM 2.2.1. InlineAssembly Cơ chế: Chèn khối lệnh ASM vào chương trình được viết bằng C/C++ 91
- Cú pháp: Các câu lệnh C ASM lệnh ASM ASM lệnh ASM ASM lệnh ASM Các câu lệnh C hoặc cách kháC: Các câu lệnh C ASM { // dấu ngoặc phải cùng một dòng khối lệnh ASM } Các câu lệnh C Ví dụ: Tính Tổng 2 số nguyên Tong.C #include #include int s1,s2 Void Main(void) thiếu hàm f() không có giá trị trả về thì ct sẽ mặc định là int { clrscr(); printf(“\n nhap vao so thu nhat :”); scanf(“%d”,&s1); printf(“\n nhap vao so thu hai :” ); scanf(“%d”,&s2); //nếu không có format thì không báo lỗi và cũng không hiện ra màn hình ASM { mov ax,s1 mov bx,s2 mov ax, bx mov s1,ax } Printf ("\n tong cua hai so là %d” , s1); 92
- Getch(); } Dịch và liên kết : Giả sử chúng ta cất giữ file trong thư mục ASM C:\ASM>tcc -ms -IC:\tc\include -LC:\tc\lib tong.c //phần trên có thể dịch được nếu chúng ta dã khai báo trong Autobat thì bất cứ ở đâu cùng gọi được tcc. còn không chúng ta phải viết như sau: C:\ASM>C:\tc\bin\tcc -ms –IC:\include -LC:\tc\lib tong.c ưđ: Dễ liên kết Nhược điểm : • Khối lệnh ASM được dịch nhờ bởi TC → không chuẩn • Không cho phép có nhãn nhảy trong khối lệnh ASM được chèn vào C→ khối lệnh chèn vào không linh hoạt và không mạnh. 2.2.2 Viết tách biệt C/C++ và tệp ASM Một số vấn đề nảy sinh cần giải quyết khi viết tách biệt, có 3 vần đề Vấn đề: (đa tệp) Chúng ta phải liên kết các file với nhau do đó chúng ta phải khai báo Public và Extemal với các nhãn dùng chung. Khai báo trong C/C++ PUBLIC: Bất kỳ một khai báo nào của C/C++ đều là Public, nên không cần khai báo tường minh. Với nhãn là biến nhớ cho phép ASM khai báo Public và c/c++ xin phép được dùng cú pháp: Extem kiểu tên biến ASM char db int dw float dd EXTERNAL: Khai báo để được phép dùng chương trình con của ASM Extern kiểu tên hàm ([đối]); Khai báo của ASM. Giống như đa tệp thuần tuý Vấn đề 2 93
- Người viết ASM phải thêm dấu '_' vào trước các nhãn dùng chung với C/C++ và thêm ở mọi nơi mà nhãn đó xuất hiện. Vì dùng C khi dịch các nhãn ở ngoài nó đều thêm '_' vào trước nhãn. Vấn đề 3 Tên hàm ASM mang giá trị quay về AX, DX:AX tương ứng 2,4 byte Phương pháp 1 (Hàm không đối) Chúng ta phải chuyển giao tham số thông qua biến toàn cục Ví dụ Tính giai thừa của n! C: Nhập n; Gọi chương trình con tính n! do ASM tính; Hiện kết quả ASM: Viết chương trình con tính n! gtn1.c #include #include int n extern int gt(); Void main (void) Printf ("\n Nhap vao n =” ); scanf("%n ", &n); Printf ("\n %d Giai thua la: %d”,n , gt():5); Getch(); } //biến toàn cục sẽ cất trong Data, biến cục bộ cất trong Stack, static biến cục bộ cất trong Data gtn2.asm .model small/large // ms/-ml .data extrn _n: Word a dw ? b dw ? .code public _gt _gt proc mov a,1 94
- mov b,2 mov cx, _n cmp cx jb exit dec cx lap: mov ax, a mul b mov a,ax inc b loop lap exit:mov ax, a ret _gt endp end Dịch liên kết file tcc ms/ml IC:\tc\include -LC:\tc\lib gtn1 gtn2.asm -> gtn1.exe. Phương pháp 2 (Hàm có đối) Hàm có đối thì chương trình phải chuyển giao tham số thông qua Stack. Lý do: Chúng ta biết chương trình con thuần tuý ASM không có đối. tuy nhiên khi C/C++ liên kết với ASM thì nó giả thiết chương trình con ASM có đối. Số lượng đối, kiểu đối do C/C++ giải thiết và với những giả thiết đó thì chương trình con ASM. C/C++ đưa tham số thực vào Stack và người viết chương trình con ASM phải vào Stack lấy giá trị đó. Giải thích extern int test (int n1, int n2, int n3); Vòm main (void) { int a,b,c - 95
- test (a,b,c); - } có 5 bướC: .model small [.data] public _test _test proc push bp mov bp,sp các lệnh ASM pop bp ret _test endp end Bài tập 3: tính n! hàm có 1 đối gtn1.c #include #include int n extern int gt(int i); Void main(void) { clrscr(); printf(“\n Nhap vao n =” ); scanf (“%n ", &n); printf("\n %d Giai thua la : %d",n , gt(n):5); getch(); } gtn2.asm .model small/large //-ms/-ml 96
- .data a dw ? b dw? .code public _gt _gt proc push bp mov bp,sp mov a, 1 mov b, 2 mov cx, _n cmp cx jb exit dec cx lap: mov ax,a mul b mov a,ax inc b loop lap exit: mov ax, a pop bp ret _gt endp end Bài tập 4 Tính trung bình cộng 2 số nguyên Cách 1 : Hàm không có đối - Sl,S2, flag là các biến toàn cục. - Tên Hàm ASM -> trung bình cộng làm tròn dưới. 97
- TBC1.C #include #include int s1, s2, flag = 0; extern int tbc(); Void main(void) { Printf ("\n nhap vao so thu 1 : “); scanf(“%d” ,&s1); Printf ("\n nhap vao so thu 2 : “); scanf(“%d” ,&s2); Printf ( “\n Trung binh cong cua 2 so nguyen la: %d”, tbc()+0.5*flag); getch(); } // chú ý ngôn ngữ C phân biệt chữ hoa và chữ thường. TBC2.ASM .model small .data extrn _s: Word, _s2: Word, flag: Word .code public _tbc mov ax, _s1 mov bx, _s2 add ax, bx sar ax, 1 Jnc exit mov cx, 1 mov _flag, cx exit: ret _tbc endp end Cách 2: 98
- - s1,s2 là biến cục bộ -> trong Stack - flag là biến toàn cục - hàm tính trung bình cộng là làm tròn dưới. TBC1.C #include #include int flag = 0; extern int tbc(int n1, int n2); Void main(void) { int s1,s2; Printf (“\n nhap vao so thu 1 :” ), scanf("%d",&s1); Printf (“\n nhap vao so thu 2 :” ); scanf("%d",&s2); Printf ( “\n Trung binh cong cua 2 so nguyen la: %d”, tbc()+o.5*flag); Getch(); } TBC2.ASM .model small .da ta extrn flag: Word .code public _tbc _tbc proc push bp mov bp, sp mov ax,[bp+4] mov bx, [pb + 6] add ax, bx sar ax, 1 jnc exit 99
- mov cx, 1 mov _flag, cx exit: pop bp ret _tbc endp end Bài tập 5: Sắp xếp dãy số theo chiều tăng dần. • Nhận số lượng thành phần • Nhận các số đưa vào một mảng • Hiện các số của mảng ra màn hình • Gọi chương trình con sắp xếp do ASM viết • Hiện các số đã xắp xếp ASM: Viết chương trình con sắp xếp dãy số. Giải #include #include extern sx(int n, int far* mang); Void main(void) { int sltp a[100]; printf (“\n Nhap vao sltp =”); scanf("%d", &sltp); printf (“\n Nhap vao cac so cua mang” ); for (I=0, I<sltp, I++) { printf ("\n a[%d]= ", i); scanf("%d” ,&a[i]); } printf (“\day so vua nhap vao la” ); for(i=o, I<sltp, I++) printf("%d”, a[i]); 100
- sx(sltp a); printf("\ day so đa sap xep la”); for(i=0, I<sltp, I++) printf("%d ", a[i]); getch(); } sx2. asm .model small .code public sx _sx proc .push bp mov bp, sp mov si, [bp+4] dec si l1: mov cx, [bp+4] les bx, [bp + 6] dec cx l2: mov ax,es:[bx] mov dx,es:[bx+2] cmp ax,dx jl l3 mov es:[bx+2],ax mov es:[bx],dx l3: add bx, 2 loop l2 dessi jne l1 101
- pop bp _sx endp end chú ý: Directive ARG Cú pháp ARG tên đối Kiểu // C ngược với P là từ trải qua phải Liên kết C++ với ASM Giống C liên kết với chương trình con trừ một vấn đề tên chương trình con ASM. C: .code public _tên chương trình con _tên chương trình con proc các câu lệnh của ASM ret _tên chương trình con endp End. C++: .code public @tên chương trình con $ @tên chương trình con $ các câu lệnh ASM ret @tên chương trình con $ endp Các bướC: b1: Viết modul C++. cpp b2: Dịch từ đuôi cpp ra .asm tcc -S tên tệp.cpp -> tên tệp.asm b3: Hiện lên màn hình tên tệp .asm (ở dòng cuối cùng có @tên chương trình con $ ) Bài tập 6: So sánh 2 số và hiện số bé 102
- SS1.CPP #include #include extern int ss(int n1, int n2); Void main(void) { int s1,s2 clrscr(); cout >s1; cout >s2; cout ss1.asm Hiện ss1.asm lên màn hình : -> @ss$ .model small .code public @ss$ @ss$ proc push bp mov bp, sp mov ax, [bp + 4] mov bx, [bp + 6] cmp ax, bx jl l1 xchg ax, bx l1; pop bp @ss$ endp End. 103
- Chương 3: LẬP TRÌNH HỆ THỐNG Lập trình hệ thống thực chất là nghiên cứu các ngắt của hệ thống. Chương này gồm 6 phần 3.1. Các bước khi máy tính khởi động Từ khi bật máy đến khi hiện thị C:\> thì máy tính làm gì ? Với CPU của intel (hoặc là hỗ trợ). khi bật máy tính thì ngay lập tức thanh ghi CS=F000h và thanh ghi IP = FFFOh. Đây là địa chỉ của vùng nhớ ROM và máy tính nhảy đến vùng ROM BIOS này, với byte này chứa mã máy của lệnh nạp, 2 byte tiếp theo là địa chỉ nhảy đến chương trình kiểm tra đầu tiên của máy tính. ROM BIOS nếu là 2k thì nó được viết bằng ASM. Nếu là 128K thì bên trong viết bằng ASM bên ngoài viết bằng C. ROM BIOS chứa chương trình khởi động máy tính và chứa chương trình con ngắt của BIOS. Kiểm tra CPU Kiểm tra các thanh ghi bên trong CPU bằng cách lần lượt cho các giá trị FFFFH, 0000H, 5555H và kiểm tra có đúng không? • Nếu không đúng màn hình hiển thị Fatal Error • Nếu đúng kiểm tra tiếp Kiểm tra cấu hình tối thiểu của máy tính: Bàn phím Kiểm tra một số linh kiện trên mainboard: 8259, 8250, 8237, 8253 Kiểm tra checksum của ROMBIOS: Khi sản xuất máy tính thì ROM BIOS được nạp 2 lần: Lần l: Nạp mã máy của 2 loại chương trình. Sau đó cộng tất cả các byte mã máy trên Rom để tạo thành một byte checksum ROM BIOS. Lần 2: Nạp byte checksum vào ROMBIOS. Trong chương trình kiểm tra máy tính có một chương trình cộng lại tất cả các byte của mã máy trong Bios, được 1 byte checksum hiện thời. So sánh 2 byte checksum. Nếu bằng nhau là tốt, nếu không bằng nhau trên màn hình hiện dòng chữ checksum error (máy tính vẫn chạy bình thường, nếu chạy đến vùng lỗi thi mới bộ ảnh hưởng) Kiểm tra RAM Cho lần lượt toàn bộ các byte của RAM là các giá trị FFH, 00H, 55H và kiểm tra đúng hay không? 104
- (Từ lệnh Ctrl + Alt + Del) Đưa địa chỉ đầu của chương trình con phục vụ ngắt của Bios vào bảng vector ngắt. Cập nhật thông tin liên quan đến máy tính đang dùng vào vùng dữ liệu của ROM BIOS. Kiểm tra liệu có Rom mở rộng không Lấy boot sector vào RAM Trao quyền cho chương trình nằm ở boot sector. Lấy haiflle ẩn vào vùng RAM Lấy command. com vào RAM (command.com dùng để dịch các câu lệnh của đối interpreter dùng dịch ra mã máy) Dịch từng câu -> Interpreter Dịch cả mảng - > compo Lấy [Autoexec.bat] C :\ > 3.2 Phân loại ngắt và khái niệm Phân loại ngắt Một số khái niệm Ngắt là gì Ngắt là tạm dừng chương trình đang chạy để chuyển sang chạy một chương trình con phục vụ ngắt. sau khi chạy xong chương trình con phục vụ ngắt thì trở lại tiếp tục chạy chương trình đang dở. Ngắt cứng Ngắt cứng là ngắt sinh ra do tác động của các linh kiện điện tử. 105
- Ngắt mềm Là ngắt kích hoạt bằng lệnh int n Bảng vector ngắt: Bảng vector ngắt: Là vùng nhớ RAM chứa địa chỉ đầu của tất cả các chương trình con phục vụ ngắt của máy tính. Mỗi địa chỉ gồm 4 byte. Độ lớn: Máy tính có 256 ngắt x 4 = 1024 byte = 1kbyte Vị trí. Một kbye đầu tiên Mối quan hệ số ngắt và địa chỉ ô nhớ đầu của bảng vector ngắt: Địa chỉ ô nhớ = n x4 Ví dụ int 20h -> vị tri của nó là ô nhớ 20 +21 là offset, ô nhớ 22 + 23 là seg 3.3 Cơ chế khi một ngắt được kích hoạt Chương trình con bình Chương trình con phục vụ ngắt Kích hoạt: CALL Tác động của linh kiện hoặc lệnh INTR Cơ chế đều có 5 bước b1: Tham số thực đưa vào - Đưa flag vào Stack Stack - Đưa tham số thực nếu có vào Stack b2: Địa chỉ của lệnh tiếp Địa chỉ của lệnh tiếp theo vào Stack theo vào Stack b3: Hệ đưa địa chỉ đầu của HĐH không quản lý địa chỉ đầu tiên của chương chương trình con vào CS:IP và trình con phục vụ ngắt. Xong địa chỉ đầu tiên của rẽ nhánh vào chương trình chương trình con phục vụ ngắt nằm trong bảng con. vector ngắt. Máy tính vào vị trí tương ứng của bảng vector ngắt. Lấy địa chỉ đầu chương trình con phục vụ ngắt CS:IP b4: Thực hiện chương trình Thực hiện thận chương trình con phục vụ ngắt con cho đến khi gặp lệnh RET, cho đến khi gặp lệnh IRET thì vào Stack lấy địa chỉ vào Stack lấy địa chỉ lệnh tiếp lệnh tiếp theo -> CS:IP -> Quay về chương trình đã theo đưa vào CS:IP -> Quay kích hoạt về chương trinh đãgọi b5: Tiếp tục chương trình dang Vào stack lấy giá trị cờ -> Flat -> tiếp tục chương dở trình 106
- 3.4. Các bước xác lập ngắt 3.4.1. Viết chương trình con phục vụ ngắt theo yêu cầu của thuật toán Cú pháp: tên chương trình con phục vụ ngắt proc o Bảo vệ các thanh ghi mà chương trình con phục vụ ngắt phá vỡ o Các lệnh ASM theo yêu cầu của thuật toán o Hồi phục các thanh ghi mà thân chương trình con phục vụ ngắt phá vỡ IRET tên chương trình con phục vụ ngắt Endp 3.4.2. Lấy địa chỉ đầu của chương trình con phục vụ ngắt và đặt vào vị trí tương ứng của vector ngắt. Lấy địa chỉ của chương trình con phục vụ ngắt Sử dụng 2 directive đó là SEG và OFFSET. Directive SEG: Chức năng : Lấy địa chỉ đầu segment lệnh đầu của chương trình con phục vụ ngắt. Cú pháp: SEG tên chương trình con phục vụ ngắt Ví dụ: Mov ax, SEG tênctcpvn Directive OFFSET Chức năng: Lấy địa chỉ đầu offset lệnh đầu của chương trình con phục vụ ngắt. Cú pháp: OFFSET tên chương trình con phục vụ ngắt Ví dụ: Mov bx,OFFSET tênctcpvn đưa địa chỉ đầu của ctcpvn vào vị trí tương ứng của bảng vecter ngắt Cách 1 : Trực tiếp Ví dụ ta can thiệp vào ngắt thứ 5h Ctn5 Proc : Ret Ctn5 endp xor ax, ax 107
- mov ds, ax mov ax, offset ctn5 mov ds:[20],ax mov ax,seo ctn5 mov ds:[22],ax Cách 2: Gián tiếp nhờ chức năng 25h của ngắt int 21h. // tất cả các hàm của dos đều trong 21h. Yêu cầu: ds:dx <- seg:offset địa chỉ đầu của ctcpvn al là số ngắt an <- 25h int 21h Ví dụ: Ctn5 Proc : Ret Ctn5 endp cli mov dx, offset ctn5 mov ax, seg ctn5 mov ds, ax mov al, 5h mov ah, 25h int 21h sti Bài tập: Hãy xác lập ngắt bỏ tác dụng của phím printscreen. Muốn in nội cung của màn hình ở chế độ dos ra màn hình ta có 2 cách - Ấn phím printscreen. - Gọi ngắt int 5h Có 2 cách làm: 108
- C1: Dùng chương trình debug để bẻ lái vector ngắt. b1: Khởi động debug C:/asm>debug b2: Dùng lệnh D để hiện vecter ngắt. D 0:0 //xem 128 byte đầu của vectơ ngắt 0:0000 là 16 byte đầu của bảng vectơ ngắt địa chỉ của ngắt int 0 - int 3 0:0010 là 16 byte đầu của bảng vectơ ngắt địa chỉ của ngắt int 4 - int 7 Dữ liệu trong ngắt thứ 5 là 54 ff 00 f0 -> địa chỉ là f000:ff54 b3: Dùng lệnh U để dịch ct từ dạng .exe sang .asm U f000:ff54 địa chỉ mã máy lệnh dạng gợi nhớ f000:ff54 : : : f000:ffd6 Iret b4: Dùng lệnh E của debug để sửa địa chỉ đầu có trong bảng vectơ ngắt E 0:0014 54 d6 //có hai cách để khôi phục lại là dùng lệnh E hoặc khởi động lại máy C2: Viết chương trình để bỏ tác dụng của phím Printscreen .model .stack 100h .code Start: cli mov dx,offset ctn mov ax,seg ctn mov ds,ax mov al,5 mov ah,25h int 21h stimov ah,4ch 109
- int 21h ctn proc iret ctn endp end start 3.5. Vùng dữ liệu ROM BIOS Vùng dữ liệu trong ROM BIOS là gì Là vùng RAM chứa các thông tin liên quan đến máy tính đang dùng. Các thông tin ấy được được cập nhật vào vùng nhớ này khi máy tính khởi động. Độ lớn: 256 bytes Vị trí: ngay sau bảng vectơ ngắt. Một số thông tin của vùng dữ liệu ROM BIOS • 0:400h - 0:407h : Địa chỉ cổng Com (đại chỉ của ngoại vi chỉ có 2 bytes). 0:400h + 401h Địa chỉ của cổng Com 1 0:402h + 403h Địa chỉ của cổng Com 2 0:404h + 405h Địa chỉ của cổng Com 3 0:406h + 407h Địa chỉ của cổng Com 4 • 0:408h - 0:40Fh: Địa chỉ của 4 cổng LPT 0:408h + 0:409h Địa chỉ cổng LPT 1 0:40Ah + 0: 40Bh Địa chỉ cổng LPT 2 0:40ch + 0: 40Dh Địa chỉ cổng LPT 3 0:40Eh + 0: 40Fh Địa chỉ cổng LPT 4 • 0:410 + 0:411h: Danh sách thiết bị 0:0410h 110
- Cách lấy thông tin từ vùng dữ liệu ROM BIOS. Dùng Debug D0:400h 0:400h Sẽ hiện 16 byte là địa chỉ của 4 cổng Com, 4 cổng LPT, địa chỉ chỉ có 2 byte 0:410h Hai byte đầu tiên là 23h C5h Viết chương trình Bài tập 1: Hãy viết chương trình cho biết máy tính của bạn có ổ mềm hay không, nếu có thi là bao nhiêu bao nhiêu ổ mềm. - Lấy dữ liệu trong địa chỉ 0:410h - Lấy dữ liêu của thanh ghi đó - Có hai cách: Dùng ngắt int 11h và tự trỏ lấy OMEM.ASM include lib1.asm .model small .stack 100h .data m1 db ' không có ổ mềm nào ! $ ' m2 db ' số lượng ổ mềm là: $ ' .code 111
- start: mov ax, @data mov ds,ax clrscr int 11h shr al, 1 jc l1 hienstring m1 jmp exit l1: hienstring m2 mov c1,5 shr al,cl inc al add al,30h mov ah,0eh int 10hexit: mov ah, 1 int 21h mov ah,4ch int 21h end start Bài tập 2: Hãy viết chương trình cho biết máy tính của bạn có những cổng com nào hay không? nếu có thi bao nhiêu, cho biết địa chỉ cổng com dạng hexa. Lấy đia chỉ 0:411h cho vào thanh ghi 8 bit Tách 3 bit cho biết số lượng của cổng com and với 0Eh Địa chỉ cổng Com, số lượng cổng com đưa vào CX địa chỉ cổng com trong 2 ô nhớ 0:400h + 401h COM.ASM include lib1.asm _stack segment 112
- db 100h _stack ends datasegment tb1 db 10,13, ' Không co c ổng com nào ! $ ' th2 db 10,13, ' Số lượng cổng com là: $ ' th3 db 10,13,' Địa chỉ cổng com là: $' tb4 db ' $ ' dataends code segment assume cs:code, ds:data, ss:stack start: mov ax,@data mov ds,ax clrscr int 11h mov al,ah and al,0eh jnz 11 hienstring tb1 jmp exit l1: hienstring tb2 shr al, 1 mov cl,al xor ch,ch add al,30h mov ah,0eh int 10h hienstring tb3 xor ax,ax 113
- mov es,ax mov bx,400h lap: mov ax,es:[bx] call hien_hexa hienstring th4 add bx,2 loop lap exit: mov ah, 1 int 21h mov ah,4ch int 21h ; hien_hexa proc push ax, bx, cx, dx mov bx, 16 xor cx,cx hxl : xor dx,dx div 16 cmp dx, 10h jb hx2 add dx,7 hx2: add dx,30h push dx inc cx add ax,ax jnz hx1 114
- pop ax mov ah,0eh int 10h loop hx3 pop dx,cx,bx,ax ret hien_hexa endp code ends end start Bài tập 3: Cho biết đia chỉ cơ sở của Video RAM máy tính đang dùng kn: là vùng nhớ RAM chứa nội dung hiện ra màn hình Mono: Địa chỉ cơ sở là: B000h Color: : B800h VR.asm include lib1.asm .model tiny .code org 100h Start: jmp khaibao tb db 'địa chỉ cơ sở của Video RAM là: $' khaibao: clrscr int 11h ; Đưa địa chỉ 0: [410] -> Al, 0: [411] -> Ah hienstring tb add al,30h cmp al,30 je mono mov ax,0B800h jmp Hien mono: 115
- mov ax,0B000h Hien: call Hien_hexa mov ah, 1 int 21h int 20h Hien_hexaproc : Ret Hien_Hexa endp Endstart 3.6. Các ngắt hay dùng trong hệ thống - Ngắt liên quan đến bàn phím - Ngắt liên quan đến màn hình - Ngắt liên quan đến đĩa - Ngắt liên quan đến thư mục - Ngắt liên quan đến tệp - Ngắt liên quan đến máy in - Ngắt liên quan đến chuột - Ngắt liên quan đến thời gian - Ngắt liên quan đến truyền tin nối tiếp Khái niệm: Mỗi một ngắt của chương trình hệ thống thường có nhiều chức năng để chọn một chức năng nào đó của một ngắt thì: Mov ah, chức năng int n Ví dụ //ngắt Int 21h đây là các hàm của Dos. 1. mov ah, 1 int 21h 2. mov dl,ASCII của ký tự mov ah, 02h int 21h 116
- 3.1ea dx, tên_xâu mov ah, 09h int 21h 4. mov ah, 4ch Int 21h 3.6.1. Ngắt bàn phím Ngắt của dos Int 16h (int 9h) Ngắt của Dos thì mã máy nằm trong RAM Ngắt của Bios mã máy nằm trong Rom Chức Ctrl E cho Ý nghĩa Tần số năng break 0h Không Không Nhận ký tự từ bàn phím: Nhận đượC: - Nếu trong vùng đệm bàn - AL # 0 -> Al là mã ASCII - > AH phím có ký tự -> AL chứa mã quét. - Nếu vùng RAM rỗng thì - Nếu Al = 0 -> AH chứa mã ASCII máy tính chờ ấn phím. mở rộng (F1 – F10) Chú ý: ax = 3c00h là F1 1h Không Không Kiểm tra vùng đệm bàn phím ZF =0 Không có ký tự ở vùng đệm. Chú ý. Nếu vùng đệm bàn ZF = 1 Có ký tự ở vùng đệm và sẽ phím rỗng thì máy tính không đưa vào AL chờ ấn phím mà thực hiện 2h Không Không Choiế biết trạng thái các phím AH chứa trạng thái các phím đặc đặc biệt của bàn phím: biệt: Shitf L, Shitf R, Alt, Ctrl, Insert,Caps Lock, Num Luck, SC N CL is A C SL SR Scroll Lock 117
- Ngắt của Dos (Int 21h) Chức ctrl break Echo Ý nghĩa Tần số năng 1h Có Có Nhận một ký tự từ bàn Nhận đượC: AL -> Mã ASCII phím: AH -> Mã scan (Mã scan là - Nếu có ký tự trong vùng mã thứ tự của bàn phím) đệm bàn phím -> AL - Nếu Vùng đệm bàn phím rỗng, chờ ấn phím 07h Có Không Như trên Như trên 08h Không Không Như trên Như trên 06h Không Không Kiểm tra vùng đệm của - ZF = 1 Không có ký tự bàn phím - ZF = 0 có -> AL - Nếu có ký tự -> AL - Nếu rỗng không trở nhấn phím 0Ah Có Có Cho phép nhận một xâu ký Vào : DS:AX < - seg:offset tự đưa vào vùng đệm của đầu vùng đệm. 0Bh Cho biết trạng thái của NĐ: AL = OFFh CÓ ký tự vùng đệm bàn phím AL = 0 Rỗng 0Ch Xoá vùng đệm bàn phím. Vào: sau đó thực hiện chức AL <- Chức năng năng có trong AL Ví Dụ: Viết Chương trình con vào số n (cho phép đánh sai và sửa) .data buff db 10 db ? db dup(?) .code Vaoso_n proc push bx cx dx si di mov bx, 10 118
- xordi,di lea dx,buff mov ah,0ah int 21h xorax,ax mov si,dx inc si mov cl,[si] xorch,ch inc si mov dl,si cmp dl,'-' jne vsn1 inc di dec cx inc si vsn1: imul bx sub dl,[si] sub dl,30 or dh,dh add ax,dx inc si loop vsn1 add di,di jz vsn2 neg ax vsn2: pop di si dx cx bx ret 119
- vaoso_n endp 3.6.2. Các ngắt với màn hình a. Các ngắt liên quan đến chế độ văn bản của màn hình khái niệm 1. Màn hình phản ánh nội dung trong Video RAM 2. Độ lớn của ký tự Mono: Mỗi một chữ là ma trận 14x9 chư trong đó có độ rộng, dai là 7x7 Color: Mỗi một chữ là ma trận 8x8 chư trong đó có độ rộng, dai là 7x5. 3. Byte thuộc tính với màn hình Ngắt Bios liên quan đến màn hình ở chế độ Text (Int 21h) DV Ý nghĩa Thông số 0h Set mode cho màn hình Vào: AL số cột, DH -> số dòng 09h Hiện ký tự và màu sắc ra màn hình Vào: AL <- mã ascii . Chú ý: Sau khi hiện xong con trỏ không CX <- số làn thực hiên. nhảy sang phải BL <- thuộc tính, BH <- trang màn hình 0Ah Giống chức năng 9 nhưng không có màu 0Eh Hiện một ký tự ra màn hình Vào: AL <- MÃ ASCII 0Fh Get mode NĐ: Số thể hiện mo de màn hình hiện thời 120
- Bài tập 1: Xác lập Macro xoá màn hình Clrscr Proc push ax cx dx xordx,dx mov ah,2 ;gotoxy = 00 int 10h mov al,20h ;mã ascii của ‘ ‘ mov cx,2000 mov ah,0ah int 10h pop dx cx ax EndM Bài tập 2: Hiện ở dòng 10, cột 20, dòng chữ 'Hello Darling ! ' chữ đỏ, nền màu xanh Include libl.asm _stack segment db 100h dup(?) _stack ends ' ' Data segment m db 'Hello Darling !',0 Data ends Code segment Assume cs: code, ds: data, ss:_stack Start: mov ax,@data mov ds,ax clrscr mov dl,20 mov dh, 10 mov ah,2 int l0h 121
- lea si,m L1: mov al,[si] and al,al jz exit mov cx,l ;hiện 1 lần mov bl,0ach ;màu đỏ đậm, nền màu xanh, nháy mov ah,09h int 10h inc dl ;chuyển con trỏ sang phải mov ah,02h int 10h inc si jmp 11 exit: mov ah, 01h im 21h mov ah,4ch int 21h Code ends Endstart Ngắt của Dos phục vụ chế độ văn bản (int 21h) Chức Ý nghĩa tham số năng 02h Hiện một ký tự ra màn hình DL <- mã ASCII của ký tự cần hiện 09h Hiện một xâu ký tự kết thúc bằng $ ra DS:DX <- seg:offset đầu xâu màn hình 122
- b) Ngắt liên quan đến chế độ đồ hoạ màn hình Khái niệm: Bảng mầu của màn hình CGA Chức Ý nghĩa Tham số năng 0h sét mode cho màn hình Vào: AL <- Số thể hiện màn hình 0bh Chọn màu nền cho toàn bộ màn hình Vào: BH <- 0, chọn màu cho toàn bộ Chọn bộ màu cho pixel màn hình để trong BL mầu BH <- 1 Cho bộ mầu pixel BL <- bộ màu 0ch Hiện một pixel Vào. DX <- Số dòng CX <- Số cột AL <- Số màu 123
- MỤC LỤC Chương 1. NGÔN NGỮ ASM VÀ CÁCH LẬP TRÌNH (25 tiết) 2 1.1. Mở đầu 2 1.2. Cài đặt chương trình dịch TASM 2 1.3. Các bước thực hiện một chương trình Assember trên máy PC: 3 1.4. Sự hỗ trợ của hệ thống cho việc lập trình Assember 4 1.4.1 Cấu trúc các thanh ghi 4 1.4.2 Cách thể hiện địa chỉ ô nhớ (ROM hoặc RAM): dạng 1ôgíc và dạng vật lý 7 1.4.3 Các ngắt hay dùng hỗ trợ cho lập trình Assembler 7 1.5. Hệ lệnh Assembler 8 1.5.1. Cú pháp của một dòng lệnh ASM 8 1.5.2. Tập lệnh Mnemonic 8 1.5.3 Các lệnh điều khiển khi dịch chương trình (directive) 26 1.6. Chương trình con 43 1.6.1. Ý nghĩa của chương trình con 43 1.6.2. Cơ chế khi một chương trình con bị gọi 44 1.6.3. Cú pháp một chương trình con ASM 44 1.7. MACRO 48 1.7.1. Ý nghĩa 48 1.7.2. Khai báo (xác lập) MACRO 48 1.7.3 Cách dùng MACRO đã được xác lập 50 1.8. Directive INCLUDE 50 1.8.1. Ý nghĩa 50 1.8.2 Cú pháp chèn 50 1.8.3. Cơ chế khi chương trình dịch TASMGẶP directive INCLUDE 50 1.9. Chương trình đa tệp 64 1.9.1. Ý nghĩa 64 1.9.2. Directive PUBLIC 64 1.9.3. Directive EXTRN 65 1.9.4. Cách dịch và liên kết 68 1.10. Biến hỗn hợp : Directive STRUC, RECORD và UNION 68 1.10.1. Cấu trúc STRUC 68 1.10.2 Directive UNION 69 1.11. Xây dựng chương trình Assembly để được tệp thực hiện dạng .COM 69 1.11.1. Sự khác nhau chương trình dạng COM và EXE 69 1.11.2. Làm thế nào để có được chương trình dạng .COM 69 1.11.3. Các vấn đề cần lưu ý - Directive ORG 100h 69 1.11.4. Dạng thường thấy 1 chương trình ASM để được dạng COM 70 Chương 2: LIÊN KẾT CÁC NGÔN NGỮ BẬC CAO VỚI ASM 79 2.1. Liên kết Pascal với ASM 79 2.1.1. Inline ASM 79 2.1.2. Viết tách biệt tệp ngôn ngữ Pascal và tệp ASM 80 2.2 Liên kết c/c++ với ASM 91 2.2.1. InlineAssembly 91 2.2.2 Viết tách biệt C/C++ và tệp ASM 93 Chương 3: LẬP TRÌNH HỆ THỐNG 104 3.1. Các bước khi máy tính khởi động 104 3.2 Phân loại ngắt và khái niệm 105 3.3 Cơ chế khi một ngắt được kích hoạt 106 3.4. Các bước xác lập ngắt 107 124
- 3.4.1. Viết chương trình con phục vụ ngắt theo yêu cầu của thuật toán 107 3.4.2. Lấy địa chỉ đầu của chương trình con phục vụ ngắt 107 3.5. Vùng dữ liệu ROM BIOS 110 3.6. Các ngắt hay dùng trong hệ thống 116 3.6.1. Ngắt bàn phím 117 3.6.2. Các ngắt với màn hình 120 125