经典汇编语言教程:12.3 简单的屏幕编辑程序
11956 点击·0 回帖
![]() | ![]() | |
![]() | 下面是一个简单的屏幕编辑的C语言程序,它不仅涉及到键盘处理、光标定位、屏幕输出、字符颜色等,而且还运用了C语言和汇编语言的混合编程方法。若读者能把它改写成相同功能的汇编语言程序,那么,可以说,你已基本掌握了中断的使用方法,也对计算机输入输出的工作方式有了更进一步的认识。 该程序的功能: ◆ 可用移动光标键↑、↓、←和→移动光标1行或1列,也可用TAB/Shift+TAB、Home和End键跳跃地移动光标; ◆ 当光标已在第1行,再向上移动时,这时,光标被定位到第25行,反之也然; ◆ 当光标已在第0列,还要向左移动时,光标被定位到第79列,反之也然; ◆ 当按下^W或^Z时,屏幕将向上或向下滚动1行; ◆ 显示当前键盘的状态:大小写状态、数字键盘状态和插入/修改状态; ◆ 如果按普通的键,将在屏幕上显示该字符,如果按下用Alt、Ctrl或Shift组合的组合键,则显示该按键的扫描码; ◆ 用Esc键来结束程序的运行。 C语言的源程序清单: #define NUM_KEY 0x20 /* 键盘状态字宏定义 */ #define CAPS_KEY 0x40 #define ESCAPE 27 /* 几个功能键的宏定义 */ #define TAB_KEY 9 #define SHIFT_TAB 15 #define CTRL_W 23 #define CTRL_Z 26 #define UP_ARROW 72 #define DOWN_ARROW 80 #define LEFT_ARROW 75 #define RIGHT_ARROW 77 #define INSERT 82 #define END_KEY 79 #define HOME_KEY 71 #define UP_SCROLL 6 /* 屏幕滚动宏定义 */ #define DOWN_SCROLL 7 #include <dos.h> int insert, cap_key, num_key; /* up_down:屏幕滚动方式:6-向上滚; 7-向下滚 (l_row, l_col)-(r_row, r_col):滚动矩形的对角线坐标 num:屏幕滚动的行数,0-清屏 attr:滚动后所剩下行的属性 */ cls(int up_down, int l_row, int l_col, int r_row, int r_col, int num, intattr) {union REGS in, out; in.h.ah = up_down; in.h.al = num; in.h.ch = l_row; in.h.cl = l_col; in.h.dh = r_row; in.h.dl = r_col; in.h.bh = attr; int86(0x10, ;in, ;out); } get_cursor(int *x, int *y) /* 取当前光标的位置,并分别存入变量x和y中*/ {union REGS in, out; in.h.ah = 3; in.h.bh = 0; int86(0x10, ;in, ;out); *x = out.h.dh; *y = out.h.dl; } locate(int row, int col) /* 把光标设置在(row, col)位置 */ {union REGS in, out; in.h.ah = 2; in.h.bh = 0; in.h.dh = row; in.h.dl = col; int86(0x10, ;in, ;out); } disp_string(int row, int col, char string[]) /* 在(row, col)位置显示字符串string */ {struct REGPACK in, out; int x, y; get_cursor(;x, ;y); locate(row, col); in.r_ds = FP_SEG(string); in.r_dx = FP_OFF(string); in.r_ax = 0x900; intr(0x21, ;in); locate(x, y); } check_key_state() /* 在(row, col)位置以属性attr显示字符ch */ {char state; state = bioskey(2); if (state ; CAPS_KEY) {if (!cap_key) {cap_key = 1; disp_string(24, 66, "CAP$");} } else if (cap_key) {cap_key = 0; disp_string(24, 66, " $");} if (state ; NUM_KEY) {if (!num_key) {num_key = 1; disp_string(24, 70, "NUM$");} } else if (num_key) {num_key = 0; disp_string(24, 70, " $");} } insert_key() /* 在最后一行显示插入/修改状态标志,并改变光标形状 */ {union REGS in, out; insert = 1 - insert; disp_string(24, 74, (insert ? "INS$" : " $")); /* 显示插入/修改标志 */ in.h.ah = 1; in.h.ch = (insert ? 0 : 14); in.h.cl = 15; /* 改变光标的形状 */ int86(0x10, ;in, ;out); } move_right(int row, int col, int len) /* 在(row, col)位置之后的字符和属性向后移len个位置 */ {int j, attr; char ch; for (j = 79; j >= col+len; j--) {read_char_attr(row, j-len, ;ch, ;attr); write_char_attr(row, j, ch, attr); } } read_char_attr(int row, int col, char *ch, int *attr) /* 在读(row, col)位置字符和属性,并分别存入ch和attr */ {union REGS in, out; locate(i, j); in.h.ah = 8; in.h.bh = 0; int86(0x10, ;in, ;out); *ch = out.h.al; *attr = out.h.ah; } write_char_attr(int row, int col, char ch, int attr) /* 在(row, col)位置以属性attr显示字符ch */ {union REGS in, out; locate(row, col); in.h.ah = 9; in.h.al = ch; in.h.bh = 0; in.h.bl = attr; in.x.cx = 1; int86(0x10, ;in, ;out); } ctos(char ascii, char str[]) /* 把字符的ASCII码转换成字符串 */ {int i; i = 2; do {str[i--] = ascii%10 + '0'; ascii /= 10; } while (ascii >0); for (; i >= 0; i--) str = ' '; } main() {int k, key, row, col; char ch1, ch2, str[]=" $"; /* 前面有3个空格 */ char msg1[]="This is a simple screen edidtor.$", msg2[]="You can move cursor by Arrow keys, TAB/Shift-TAB, Home and End.$", msg3[]="You can press ^W for scroll up or ^Z for scroll down.$", msg4[]="It has some functions, such as insert/modify a char.$", msg5[]="If you press a function key, or key combined with Alt, Ctrl, Shift, it will display the key's scan code.$", msg6[]="The program exits when you press ESCAPE.$"; cls(UP_SCROLL, 0, 0, 24, 79, 0, 7); disp_string(0, 0, msg1); disp_string(2, 0, msg2); disp_string(4, 0, msg3); disp_string(6, 0, msg4); disp_string(8, 0, msg5); disp_string(11, 0, msg6); row = col = ch1 = insert = 0; locate(row, col); while (ch1 != ESCAPE) {while (ch1 != ESCAPE) {if (!bioskey(1)) {check_key_state(); continue;} key = bioskey(0); ch1 = key; ch2 = key >>8; if (ch1 != 0) {switch(ch1) {case TAB_KEY: col = ((col;0xFFF8) + 8) %80; break; case CTRL_W: cls(DOWN_SCROLL, 0, 0, 24, 79, 1, 7); row = row + 1; break; case CTRL_Z: cls(UP_SCROLL, 0, 0, 24, 79, 1, 7); break; default: if (ch1 == ESCAPE) continue; if (insert) move_right(row, col, 1); write_char_attr(row, col, ch1, 31); col = (col+1+80) % 80; break; } locate(row, col); continue; } switch (ch2) {case UP_ARROW: row = (row-1+25) % 25; break; case DOWN_ARROW: row = (row+1+25) % 25; break; case LEFT_ARROW: col = (col-1+80) % 80; break; case RIGHT_ARROW: col = (col+1+80) % 80; break; case SHIFT_TAB: k = col ; 0xFFF8; col = (col - ((k==0)? 8:k+80)) % 80; break; case HOME_KEY: col = 0; break; case END_KEY: col = 79; break; case INSERT: insert_key(;insert); break; default: ctos(ch2, str); k = strlen(str)-1; if (insert) move_right(row, col, k); disp_string(row, col, str); col = (col + k + 80) % 80; break; } locate(row, col); } } cls(UP_SCROLL, 0, 0, 24, 79, 0, 7); | |
![]() | ![]() |