当前位置: 首页 > 文档资料 > 汇编语言教程 >

12.3 简单的屏幕编辑程序

优质
小牛编辑
132浏览
2023-12-01

12.3 简单的屏幕编辑程序

下面是一个简单的屏幕编辑的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, int attr)

{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[i] = ' ';
}

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);
}