📄 ch5.prg
字号:
1、重排代码段次序程序
;*********************************************************
; 程序名: DOS_HDR.ASM
; 功能: 定义TC目标代码的段次序
; 说明: 本模块可以和任何TC产生的目标代码文件连接,
; 从而生成新的TC可执行代码。
; 操作步骤: TASM DOS_HDR,M1
; LINK M1+?????
; 程序员: 《用C语言写DOS设备驱动程序》,希望电脑公司
;*********************************************************
name dos_hdr.asm
_DATA segment word public 'DATA'
_d@ label byte
_DATA ends
_BSS segment word public 'BSS'
_b@ label byte
_BSS ends
_TEXT segment byte public 'CODE'
DGROUP group _DATA,_BSS,_TEXT
assume cs:DGROUP,ds:DGROUP,ss:DGROUP
_TEXT ends
end
2、替换命令描述文件DOS.ARR
在该文件中,必需注意制表符的安排问题,一定要严格按照TCC产生的汇编
语言程序的格式,否则将找不到替换的对象。下面的该文本的清单∶
s/DGROUP group _DATA,_BSS/DGROUP group _DATA,_BSS,_TEXT/
s/assume cs:_TEXT/assume cs:DGROUP/
s/dw@/dwDGROUP:@/
s/dw _Init_cmd/dw DGROUP:_Init_cmd/
s/dw _Media_check_cmd/dw DGROUP:_Media_check_cmd/
s/dw _Build_bpb_cmd/dw DGROUP:_Build_bpb_cmd/
s/dw _Ioctl_input_cmd/dw DGROUP:_Ioctl_input_cmd/
s/dw _Input_cmd/dw DGROUP:_Input_cmd/
s/dw _Input_no_wait_cmd/dw DGROUP:_Input_no_wait_cmd/
s/dw _Input_status_cmd/dw DGROUP:_Input_status_cmd/
s/dw _Input_flush_cmd/dw DGROUP:_Input_flush_cmd/
s/dw _Output_cmd/dw DGROUP:_Output_cmd/
s/dw _Output_verify_cmd/dw DGROUP:_Output_verify_cmd/
s/dw _Output_status_cmd/dw DGROUP:_Output_status_cmd/
s/dw _Output_flush_cmd/dw DGROUP:_Output_flush_cmd/
s/dw _Ioctl_output_cmd/dw DGROUP:_Ioctl_output_cmd/
s/dw _Dev_open_cmd/dw DGROUP:_Dev_open_cmd/
s/dw _Dev_close_cmd/dw DGROUP:_Dev_close_cmd/
s/dw _Remove_media_cmd/dw DGROUP:_Remove_media_cmd/
s/dw _Unknown_cmd/dw DGROUP:_Unknown_cmd/
s/dw _Ioctl_cmd/dw DGROUP:_Ioctl_cmd/
s/dw _Get_logical_device_map_cmd/dw DGROUP:_Get_logical_device_map_cmd/
s/dw _Set_logical_device_map_cmd/dw DGROUP:_Set_logical_device_map_cmd/
3、预处理程序清单
/*****************************************************************
程序名:arrange.c
功能: 修改_TEXT段属组及其相关引用
说明: 未对读出文件的格式作容错匹配处理,强烈要求对照表
文件与源文件在制表符上的匹配。
程序员:原作《用C语言写DOS设备驱动程序》,希望电脑公司;
修改: 吕强
时间: 1993,8,23. 第1.10版
*****************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXCMDS 100 /* 最大可接受的替换行数 */
#define LINEWID 100 /* 最大行宽度 */
/***********************************************************
出错处理
***********************************************************/
error(char *s1,char *s2)
{
fprintf(stderr,s1,s2);
exit(1);
}
/*********************************************************
在line行中按s行描述的替换对应进行替换
*********************************************************/
substitute(char *s,char *line)
{
char *p;
int i,slen;
char source[LINEWID],target[LINEWID],tmpstr[LINEWID];
char delimiter = *s; /* 获得分界符 */
/* 把s串中当前点至分界符处的字串搬入source串 */
for (i=0,s++; *s!='\n' && *s!=delimiter; i++)
source[i] = *s++;
source[i] = '\0';
if ((slen=strlen(source))<=0) /* 验证source串有内容 */
error("Line %s, source line cannot be empty",s);
/* 把s串中当前点至分界符处的字串搬入target串 */
for (i=0,s++; *s!='\n' && *s!=delimiter; i++)
target[i] = *s++;
target[i] = '\0';
for (p=strstr(line,source); p; p=strstr(p+1,source))
{ /* 在目标串中找到了source串 */
strcpy(tmpstr,p+slen); /* 在目标串中略去source串 */
strcpy(p,target); /* 把source串内容替换成target串 */
strcpy(p+strlen(target),tmpstr);
}
}
/*********************************************************
命令行语法: ARRANGE FILE1 FILE2 FILE3
FILE1:对照表文件名(DOS.ARR)
FILE2:源文件名(?.ASM)
FILE3:目标文件名(?.ASM)
*********************************************************/
main(int argc, char *argv[])
{
char *cmds[MAXCMDS];
char line[LINEWID];
FILE *fp_cmd_change_table;
FILE *fpin, *fpout;
int nl=0;
/* 打开各个文件 */
if ((fp_cmd_change_table=fopen(argv[1],"r")) == NULL)
error("Can not open table file %s",argv[1]);
if ((fpin=fopen(argv[2],"r")) == NULL)
error("Can not open input file %s",argv[2]);
if ((fpout=fopen(argv[3],"w")) == NULL)
error("Can not open output file %s",argv[3]);
/* 把对照表文件中的替换对应行读入cmds数组 */
while (fgets(line,LINEWID,fp_cmd_change_table))
{
cmds[nl] = strdup(line);
if (!cmds[nl]) error("strdup failed at line %s",line);
if (++nl >= MAXLINE) error("Too many commands in table file","");
}
cmds[nl] = NULL;
/* 在生成的汇编语言程序的头行插入.286c行 */
line[0]='\0';
strcpy(line,".286c\n");
fputs(line,fpout);
while (fgets(line,LINEWID,fpin))
{ /* 依次取源文件的每一行 */
int i; char *p;
for (i=0; p=cmds[i]; i++)
{ /* 依次取该操作的描述行 */
switch(*p)
{
case 's': /* 是替换对应行命令 */
substitute(++p,line); /* 按p所描述的进行处理 */
break;
default: /* 只处理替换命令 */
error("Unknown command %s",p);
break;
}
}
fputs(line,fpout); /* 把经过替换处理的行写入目标文件 */
}
fcloseall();
}
二、块设备驱动程序框架程序
1、变量定义文件
/*****************************************************************
程序名:dos_ddh.h
功能:
说明:
程序员:原作《用C语言写DOS设备驱动程序》,希望电脑公司;
修改: 吕强
时间: 1993,8,23. 第1.10版
*****************************************************************/
/* symbolic contansts */
#define DOS_CMDS 25 /* number of DOS commands */
#define STACK_LENGTH 512 /* DOS device driver stack */
#define DEVICES 1 /* number of block devices */
#define OP_COMPLETE 0x0000 /* no errors return code */
/* device attribute field definitons in DDH_struct.ddh_attribute */
#define CHAR_DD 0x8000
#define IOCTL_SUP 0x4000
#define NON_IBM 0x2000
#define REMOVABLE 0x0800
#define GET_SET 0x0040
#define CLOCK_DD 0x0008
#define NUL_DD 0x0004
#define STDOUT_DD 0x0002
#define STDIN_DD 0x0001
#define GEN_IOCTL 0x0001
struct DDH_struct
{
struct DDH_struct far *next_DDH;
unsigned int ddh_attribute;
unsigned int ddh_strategy;
unsigned int ddh_interrupt;
unsigned char ddh_name[8];
};
/* device staus word mask word */
#define ERROR_BIT 0x8000 /* error bit mask */
#define ERROR_NUM 0x00FF /* error number mask */
#define DONE_BIT 0x0100 /* device operation done */
#define BUSY_BIT 0x0200 /* device busy */
/* the value of the REQ_struct.status */
#define WRITE_PROTECT 0x00
#define UNKNOWN_UNIT 0x01
#define NOT_READY 0x02
#define UNKNOWN_CMD 0x03
#define CRC_ERROR 0x04
#define BAD_REQ_LEN 0x05
#define SEEK_ERROR 0x06
#define UNKNOWN_MEDIA 0x07
#define NOT_FOUND 0x08
#define OUT_OF_PAPER 0x09
#define WRITE_FAULT 0x0A
#define READ_FAULT 0x0B
#define GENERAL_FAIL 0x0C
/* device driver command codes in REQ_struct.command */
#define INIT 0
#define MEDIA_CHECK 1
#define BUILD_BPB 2
#define IOCTL_INPUT 3
#define INPUT 4
#define INPUT_NO_WAIT 5
#define INPUT_STATUS 6
#define INPUT_FLUSH 7
#define OUTPUT 8
#define OUTPUT_VERIFY 9
#define OUTPUT_STATUS 10
#define OUTPUT_FLUSH 11
#define IOCTL_OUTPUT 12
#define DEV_OPEN 13
#define DEV_CLOSE 14
#define REMOVE_MEDIA 15
#define RESERVED_1 16
#define RESERVED_2 17
#define RESERVED_3 18
#define IOCTL 19
#define RESERVED_4 20
#define RESERVED_5 21
#define RESERVED_6 22
#define GET_LOGICAL_DRIVE_MAP 23
#define SET_LOGICAL_DRIVE_MAP 24
/* request header of every command */
struct INIT_struct
{
unsigned char num_of_units;
unsigned int far *end_ptr;
unsigned int far *BPB_ptr;
unsigned char drive_num;
unsigned int last_drv;
};
struct MEDIA_CHECK_struct
{
unsigned char media_byte;
unsigned char return_info;
unsigned char far *return_ptr;
};
struct BUILD_BPB_struct
{
unsigned char media_byte;
unsigned char far *buffer_ptr;
struct BPB_struct far *BPB_table;
};
struct I_O_struct /* IOCTL_INPUT,INPUT,OUTPUT,OUTPUT_VERIFY,IOCTL_OUTPUT */
{
unsigned char media_byte;
unsigned char far *buffer_ptr;
unsigned int count;
unsigned int start_sector;
unsigned char far *vol_id_ptr;
unsigned long start_sector_32;
};
struct INPUT_NO_WAIT_struct
{
unsigned char byte_read;
};
struct IOCTL_struct
{
unsigned char majorgu_func;
unsigned char Minor_func;
unsigned int SI_reg;
unsigned int DI_reg;
unsigned char far *ioctl_req_ptr;
};
struct L_D_MAP_struct
{
unsigned char unit_code;
unsigned char cmd_code;
unsigned int status;
unsigned long reserved;
};
struct REQ_struct
{
unsigned char length;
unsigned char unit;
unsigned char command;
unsigned int status;
unsigned char reserved[8];
union
{
struct INIT_struct init_req;
struct MEDIA_CHECK_struct media_check_req;
struct BUILD_BPB_struct build_BPB_req;
struct I_O_struct i_o_req;
struct INPUT_NO_WAIT_struct input_no_wait_req;
struct IOCTL_struct ioctl_req;
struct L_D_MAP_struct l_d_map_req;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -