1. Trang chủ
  2. » Giáo Dục - Đào Tạo

Lập trình bằng Turbo Pascal part 10 pot

22 464 1
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 22
Dung lượng 262,16 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Một ngắt lại có thể lμm vμi việc khác nhau, mỗi việc như thế cũng gán tương ứng với một số nguyên, gọi lμ chức năng của ngắt.. DOS chấm dứt chương trình .COM Thực hiện rất nhiều chức năn

Trang 1

1.1.2 Cấu trúc của địa chỉ trong bộ nhớ

Bộ vi xử lí họ 8086 dùng 20 bit để đánh địa chỉ bộ nhớ Suy ra nó quản lí được một không gian địa chỉ gồm 2 20 bit = 1 MB hay 1.048.576 địa chỉ Nhưng các thanh ghi chỉ có 16 bit, chỉ có thể quản lí một không gian địa chỉ gồm 2 16 bit = 64 KB hay 65.536 địa chỉ Vì lí do nμy, bộ nhớ được chia lμm nhiều đoạn - segment, mỗi đoạn gồm 64 KB Địa chỉ một ô nhớ gồm hai phần, có dạng Segment: offset Segment lμ địa chỉ đoạn, được ghi trong các thanh ghi đoạn, còn offset lμ độ dịch chuyển, được ghi trong các thanh ghi

offset Địa chỉ thực của ô nhớ sẽ nhận được sau khi nhân địa chỉ đoạn với 16

(hay lμ dịch trái 4 bit) rồi cộng với điạ chỉ offset

Trong Pascal người ta dùng dấu hiệu $ đứng trước một số hệ đếm 16

(hexadecimal) để phân biệt với số thập phân thông thường Các địa chỉ ô nhớ thường được viết bằng số trong hệ đếm cơ số 16 Ví dụ $F12A:$E82B Địa chỉ thực tương ứng sẽ lμ $F12A0 + $E82B = $FFACB

1.2 Các ngắt - interrupt

1024 byte đầu tiên trong bộ nhớ được chia thμnh 256 bộ 4 byte, chứa

được 256 địa chỉ, trỏ đến các chương trình xử lí các công việc cơ sở của hệ thống gọi lμ các véc tơ ngắt - Interrupt Các ngắt được đánh số từ 0 đến 255 hay lμ từ $00 đến $FF

Một ngắt lại có thể lμm vμi việc khác nhau, mỗi việc như thế cũng gán

tương ứng với một số nguyên, gọi lμ chức năng của ngắt Ví dụ, ngắt số 16 =

$10 lμ ngắt phục vụ mμn hình Ngắt nμy lại có nhiều chức năng khác nhau

như

$00: Thiết lập chế độ mμn hình

$03: Lấy toạ độ con chạy trên mμn hình văn bản

$0F: Lấy chế độ hiện tại của mμn hình

Trang 2

DOS chấm dứt chương trình COM Thực hiện rất nhiều chức năng của DOS

1.3 Thâm nhập trực tiếp qua thanh ghi và ngắt

Việc gọi thực hiện ngắt từ trong một chương trình Pascal cũng qua

những bước tương tự Unit Dos của TurboPascal cung cấp các hỗ trợ cần

thiết để thực hiện gọi ngắt

Trước hết, để truy cập các thanh ghi của bộ vi xử lí, có kiểu dữ liệu

thanh ghi - Registers được định nghĩa trong Unit Dos như sau

Type registers = record

Case Integer of

0: (AX, BX, CX, DX, BP, SI, DI, DS, ES, Flags: word);

1: (AL, AH, BL, BH, CL, CH, DL, DH: byte);

Trang 3

MsDos( Var Regs: Registers);

Biến thanh ghi Regs đóng vai trò cung cấp dữ liệu đầu vμo cho ngắt

được gọi vμ cũng lμ nơi để nhận kết quả trả về nếu có

MsDos dμnh riêng để gọi các phục vụ của Dos, ứng với ngắt số $21

Lời gọi MsDos(Regs) tương đương với lời gọi Intr( $21, Regs) vì ngắt số

$21 lμ các phục vụ của DOS

1.3.2

1.4.1

Các bước gọi ngắt

- Khai báo một biến kiểu thanh ghi, ví dụ Regs

- Đặt các giá trị cần thiết cho các thanh ghi thông qua các trường của

biến Regs Quy ước:

AH chứa số hiệu của chức năng

AL chứa số hiệu của chức năng phụ (nếu có)

Các thanh ghi còn lại dùng đến hay không tuỳ theo từng ngắt

- Gọi thực hiện ngắt bằng Intr hay MsDos

- Nhận kết quả trả về trong các trường của Regs (nếu cần)

Để biết công việc của mỗi ngắt, các chức năng ngắt khác nhau, ý nghĩa của thông tin trả về trong các thanh ghi,v.v cần tham khảo các tμi liệu tra cứu về hệ thống, hệ điều hμnh DOS

1.4 Các ví dụ minh hoạ

begin

Trang 4

writeln(' mode man hinh la:',AL);

writeln(' so cot :',AH);

writeln(' active page :',BH);

procedure SetVideoMode(mode: integer);

var regs: registers;

begin with regs do

Xem vμ thiÕt lËp ngμy hÖ thèng

Ng¾t cã sè hiÖu $21 thùc hiÖn nhiÒu chøc n¨ng kh¸c nhau cña DOS

Trang 5

if AL=0 then Writeln('da dat ngay xong !')

else writeln('co loi');

Tham số đầu vμo:

DL:= số hiệu của ổ đĩa (0,1,2 );

Giá trị trả về

Trang 6

AX= số sector cho mỗi cluster ( = $FFFF nếu ổ đĩa không hợp

function SoByteConRoi(Drv: char): LongInt;

var regs: registers;

if AX=$FFFF then SoByteConRoi:=-1

else SoByteConRoi:= LongInt(AX)*BX*CX;

end;

end;

BEGIN write(' Cho ten o dia:'); readln(TenODia);

Ketqua:= SoByteConRoi(TenODia);

if Ketqua =-1 then writeln(' Co loi!')

else writeln(' con ', Ketqua:0, 'byte trong ');

readln;

END

1.5 Sử dụng các hàm, thủ tục của unit DOS

Trong phần trước ta đã thấy việc thâm nhập hệ thống vμ thực hiện một

số chức năng hệ điều hμnh DOS một cách trực tiếp sử dụng các ngắt lμ khá tỉ

mỉ vμ mất nhiều công sức

Unit DOS của Turbo Pascal cung cấp một thư viện các chương trình

con lμm sẵn, hỗ trợ người sử dụng trong các giao tiếp với hệ thống vμ hệ điều hμnh Có thể sử dụng các hμm, thủ tục ấy để thâm nhập hệ thống dễ dμng hơn

Ví dụ, có thể xem vμ đặt ngμy tháng hệ thống bằng các thủ tục GetDate,

Trang 7

Rõ rμng lμ với sự hỗ trợ của unit Dos, việc thâm nhập hệ thống, thực hiện

các chức năng thông dụng của hệ điều hμnh DOS trở nên dễ dμng hơn nhiều

Cần tìm hiểu kĩ về unit Dos để nắm được cách sử dụng rất nhiều hμm vμ thủ

tục đã được lμm sẵn trong đó

2 Điều khiển chuột

2.1 Toạ độ chuột

Mμn hình văn bản chuẩn gồm 80 cột, 25 dòng tức lμ 2000 ô chữ nhật,

mỗi ô hiển thị một kí tự Trong khi đó, mμn hình đồ hoạ lại chia lμm nhiều

điểm ảnh, thấp nhất cũng lμ 640 x 480 đối vơí mμn hình VGA Để con chuột

có thể dùng trong cả hai chế độ mμn hình, người ta quy định toạ độ micki của

chuột biến đổi trong khoảng sau đây, không phụ thuộc chế độ văn bản hay đồ hoạ

0 ≤ x_mouse ≤ 632

0 ≤ y_mouse ≤ 192

Trang 8

Để chuyển sang toạ độ x_text, y_text trên mμn hình văn bản, lưu ý rằng 1 ≤ x_text ≤ 80, ≤ y_text ≤ 25 ta sẽ có công thức đổi toạ độ chuột

sang toạ độ trên mμn hình văn bản lμ

x_text = x_mouse/8 + 1

y_text = y_mouse/8 + 1

Theo công thức trên, ta sẽ được 8 x 8 = 64 điểm chuột trong một ô kí tự trên

mμn hình văn bản Khi nhấn chuột vμo các điểm nμy đều chỉ ứng với một ô

vị trí kí tự trên mμn hình văn bản mμ thôi

Công thức chuyển toạ độ chuột sang toạ độ trên mμn hình đồ hoạ lμ

x_graphics = (x_mouse / 632) * getmaxx;

y_graphics = (y_mouse / 192) * getmaxy;

ở đây getmaxx, getmaxy lμ toạ độ x, toạ độ y lớn nhất của chế độ đồ hoạ

đang xét

2.2 Ngắt điều khiển chuột $33

Con chuột được điều khiển thông qua sử dụng ngắt số hiệu $33 Ngắt nμy có nhiều chức năng khác nhau Cần gán các số hiệu chức năng (sẽ liệt kê dưới đây) cho thanh ghi AX (chứ không phải AH như các ngắt khác)

Các chức năng điều khiển chuột của ngắt $33

1- Chức năng 0: khởi tạo chuột

CX:= toạ độ x_mouse của chuột

DX:= toạ độ y_mouse của chuột

BX sẽ cho trạng thái của các phím chuột

Bit 0 = 0 phím trái nhả

Bit 0 = 1 phím trái được nhấn

Bit 1 = 0 phím phảI nhả

Bit 1 = 1 phím phảI được nhấn

5 - Chức năng 4: Di chuyển con trỏ chuột

Đầu vμo CX = toạ độ x mới

DX = toạ độ y mới

Trang 9

6- Hỏi trạng thái vμ số lần nhấn phím kể từ khi gọi chức năng nμy

Đầu vμo BX = phím cần hỏi: 0 = trái, 1 = phải, 2 = giữa

Đầu ra

AX cho trạng thái phím (0 = nhả, 1 = nhấn)

Bít 0 cho trạng thái phím trái

Bít 1 cho trạng thái phím phải

Bít 2 cho trạng thái phím giữa

BX:= số lần nhấn CX:= toạ độ x lần nhấn cuối cùng DX:= toạ độ y lần nhấn cuối cùng

7- Hỏi trạng thái vμ số lần nhả phím kể từ khi gọi chức năng nμy

Đầu vμo BX = phím cần hỏi: 0 = tráI, 1 = phảI, 2 = giữa

Đầu ra

AX cho trạng thái phím (0 = nhả, 1 = nhấn)

Bít 0 cho trạng thái phím trái

Bít 1 cho trạng thái phím phải

Bít 2 cho trạng thái phím giữa

BX:= số lần nhấn

CX:= toạ độ x lần nhấn cuối cùng

DX:= toạ độ y lần nhấn cuối cùng

8 - Chức năng 7: Hạn chế phạm vi di chuyển ngang của chuột (phạm vi biến

đổi của x_mouse)

Đầu vμo: CX:= cột trái

9 - Chức năng 8: Hạn chế phạm vi di chuyển dọc của chuột (phạm vi biến

đổi của y_mouse)

Đầu vμo: CX:= Dòng trên cùng

DX:= Dòng dưới cùng

2.3 Ví dụ minh hoạ

2.3.1 Khởi tạo chuột

Ta xây dựng thủ tục mouseInit thực hiện các chức năng: kiểm tra nếu

đã cμi đặt chuột thì thiết lập toạ độ ban đầu của chuột, hạn chế phạm vi tác dụng của chuột trong một khung hình chữ nhật vμ cho hiển thị chuột (một hình chữ nhật) trên mμn hình văn bản

Để dễ nhớ, ta định nghĩa các hằng số lμ các chức năng của ngắt $33

như trình bμy trên x,y lμ toạ độ ban đầu của chuột Left, Top, Right, Bottom

Trang 10

Trong thủ tục dưới đây vμ các thủ tục khác tiếp theo sau, Regs lμ biến

kiểu thanh ghi

var Regs: registers;

y_graphics như đã nói trên

const MOUSE_GET_POSITION = $03;

procedure getMousePosition(VAR x,y: integer);

begin

Trang 11

regs.AX:= MOUSE_GET_POSITION;

intr(INT_MOUSE,regs);

x:= regs.CX; y:= regs.DX;

end;

2.3.3 Bắt sự kiện nhấn vμ nhả phím chuột

Sự kiện thông dụng nhất của chuột cần xử lí lμ nhấn phím vμ nhả phím

Thủ tục getMouseClickLeft cho phép ghi lại sự kiện nhấn phím chuột trái vμ toạ độ điểm nhấn Thủ tục getMouseReleaseLeft cho phép ghi lại sự kiện thả

phím chuột trái vμ toạ độ điểm thả chuột

Hoμn toμn tương tự ta có thể đón bắt các sự kiện chuột phải

2.4 Thư viện các thủ tục thao tác chuột

Tập hợp các thủ tục trên ta có thể xây dựng một thư viện các hμm tiện ích thao tác chuột Ví dụ,

Trang 12

INT_MOUSE = $33; (*ngat chuot*)

procedure getMousePosition(VAR x,y: integer);

procedure getMouseClickLeft(VAR numclick, x, y

Ta đã xây dựng bảng chọn, xử lí bằng gõ phím mũi tên

Có thể bổ xung thêm các thủ tục xử lí sự kiện chuột để cho phép chọn bằng nhấn phím trái chuột

Thủ tục xử lí gõ phím bây giờ đ−ợc mở rộng thêm thμnh thủ tục xử lí

sự kiện, bao gồm cả sự kiện nhấn chuột nh− sau

Trang 13

mouse_x:= raw_x DIV 8 + 1;

{nhan chuot ben ngoai bang}

if ((mouse_x < x) or ( x+rong < mouse_x)

or (mouse_y < y) or ( y+SoMucChon < mouse_y)) then BangChon:= -1

else

{nhan chuot ben trong bang}

for i:=0 to SoMucChon do

Turbo Pascal hỗ trợ thâm nhập trực tiếp vμo bộ nhớ Cả bộ nhớ coi như

một mảng Kích thước của các phần tử mảng (ô nhớ) có thể lμ 1 byte, 1 word

(= 2 byte) hay 1 LongInt (= 4 byte)

Biến mảng Mem dùng để truy cập đến từng byte trong bộ nhớ

Biến mảng MemW dùng để truy cập theo từng Word

Biến mảng MemL dùng để truy cập theo từng LongInt

Cần chỉ rõ địa chỉ của ô nhớ đầu tiên dưới dạng Segment: offset Ví dụ:

Mem[$xxxx: $yyyy]: truy cập một byte bộ nhớ tại địa chỉ $xxxx:

$yyyy

Trang 14

MemW[$xxxx: $yyyy]: truy cập 2 byte bộ nhớ (1 word) kể từ địa chỉ

có thể thâm nhập trực tiếp vμo vùng nhớ nμy để tăng tốc độ cho các thao tác hiển thị ra mμn hình

Chương trình dưới đây thay toμn bộ các kí tự trống bằng dấu sao “*”

procedure get_screen(var scr: one_screen);

{truy cập bộ nhớ mμn hình vμ chép lại toμn bộ mμn hình hiện tại}

procedure put_screen(var scr: one_screen);

{truy cập bộ nhớ mμn hình vμ cho hiển thị mμn hình đã lưu} var i: word;

begin

Trang 15

Writeln(' Day la man hinh se luu lai !');

Writeln(' go ENTER de luu man hinh !!!');

readln;

get_screen(old_src);

TextMode(origMode);

Clrscr;

Writeln('Man hinh cu da duoc luu lai');

Writeln('Go ENTER de xem man hinh cu !!!');

Cách truy cập trực tiếp các cổng xuất nhập (I/O port) cũng giống như

truy cập trực tiếp bộ nhớ trình bμy ở phần trên

Mảng Port để truy cập các cổng theo từng byte,

Mảng PortW để truy cập các cổng theo từng Word

Port[ i ]: truy cập một byte vùng nhớ của cổng có địa chỉ chứa trong biến i PortW[ i ]: truy cập một Word vùng nhớ của cổng có địa chỉ chứa trong biến

i

Thay đổi địa chỉ nμy ta sẽ truy cập cổng của các thiết bị khác nhau

Chương trình minh họa dưới đây lμm mμn hình trôi liên tục từ phải sang trái bằng cách thâm nhập trực tiếp vμo cổng CRT

program CuonManHinh;

Trang 16

for i:= 0 to num do

PortW[CrtAddr]:= Hi(i) SHL 8 + $0C;

PortW[CrtAddr]:= Lo(i) SHL 8 + $0D;

asm STI end;

Khi thi hμnh một chương trình, hệ điều hμnh dμnh riêng một khối nhớ

để chứa mã lệnh vμ các dữ liệu của chương trình Lúc chương trình kết thúc,

DOS sẽ gọi hμm $4C - kết thúc tiến trình vμ giải phóng vùng nhớ dμnh riêng cho chương trình, chép Command.com đè lên vùng nμy

Một cách thứ hai để kết thúc chương trình lμ dùng hμm Keep Sự khác biệt giữa Keep vμ kết thúc bình thường lμ DOS không giải phóng vùng nhớ

đã dμnh cho chương trình, nghĩa lμ không chép Command.com đè lên vùng

nμy mμ chép vμo phần còn trống khác Như vậy, chương trình vẫn còn nằm lại trong bộ nhớ

Chương trình thường trú hay TSR- Terminate and Stay Resident - lμ

chương trình mμ khi kết thúc không bị xoá khỏi bộ nhớ, nó vẫn còn lưu lại chờ vμ thực hiện chức năng công việc của mình phục vụ cho chương trình khác khi cần đến

Ví dụ các phần mềm để chuyển bμn phím từ gõ tiếng Anh sang gõ

được tiếng Việt đều lμ các chương trình thường trú Nó chặn ngắt bμn phím

vμ thay vec tơ ngắt thông thường bằng một thủ tục xử lí khác để khi gõ aa thì sẽ chuyển thμnh mã của â, gõ dd thì chuyển thμnh mã của đ, v.v

Kĩ thuật lập trình thường trú đòi hỏi phải kết hợp chặt chẽ với hệ thống, chặn vμ thay đổi một số ngắt để phục vụ cho mục đích của mình

Trang 17

- Xây dựng thủ tục xử lí ngắt mới

- Lưu lại các véc tơ ngắt mμ chương trình sẽ chiếm dụng

- Thiết đặt lại các véc tơ ngắt để ứng với các thủ tục ngắt mới

- Phục hồi lại chúng khi kết thúc

Cho kết thúc chương trình vμ ở lại thường trú

Mã thoát exitCode = 0 lμ kết thúc bình thường, exitCode = 1 lμ thoát bằng Ctrl+C, exitCode = 2 lμ thoát khi chia cho 0

Vậy một chương trình thường trú phải có Keep(0) trước từ khoá END

Ngoμi ra còn một số thủ tục hỗ trợ lμm việc vói các véc tơ ngắt

GetIntVec (IntNo: Byte; Vector: Pointer) ;

Lưu lại véc tơ ngắt số hiệu IntNo vμo địa chỉ xác dịnh trong biến

Vector

SetIntVec (IntNo: Byte; Vector: Pointer);

Đặt lại véc tơ ngắt số hiệu IntNo ứng với địa chỉ xác định trong biến

4.3 Ví dụ minh hoạ

Trang 18

4.3.1 Ví dụ 1

Đầu tiên ta xét một ví dụ đơn giản, lμm một chương trình thường trú

chiếm ngắt số $05 lμ ngắt có chức năng in nội dung của mμn hình ra máy in Ngắt nμy ứng với phím Print-screen Ta sẽ thay nó bằng một thủ tục ngắt

mới, thực hiện việc in ra kí tự #1 (khuôn mặt cười) tại góc mμn hình

Trong chương trình trên cần lưu ý mấy điểm sau

1- Phải có chỉ thị biên dịch {$M 1024,0,0} để hạn chế vùng Heap Nhắc lại rằng chỉ thị cho trình biên dịch phân bố bộ nhớ {$M StackSize,

HeapMin, HeapMax} có các giá trị mặc định lμ {$M 16384, 0, 655360},

nghĩa lμ HeapMax có thể đạt đến địa chỉ cao nhất của bộ nhớ RAM Nếu

HeapMax không được giơí hạn bởi 0 vμ dùng hμm Keep để kết thúc chương

trình thì bộ nhớ sẽ bị chiếm dụng hết đến byte cuối cùng, không còn chỗ để

tái nạp lại Command.com khi kết thúc thi hμnh chương trình

2- Khai báo Interrupt lμ bắt buộc đối với một thủ tục ngắt, tức lμ thủ

tục được gọi khi có một ngắt xảy ra Trong chương trình nμy lμ thủ tục

VietRaGocManHinh Lúc nμy trình biên dịch sẽ sinh mã để cất giữ tạm thời

nội dung tất cả các thanh ghi trước khi gọi thủ tục ngắt vμ hoμn nguyên lại các giá trị thanh ghi sau khi thủ tục ngắt kết thúc Nếu thiếu khai báo nμy, trình biên dịch coi thủ tục ngắt lμ một thủ tục thông thường như mọi thủ tục khác, không báo lỗi vμo thời điểm dịch vμ chương trình sẽ đổ vỡ ngay

3- Lệnh SetIntVec($00, SaveInt00) để khôi phục lại ngắt $00 - "chia

cho không"

Chương trình trên mới chỉ quan tâm lμm thế nμo chiếm chỗ của một

ngắt khác Nó đã viết đè lên giá trị gốc ban đầu của ngắt $05 Không có cách nμo để khôi phục lại chức năng gốc của phím Print-Screen ngoμi việc tắt máy

khởi động lại

Ngày đăng: 23/07/2014, 21:20

TỪ KHÓA LIÊN QUAN