chương 9
Truy nhập trực tiếp vào bộ nhớ
Trong chương này trỡnh bầy cỏc vấn đề:
+ Hai kiểu địa chỉ: Địa chỉ phõn đoạn và địa chỉ thực
+ Truy nhập tới địa chỉ phõn đoạn
+ Đổi từ địa chỉ phõn đoạn sang địa chỉ thực
+ Bộ nhớ màn hỡnh, truy nhập trực tiếp vào bộ nhớ màn hỡnh
+ Dựng con trỏ để lấy dữ liệu từ bộ nhớ phõn đoạn
+ Dựng con trỏ hàm để thực hiện cỏc thủ tục của DOS
§
1. Cỏc hàm truy nhập theo địa chỉ phõn đoạn
1. Hàm pokeb: Gửi một ký tự vào bộ nhớ.
+ Nguyờn mẫu trong dos.h như sau:
void pokeb(unsigned seg, unsigned off, char value);
+ Cụng dụng: Gửi giỏ trị ký tự value vào bộ nhớ tại địa chỉ phõn
đoạn seg:off
2. Hàm peekb: Nhận một ký tự từ bộ nhớ.
+ Nguyờn mẫu trong dos.h như sau:
char peekb(unsigned seg, unsigned off);
+ Cụng dụng: Nhận một byte tại địa chỉ phõn đoạn seg:off
3. Hàm poke: Gửi một số nguyờn vào bộ nhớ.
+ Nguyờn mẫu trong dos.h như sau:
void poke(unsigned seg, unsigned off, int value);
+ Cụng dụng: Gửi giỏ trị nguyờn value vào bộ nhớ tại địa chỉ phõn
đoạn seg:off
4. Hàm peek: Nhận một số nguyờn từ bộ nhớ.
+ Nguyờn mẫu trong dos.h như sau:
int peek(unsigned seg, unsigned off);
+ Cụng dụng: Nhận một word tại địa chỉ phõn đoạn seg:off
5. Hàm movedata: Sao cỏc byte.
+ Nguyờn mẫu trong mem.h như sau:
2.3. Chọn trang hiển thị
Tại mỗi thời điểm chỉ cú thể hiển thị được một trong 4 trang màn
hỡnh. Để hiển thị trang màn hỡnh thứ t (t=0,1,2,3) chỳng ta sử dụng
chức năng 5 của ngắt 0x10 theo mẫu sau:
union REGS v,r;
v.h.ah = 5 ; // Chức năng 5
v.h.al = t ; // Số hiệu trang màn hỡnh cần hiển thị
int86(0x10, &v, &r); // Thực hiện ngắt 0x10
2.4. Vớ dụ minh hoạ
Vớ dụ sau dựng hàm pokeb để đưa cỏc ký tự vào cỏc trang của bộ
nhớ màn hỡnh, sau đú dựng chức năng 5 của ngắt 0x10 để chọn trang
hiển thị.
//CT9_03.CPP
#include <dos.h>
#include <conio.h>
char d1[]={'C',1*16+14,'H',1*16+14,'U',1*16+14,'C',1*16+14};
char d2[]={'M',2*16+15,'U',2*16+15,'N',2*16+15,'G',2*16+15};
void main()
{
union REGS v,r;
clrscr();
//Mặc định hiển thị trang 0
for (int i=0;i<8;++i)
pokeb(0xb800,i,d1[i]);
getch();
//Hien thi trang 1
v.h.ah = 5 ; v.h.al = 1 ;
int86(0x10,&v,&r);
for (i=0;i<8;++i)
pokeb(0xb800,0x1000+i,d2[i]);
§
4. cỏc vớ dụ minh hoạ
Chương trỡnh 1. Chương trỡnh minh hoạ cỏch truy nhập trực tiếp
vào bộ nhớ màn hỡnh cú địa chỉ đầu là 0xB800:0. Chương trỡnh gồm
hàm main() và hai hàm sau:
1. Hàm cuaso
void cuaso(int dongt,int cott,int dongd,int cotd,int maucs);
thiết lập một cửa sổ mầu cú toạ độ gúc trờn-trỏi là (dongt, cott) và gúc
dưới-phải là (dongd,cotd). Mầu cho bởi tham số maucs. ở đõy sử
dụng hàm pokeb và địa chỉ phõn đoạn.
2. Hàm duarmh
void duarmh(char *day, int dong, int cotd, int cotc,int m_nen,
int m_chu);
sẽ đưa ra màn hỡnh một dẫy ký tự (chứa trong dóy) tại dũng dong, từ
cột cotd đến cotc. Mầu nền cho bởi m_nen, mầu chữ cho bởi m_chữ.
ở đõy sử dụng toỏn tử gỏn trờn địa chỉ thực.
Trong hàm main() sẽ sử dụng cỏc hàm cuaso và duarmh để tạo hai
cửa sổ và viết hai dũng chữ trờn trang màn hỡnh thứ hai (từ dũng 26
đến dũng 50).
/*
chương trỡnh minh hoạ cỏch truy nhập trực tiếp vào bộ
nhớ của màn hỡnh
*/
#include "dos.h"
#include "conio.h"
void duarmh(char *day, int dong,I nt cotd, int cotc,I nt m_nen, int
m_chu);
void cuaso(int dongt,int cott,int dongd,int cotd,int maucs);
main()
{
{
p=t*4096+i*160+(cott-1)*2;
for (j=0;j<=cotd-cott;++j)
{
pokeb(0xb800,p+2*j,32);
pokeb(0xb800,p+2*j+1,mau);
}
}
}
void duarmh(char *day, int dong, int cotd, int cotc, int m_nen,
int m_chu)
/* Dung dia chi thuc */
{
int i,p,t,d,kt,mau;
char far *buf;
union REGS v,r;
/* Lay dia chi thuc cua bo nho man hinh */
buf=(char far*)MK_FP(0xb800,0);
/* Xac dinh thuoc tinh mau */
mau = (m_nen << 4)+m_chu;
/*
Xac dinh trang man hinh t
va cac chi so dong d trong trang t
*/
t=(dong-1)/25; d=dong-1-t*25;
/* Chon t la trang hien thi */
v.h.ah=5;v.h.al=t; int86(0x10,&v,&r);
p=t*4096+d*160+(cotd-1)*2;
/*
Dua cac ky tu va thuoc tinh mau
printf("\n So hieu ngat (Bam 0 - Ket thuc): ");
scanf("%d",&n); if(n==0) break;
k=(n-1)*4;
off=p[k]+256*p[k+1]; seg=p[k+2]+256*p[k+3];
printf("\nDia chi %x:%x",seg,off);
}
}
Chương trỡnh 3. Chương trỡnh minh hoạ cỏch dựng con trỏ hàm
để thực hiện thủ tục khởi động lại mỏy của DOS, biết địa chỉ đầu của
thủ tục này là 0xFFFF:0000 . Chương trỡnh yờu cầu nhập mật khẩu.
Nếu chọn đỳng (bấm ABCD và Enter) thỡ chương trỡnh tiếp tục làm
việc, nếu vào sai thỡ sẽ khởi động lại mỏy.
#include <dos.h>
#include <conio.h>
#include <iostream.h>
#include <ctype.h>
typedef void far (*HAM)(void);
void khoi_dong_may(void)
{
HAM f;
f = (HAM)MK_FP(0xFFFF,0);
f();
}
char mat_khau[]= {'A','B','C','D'};
int n = sizeof(mat_khau)/sizeof(char);
void main()
{
char i, ch, sai_mat_khau;
clrscr();
i=0;