Tải bản đầy đủ (.doc) (7 trang)

Truy xuất vùng nhớ

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (79.25 KB, 7 trang )

Kỹ thuật truy xuất vùng nhớ máy tính
Lê Hoàng Tuấn
Ngay từ khi bắt đầu làm quen với ngôn ngữ lậptrình Pascal, ta đã biết dùng thủ tục Write
để xuất một chuỗi kí tự hay một giátrị ra màn hình. Đồng thời dùng thủ tục Textcolor và
Textbackground để định màuchữ và màu nền. Trong quá trình học Pascal có khi nào bạn
thử xuất dữ liệu tạitọa độ (80, 25) chưa Chẳng hạn:
Uses crt;
Begin
Gotoxy(80,25); { giả sử Modemàn hình là 80x25 }
Write("A");
Readln;
End;
Khi thử ví dụ trên, chữ A sẽkhông hiển thị tại tọa độ (80, 25) mà là (80, 24). Nguyên nhân
là do thủ tụcWrite xuất dữ liệu tại tọa độ con trỏ, sau đó con trỏ đứng liền kề kí tự
cuốicùng vừa xuất. Do không tồn tại tọa độ (81, 25) nên con trỏ nhảy xuống dòng kếtiếp
đẩy màn hình lên một dòng và tọa độ (80, 25) trở thành (80, 24).
Nhiềubạn sẽ cho rằng không cần thiết phải giải quyết vấn đề trên vì khi viết chươngtrình
chúng ta thường không có nhu cầu xuất dữ liệu tại tọa độ góc dưới bênphải màn hình (tọa
độ này thay đổi tùy theo mode màn hình 80x25, 40x25... ).Tuy nhiên vẫn có một số trường
hợp cần xuất dữ liệu tại tọa độ này. Chẳng hạn 2dòng: đầu và cuối màn hình có màu khác
với màu nền để ghi tên chương trình, tácgiả, kích thước file, ngày cập nhật... (giống như
giao diện của chương trìnhdiệt virus Bkav, D2... ).
Sau đây sẽ trình bày kĩ thuật truy xuấttrực tiếp vào vùng nhớ màn hình để khắc phục vấn
đề trên. Kĩ thuật này cũnggiúp ích nhiều cho việc trình bày màn hình ở chế độ văn bản khi
viết chươngtrình bằng Turbo Pascal.
Để thực hiện được kĩ thuật này trước tiênhãy tìm hiểu về cơ chế hoạt động của màn hình
máy vi tính.
Khi hoạt động, máy tính liên tục đọc bộ nhớRam để lấy các thông tin như hiển thị kí tự gì
với màu sắc gì và ở tọa độ nàotrên màn hình. Vùng nhớ chứa các thông tin này trong Ram
gọi là vùng nhớ mànhình (VNMH). Mỗi kí tự hiển thị tại một tọa độ nào đó trên màn hình
được lưutrữ trong VNMH bằng 2 byte: byte thứ nhất là byte thấp chứa mã ASCII của kí


tựcần hiển thị, byte thứ hai là byte cao chứa thuộc tính màu (bao gồm màu của kítự và màu
nền của kí tự đó). Như vậy khi truy xuất vào VNMH, nếu thay đổi đượcthông tin tại một
tọa độ nào đó thì có thể trình bày màn hình theo ý muốn màkhông ảnh hưởng đến vị trí con
trỏ (đây là điểm cơ bản giúp xuất được dữ liệutại tọa độ (80, 25)). Tuy nhiên, muốn truy
xuất vàoVNMH cần phải xác định vị trí của nó trong máy tính. Địa chỉ của một vùng
nhớtrong bộ nhớ được biểu diễn bằng một cặp số cơ số 16, cách nhau một dấu 2 chấm(:).
Số bên trái là địa chỉ Segment (địa chỉ cơ sở đoạn), số bên phải là địachỉ Offset của vùng
nhớ.
Ví dụ: đối với Card Hercule Monochrome địa chỉ của VNMHlà $B000, đối với Card CGA,
EGA, VGA... có địa chỉ $B800.
Nếu đã biết rõ máy tính đang dùng Card mànhình nào, ta có thể truy xuất trực tiếp vào
VNMH có địa chỉ tương ứng. Nhưng đểchương trình chạy được trên nhiều máy khác nhau,
cần xác định địa chỉ VNMH bằngcách truy nhập vào vùng nhớ 1 byte $0000:$0449 chứa
giá trị Mode màn hình.
Để truy xuất một vùng nhớ máytính, ta dùng các biến truy xuất vùng nhớ do Pascal cung
cấp :
Tên biến Kiểu Công dụng
Mem Array of byte Truy xuất vùng nhớ 1 byte
Memw Array of word Truy xuất vùng nhớ 2 byte
Meml Array of longint Truy xuất vùng nhớ 4 byte
Có thể viết hàm lấy địa chỉ Segment của VNMH như sau:
Function Segment:word;
Begin
If mem[$0000:$0449]=7 then segment:=$B000
Else segment:=$B800;
End;
Hàm lấy địa chỉ Offset của một tọa độ bất kì trên mànhình:
Function Offset(cot,dong:byte):word;
Begin
Case mem[$0000:$0449] of

offset:=2*(Cot-1) + 80*(dong-1) { đối với mode 40x25 }
Else offset:=2*(Cot-1) + 160*(dong-1); {đối với mode 80x25 }
End;
End;
Khi đã truy nhập vào VNMH, bạncó thể trình bày dữ liệu trên màn hình theo ý muốn hoặc
thay đổi các thông tintrong vùng nhớ này để tạo ra các hiệu ứng hình ảnh thú vị trong chế
độ văn bản.
Cú pháp truy xuất như sau:
Nếu chỉ muốn truy xuất vào 1 trong 2 byte (byte thấpchứa mã kí tự, byte cao chứa thuộc
tính màu) thì dùng biến Mem:
Mem[Segment:Offset(x,y)+1]:=Mau;
Mem[Segment:Offset(x,y)]:=Ord(KiTu);
Nếu muốn truy xuất vào cả hai byte thì dùng biến Memw:
Memw[Segment:Offset(x,y)]:=(MauShl 8) + Ord(KiTu);
Ví dụ 1: Viết ra màn hình chứ A màu xanh trên nền trắngtại tọa độ (80, 25). Giả sử
mode màn hình là 80x25.
Đầu tiên xác định địa chỉSegment của VNMH và lấy địa chỉ Offset của tọa độ (80,25), sau
đó thực hiện cúpháp như nói trên.
Var Seg,Off : word;
Begin
Seg:=Segment;
Off:=Offset(80,25);
Memw[Seg:Off]:=($71 Shl 8) +Ord("A");
Readln;
End.
Ví dụ 2: Truy xuất vào byte cao nơi chứa thuộc tính màusẽ cho phép định lại màu của 1
toạ độ bất kì. Bằng cách này có thể tạo nhiều hiệu ứnghình ảnh thú vị, tương tự cách dùng
thủ tục Putpixel của Turbo Pascal mà bạnNguyễn Xuân Tài đã đề cập trong bài viết Điểm,
màu & Toán học (TH&NT số 6 - 2000). Sự khác nhau giữa hai cách này là một bên hoạt
độngtrong chế độ văn bản còn bên kia hoạt động trong chế độ đồ họa. Tất nhiên hìnhảnh

tạo ra bằng cách truy xuất VNMH sẽ không mịn bằng cách dùng thủ tục Putpixel.Nguyên
nhân là do cấu trúc khác nhau của màn hình giữa hai chế độ văn bản và đồhọa. Màn hình
đồ họa gồm nhiều điểm ảnh (Pixel) rất nhỏ còn màn hình văn bảngồm một số cột và hàng.
Hãy thử các ví dụ sau:
Đầu tiên là 7 dải màu giống như 7 sắc cầu vồng:
For x:=1 to 80 do
For y:=1 to 25 do
Begin
Mau:=(x+y) mod 256;
Mem[segment:offset(x,y)+1]:=mau;
End;
Lần lượt thay thế biến Mau bằng các công thức khác:
Đường caro: Mau:=(x+y)*(x+y) mod 256;
Đường cong nhiều màu: Mau:=(x*y) mod 256;
Một số hoa văn lạ mắt:
Mau:=(x mod 32)*(y mod 32)*ymod 16*2;
Mau:=(x+y)*abs(x-y) mod 256;
Mau:=(x+y)*abs(x-y) mod 26;
Mau:=(x+y)*abs(x-y) mod 46;
Mau:=(x+y)*abs(x-y) mod 66;
Bây giờ xin trình bày một ứngdụng nhỏ áp dụng kĩ thuật truy xuất trực tiếp VNMH: Cuộn
lên, cuộn xuống, qualại một vùng dữ liệu trên màn hình. Đây là việc hay gặp khi viết các
chươngtrình cần hiển thị một văn bản có số dòng lớn hơn số dòng trên màn hình. Giả
sửcần cuộn dòng y lên một dòng, ta có giải thuật như sau:
+ Truy xuất vào VNMH chứa nộidung của dòng y do con trỏ P1 quản lí.
+ Ghi nội dung này vào vùng nhớcủa dòng y -1 do con trỏ P2 quản lí.
+ Xóa nội dung của dòng y đểtạo dòng trắng cùng màu với màu nền.
Thủ tục sau sẽ cuộn một vùng màn hình lên 1 dòng:
Procedure Cuonlen(x1,y1,x2,y2,maunen:byte);
Var

p1,p2:^word;
x,y:byte;
sobyte:word;
Begin
for y:=y1 to y2 - 1 do
Begin
p1:=ptr(segment,offset(x1,y+1));
p2:=ptr(segment,offset(x1, y));
sobyte:=2*(x2 - x1+1);
move(p1^,p2^,sobyte);
End;
for x:=x1 to x2 do {Tạo dòng trống cùng màu nền}
memw[segment:offset(x,y2)]:=(maunenshl 8) + ord(' ');
End;
Thủ tục cuộn một vùng màn hình xuống 1 dòng:
Procedure Cuonxuong(x1,y1,x2,y2,maunen:byte);
Var

Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay
×