Giáo trình C - Chương 4: Bộ nhớ và hiển thị kí tự
Các phép toán này có thể áp dụng cho dữ liệu kiểu int , char nh-ng không áp dụng
cho số float .
Toán tử & (khác với and logic &&) cần hai toán hạng có kiểu giống nhau . Các toán
hạng này đ-ợc and bit với bit . Toán tử & th-ờng dùng kiểm tra xem một bit cụ thể nào đó
có trị là bao nhiêu . Ví dụ để kiểm tra bit thứ 3 cuả biến ch có trị 1 hay 0 ta dùng phép toán :
ch &0x08;
thêm một trình xử lí văn bản theo dòng . Trình xử lí này chỉ làm việc trên một dòng văn bản . Ta sẽ tiến hành theo 2 b−ớc : đầu tiên là một ch−ơng trình cho phép ng−ời dùng gõ vào một dòng 50 và di chuyển con nháy tới lui . Có thể xoá kí tự nhờ di chuyển con nháy tới đó và ghi đè lên nó . Ch−ơng trình nh− sau : Ch−ơng trình 4-4 : #include #include #define colmax 80 #define rarrow 77 #define larrow 75 #define video 0x10 #define ctrlc '\x03' int col=0; int far *fptr; union REGS reg; void main() { char ch; void clear(void); void cursor(void); void insert(char); fptr=(int far*)0xB8000000; clear(); cursor(); while((ch=getch())!=ctrlc) { if (ch==0) { ch=getch(); switch (ch) { case rarrow : if (col<colmax) ++col; break; case larrow : if (col>0) --col; break; } } else if (col<colmax) insert(ch); cursor(); } } void cursor() { reg.h.ah=2; reg.h.dl=col; reg.h.dh=0; 51 reg.h.bh=0; int86(video,®,®); } void insert(char ch) { *(fptr+col)=ch|0x0700; ++col; } void clear() { int j; for (j=0;j<2000;j++) *(fptr+j)=0x0700; } Để xoá màn hình ta điền số 0 vào vùng nhớ màn hình với thuộc tính 07 . Sau đó con nháy đ−ợc di chuyển về đầu màn hình nhờ phục vụ ấn định vị trí con nháy nh− sau : ngắt 10h ah=0; dh=số hiệu dòng dl= số hiệu cột bh=số hiệu trang , th−ờng là 0 Phát biểu switch dùng để đoán nhận các phím đ−ợc nhận là phím th−ờng hay phím chức năng . Phím mũi tên dùng tăng giảm col và gọi hàm cursor() để di chuyển con nháy tới đó . Nếu kí tự gõ vào là kí tự th−ờng , nó đ−ợc chèn vào nhờ hàm insert() . 6. Byte thuộc tính : Một kí tự trên màn hình đ−ợc l−u giữ bởi 2 byte : một byte là mã của kí tự và byte kia là thuộc tính của nó . Byte thuộc tính đ−ợc chia làm nhiều phần , bit nào bằng 1 thì thì thuộc tính t−ơng ứng đ−ợc bật . Bit thứ 3 điều khiển độ sáng còn bit thứ 7 điều khiển độ chớp nháy . Các bit còn lại là : 6 - thành phần đỏ của màu nền ; 5 - thành phần green của màu nền ; 4 - thành phần blue của màu nền ; 2 - thành phần đỏ của màu chữ ; 1 - thành phần green của màu chữ ; 0 - thành phần blue của màu chữ . Ta lập một ch−ơng trình để điền đầy màn hình bằng các kí tự chớp nháy . Ch−ơng trình 4-5 : #include #include #define rowmax 25 #define colmax 80 void main() { int far *fptr; int row,col; char ch; clrscr(); printf("Go vao mot ki tu , go lai de thay doi"); fptr=(int far*)0xB8000000; while((ch=getche())!='x') for (row=0;row<rowmax;row++) 52 for (col=0;col<colmax;col++) *(fptr+row*colmax+col)=ch|0x8700; } Để bật chớp nháy ta để bit thứ 7 thành 1 , 3 bit màu nền 0 , 1 và 2 đ−ợc đặt trị 1 nên nền sẽ là đen . Byte thuộc tính lúc này là 10000111 = 87h. 7. Ch−ơng trình điền thuộc tính : Để hiểu sâu hơn thuộc tính của kí tự ta xét ch−ơng trình sau Ch−ơng trình 4-6 : #include #include #define rowmax 25 #define colmax 80 void main() { int far *fptr; char ch,attr=0x07; void fill(char,char); clrscr(); printf("Go n cho chu binh thuong,\n"); printf("Go b cho chu xanh nuoc bien,\n"); printf("Go i cho chu sang,\n"); printf("Go c cho chu chop nhay,\n"); printf("Go r cho chu dao mau\n"); while((ch=getche())!='x') { switch (ch) { case 'n':attr=0x07; break; case 'b':attr=attr&0x88; attr=attr|0x01; break; case 'i':attr=attr^0x08; break; case 'c':attr=attr^0x80; break; case 'r':attr=attr&0x88; attr=attr|0x70; break; } fill(ch,attr); } } void fill(char ch,char attr) { int far *fptr; int row,col; fptr=(int far*)0xB8000000; for (row=0;row<rowmax;row++) 53 for (col=0;col<colmax;col++) *(fptr+row*colmax+col)=ch|attr<<8; } Trong hàm fill() ta có lệnh *(fptr+row*colmax+col)=ch|attr<<8; vì attr là kí tự nên phải dịch trái 8 bit tr−ớc khi kết hợp với ch . 8. Trở lại xử lí văn bản : Bây giờ chúng ta đã biết thuộc tính của kí tự và ta sẽ mở rộng ch−ơng trình xử lí văn bản bằng cách thêm vào việc chèn và huỷ bỏ kí tự ,đổi màu . Ch−ơng trình 4-7 : #include #include #define colmax 80 #define rarrow 77 #define larrow 75 #define video 0x10 #define norm 0x07 #define blue 0x01 #define bkspc 8 #define altu 22 #define ctrlc '\x03' int col=0; int length=0; int far *fptr; union REGS reg; void main() { char ch,attr=norm; void clear(void); void cursor(void); void insert(char,char); void del(void); fptr=(int far*)0xB8000000; clear(); cursor(); while((ch=getch())!=ctrlc) { if (ch==0) { ch=getch(); switch (ch) { case rarrow : if (col<length) ++col; break; case larrow : if (col>0) --col; break; case altu : attr=(attr==norm)? blue:norm; } 54 } else switch (ch) { case bkspc: if (length>0) del(); break; default : if (length<colmax) insert(ch,attr); } cursor(); } } void cursor() { reg.h.ah=2; reg.h.dl=col; reg.h.dh=0; reg.h.bh=0; int86(video,®,®); } void insert(char ch,char attr) { int i; for (i=length;i>col;i--) *(fptr+i)=*(fptr+i-1); *(fptr+col)=ch|attr<<8; ++length; ++col; } void del() { int i; for (i=col;i<=length;i++) *(fptr+i-1)=*(fptr+i); --length; --col; } void clear() { int j; for (j=0;j<2000;j++) *(fptr+j)=0x0700; } Khi gõ tổ hợp phím Alt+U sẽ lật biến attr qua lại giữa norm(thuộc tính 07) và blue (cho chữ màu xanh - thuộc tính 01) . Hàm insert(0 có vòng lặp for dùng để thâm nhập trực 55 tiếp bộ nhớ và con trỏ far để dịch các kí tự sang trái khi cần chèn . Tiến trìmh dịch phải bắt đầu từ cuối câu để tránh ghi đè lên . Đ4. Các kiểu bộ nhớ trong C 1. Địa chỉ đoạn và offset : Trong C kiểu bộ nhớ là khái niệm để chỉ về l−ợng các phần bộ nhớ khác nhau mà ch−ơng trình có thể chiếm . C cho phép 6 kiểu bộ nhớ là tiny , small , compact , medium , large và huge . Kiểu bộ nhớ mặc định là small . Bộ vi xử lí dùng các thanh ghi 16 bit để ghi địa chỉ . Thanh ghi 16 bit l−u đ−ợc ffffh byte hay 65536 hay 64 Kb địa chỉ . Vùng nhớ có kích th−ớc này gọi là đoạn . Để truy cập địa chỉ nằm ngoài đoạn , bộ vi xử lí phải dùng hai thanh ghi là thanh ghi đoạn và thanh ghi offset . Địa chỉ thực đ−ợc tính bằng cách dịch địa chỉ của thanh ghi đoạn sang trái 4 bit rồi cộng với thanh ghi offset . Làm nh− vậy ta đánh địa chỉ đ−ợc fffffh hay 1048576 = 1Mb . 2. Hai loại chỉ thị của bộ vi xử lí : Bộ vi xử lí dùng hai kĩ thuật khác nhau để tham chiếu dữ liệu trong bộ nhớ . Nếu vị trí cần tham chiếu nằm trong đoạn 64Kb và đoạn này đã đ−ợc chỉ định trong thanh ghi đoạn thì bộ vi xử lí chỉ cần dùng một lệnh duy nhất để truy cập dữ liệu . Cách này t−ơng ứng với việc dùng con trỏ near trong C và thực hiện rất nhanh . Trái lại nếu bộ vi xử lí cần tham chiếu ô nhớ nằm ngoài đoạn thì đầu tiên nó phải thay đổi địa chỉ đoạn và sau đoa là địa chỉ offset . Điều này t−ơng ứng với việc dùng con trỏ far trong C và thực hiện khá chậm . 3. Các kiểu Compact , small , medium và large : Có 4 loại chỉ thị của bộ vi xử lí ứng với 4 kiểu bộ nhớ trong C Kiểu Mã Dữ liệu small near near medium far near compact near far large far far Nếu mã ch−ơng trình nằm gọn trong một đoạn 64 K và mã dữ liệu nằm gọn trong một đoạn 64 K khác thì kiểu bộ nhớ small là thích hợp . Nếu mã ch−ơng trình lớn hơn 64 K và mã dữ liệu nằm gọn trong một đoạn 64 K khác thì hãy dùng kiểu bộ nhớ medium. Nếu mã ch−ơng trình nhỏ hơn 64 K và mã dữ liệu lớn hơn 64 K thì hãy dùng kiểu bộ nhớ compact. Nếu cả mã ch−ơng trình và mã dữ liệu lớn hơn 64 K thì hãy dùng kiểu bộ nhớ large . 4. Kiểu tyni và kiểu huge : Kiểu tyni đ−ợc dùng trong các tr−ờng hợp đặc biệt với l−ợng bộ nhớ cho cả mã ch−ơng trình lẫn mã dữ liệu nằm gọn trong một đoạn . Kiểu này đ−ợc dùng để tạo ra tập tin dạng *.com . Kiểu huge đ−ợc dùng chô một mục dữ liệu (th−ờng là mảng ) mà bản thân nó lớn hơn 64K . Đ5. Từ chứa danh mục thiết bị Đây là một vùng bộ nhớ dài 2 byte nằm trong vùng nhớ thấp có địa chỉ tuyệt đối là 410h chứa thông tin về thiết bị đ−ợc nối với máy tính. Để truy cậo từ này ta dùng con trỏ far . Con trỏ sẽ chỉ tới đoạn 0000 , địa xhỉ offset là 0410h và đ−ợc biểu diễn trong C là 00000410 hay 0x410 56 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 có Số máy in ổ đĩa đang có Không Có lắp máy dùng in nối tiếp RAM mạch Có lắp game hệ thống adaptor 00=16K Số cổng nối tiếp 01=32K Có lắp chíp 11=64K DMA Kiểu màn hình 01=màu 40 cột Số ổ đĩa 10=màu 80 cột 00 = 1 ổ 11=đơn sắc 80 cột 01 = 2 ổ 10 = 3 ổ 11 = 4 ổ Để xem xét từng bit và nhóm bit trong từ này chúng ta sẽ dùng các toán tử bitweise . Nói chung ta sẽ dịch từ chứa danh mục thiết bị sang phải và đ−a các bit cần quan tâm vào phía phải của từ và che các bit không quan tâm ở phái trái bằng toán tử and . Ngoài từ chứa danh mục thiết bị ta có thể đọc từ chứa kích th−ớc bộ nhớ tại địa chỉ 413h . Ch−ơng trình 4-8 : #define eqlist 0x410 #define memsiz 0x413 #include #include void main() { int far *fptr; unsigned int eq,data; clrscr(); fptr=(int far *)eqlist; eq=*(fptr); data=eq>>14; printf("So may in la : %d\n",data); if (eq&0x2000) printf("Co may in noi tiep\n"); data=(eq>>9)&7; printf("So cong noi tiep la :%d\n",data+1); if (eq&1) { data=(eq>>6)&3; printf("So dia mem la :%d\n",data); } else 57 printf("Khong co dia mem\n"); data=(eq>>4)&3; switch (data) { case 1: printf("Man hinh mau 40 cot\n"); break; case 2: printf("Man hinh mau 80 cot\n"); break; case 3: printf("Man hinh don sac 80 cot\n"); } fptr=(int far *)memsiz; printf("Dung luong bo nho :%dKbyte\n",*(fptr)); getch(); }
File đính kèm:
- Giao_Trinh_C_Chuong4.pdf