中国DOS联盟论坛

中国DOS联盟

-- 联合DOS 推动DOS 发展DOS --

联盟域名:www.cn-dos.net  论坛域名:www.cn-dos.net/forum
DOS,代表着自由开放与发展,我们努力起来,学习FreeDOS和Linux的自由开放与GNU精神,共同创造和发展美好的自由与GNU GPL世界吧!

游客:  注册 | 登录 | 命令行 | 会员 | 搜索 | 上传 | 帮助 »
中国DOS联盟论坛 » DOS开发编程 & 发展交流 (开发室) » QBASIC对QB中断调用的移植及绝对地址调用的扩展
作者:
标题: QBASIC对QB中断调用的移植及绝对地址调用的扩展 上一主题 | 下一主题
本是
银牌会员





积分 2201
发帖 789
注册 2005-1-27
状态 离线
『楼 主』:  QBASIC对QB中断调用的移植及绝对地址调用的扩展

''''本程序只能运行于QBASIC.exe解释环境下!
''''此程序不能在QB.exe或VBDOS.exe等编译环境下运行!
'
'            关于QBASIC对QB中断调用的移植及绝对地址调用的扩展
'
'    近来,市场上出现了不少如何使用QBASIC的书,理由一般有二:一、QBASIC为
'高版本MS-DOS自动搭售,不需要另外花钱购买,只要购买了MS-DOS,
'就不会产生版权之争;二、它是QB编译版稍经简化的解释版本,简便易学,功能
'强大,既向下兼容GW-BASIC,又向上兼容面向窗口编程的VB,又对目前流行的 C或
' C++语言程序设计的结构化练兵,其兼容性和扩展性俱佳。当然,另外还有一点:
'BASIC语言的长寿和普及早已成为不争的事实。
'    但是,不论是这些书中还是QBASIC的在线帮助的未支持的关键词中都说
'1)QBASIC不支持IntXXXXX系列的关键词--中断调用成为泡影;
'2)QBASIC提供内部支持的Absolute关键词,常常因Declare申明中参数数量、类型
'及顺序的不确定性,使申明异常困难--绝对地址调用也不能顺畅。这就大大减弱
'了QBASIC的编程实用性。
'    笔者通过对QBASIC与汇编语言的连接接口规范及相关关键词的深入研究,发现
'通过以本程序中最大数量的参数表进行ANY型申明(使用时,参数数量小于最大数
'量的,要对Absolute中开始的共(参数数量最大值-本调用参数数量值)个参数填
'入任意值)的方法解决了第二个问题,以通过对QB.LIB中INTRPT.obj模块的库操作
'和反汇编,结合Absolute调用,解决了第一个问题。
'    从此,本来只有在QB编译版中可以很方便地调用的中断调用如今在解释版的
'QBASIC中也能如意了----也就是说, QBASIC中也可以实现多个汇编语言子程序对
'QBASIC功能的扩展。而且,这种扩展在国内外尚属首次!
'
'    后面附上QBASIC源程序一和汇编子程序二与三。
'
'

'程序一
''$INCLUDE: "QB.BI" '此行QBASIC中无效,故行首加'
'  在 QBASIC 中,我们可以用
'       DEF SEG = 汇编子程序段地址%
'       CALL ABSOLUTE (中断号%,
'                      inreg AS RegTypeX,
'                      outreg AS RegTypeX
'                      汇编子程序偏移地址%)
'
' 入口:
'       中断号% = 0 到 255
'       inreg 和 outreg 为寄存器变量, 必须事先申明作自定义数据类型
'       RegTypeX, 方法如下:
'
'自定义变量类型申明
'TYPE RegTypeX
'  AX    AS INTEGER
'  BX    AS INTEGER
'  CX    AS INTEGER
'  DX    AS INTEGER
'  BP    AS INTEGER
'  SI    AS INTEGER
'  DI    AS INTEGER
'  FLAGS AS INTEGER
'  DS    AS INTEGER
'  ES    AS INTEGER
'END TYPE
'
' 技巧:
'  如果有必须保留值的寄存器变量, 只要将相应的INreg/OUTreg赋值为 -1,
'  或 NA [= Non-Applicable未使用, 但是要先有 CONST NA = -1 行], 即可.
'
' 出口:
' 若成功:
'   中断号% = 值不变 (0 到 255)
'   outreg: 成为调用后寄存器值的保存数组. 其结构同 inreg.
' 若出错:
'   中断号% = -1
'   outreg 不变.  不执行中断调用.
'   出错情况:
'     第一个参数值不在 0 到 255 (2^8-1) 范围中
'     第二,三个参数值不在 0 到 1048575 (2^20-1) 范围中
'             (VARPTR 的值总是不出这个范围)
'
' 寄存器的变动情况:
'   全部, 除 BP%, DS%, 和 flags (标志寄存器).
'   当然, 也不能避免中断调用本身带来的副作用.
'
' 例外情况:
'   可能出现调用 INT 21H MS-DOS 某些功能时带出的INT 24H 调用.


'自定义变量类型申明
TYPE RegTypeX
  ax    AS INTEGER
  BX    AS INTEGER
  CX    AS INTEGER
  DX    AS INTEGER
  BP    AS INTEGER
  SI    AS INTEGER
  DI    AS INTEGER
  FLAGS AS INTEGER
  DS    AS INTEGER
  ES    AS INTEGER
END TYPE
'汇编子程序申明: 注意REM掉的申明与再下一行在数量和类型上的差异.
'实际使用时,应以一段程序内所有调用中最大的参数数量来进行,类型应申明作ANY,
'这样,% & ! # $各种类型的数据都可以作为实参进行调用了.
'但是,调用时若汇编子程序的参数数量不足最大值,一定要注意形参表中虚实参数的
'对应关系和数量差异,具体操作,请注意本程序的做法.
'DECLARE SUB ABSOLUTE (IntNo%, INreg AS RegTypeX, OUTreg AS RegTypeX, OfsAddr%)
'DECLARE SUB ABSOLUTE (P1%, P2%, numberInWord%, nTHbitFlag%, OfsAddr%)
DECLARE SUB ABSOLUTE (P1 AS ANY, P2 AS ANY, P3 AS ANY, P4 AS ANY, OfsAddr%)

DECLARE FUNCTION SADDr% (SSEGm%, s$)
DECLARE SUB InterruptX (IntNo%, InRegs AS ANY, OutRegs AS ANY)
DECLARE SUB Mouse (aax%, bbx%, ccx%, ddx%)

'常量申明
CONST NA = -1
'变量的自定义类型申明
DIM SHARED INreg AS RegTypeX
DIM SHARED OUTreg AS RegTypeX

'汇编子程序的数组定义
ASMnBytes = 260  '汇编子程序的的字节型长度
DIM SHARED intrpt%(INT(ASMnBytes / 2 + .5))  '使它成为字型长度,偶数化字节数量
RESTORE intrptData  ' 数据指针指向intrptData汇编程序代码区
'poke 到内存中
DEF SEG = VARSEG(intrpt%(0))   ' 改段址.
intPtr% = VARPTR(intrpt%(0))
FOR i% = 0 TO ASMnBytes - 1
  READ vlu$: POKE intPtr% + i%, VAL("&H" + vlu$)
NEXT
DEF SEG

intrptData: '= 260 字节
DATA  55,8B,EC,83,C4,E2,C7,46,FA,0A,00,89,76,E4,89,7E
DATA  E2,8C,5E,FC,9C,8F,46,FE,8B,76,08,8D,7E,E6,8B,4E
DATA  FA,FC,16,07,F3,A5,55,8B,76,0A,8B,1C,0A,FF,0F,84
DATA  03,00,E9,B9,00,80,FB,25,0F,84,07,00,80,FB,26,0F
DATA  85,0E,00,B8,08,00,50,B8,02,CA,50,B8,83,C4,50,EB
DATA  07,33,C0,50,B8,CA,06,50,8A,E3,B0,CD,50,0E,B8,A5
DATA  00,50,16,8B,C4,05,06,00,50,8B,46,F4,25,D5,0F,50
DATA  8B,46,E6,8B,5E,E8,8B,4E,EA,8B,56,EC,8B,76,F0,8B
DATA  7E,F2,83,7E,FA,08,0F,84,16,00,83,7E,F6,FF,0F,84
DATA  03,00,8E,5E,F6,83,7E,F8,FF,0F,84,03,00,8E,46,F8
DATA  8B,6E,EE,9D,CB,55,8B,EC,8B,6E,02,9C,8F,46,F4,FF
DATA  76,FE,9D,89,46,E6,89,5E,E8,89,4E,EA,89,56,EC,8B
DATA  46,DE,89,46,EE,89,76,F0,89,7E,F2,8C,5E,F6,8C,46
DATA  F8,8E,5E,FC,8D,76,E6,1E,07,8B,7E,06,8B,4E,FA,FC
DATA  F3,A5,8B,76,E4,8B,7E,E2,8B,E5,5D,CA,06,00,8B,76
DATA  0A,C7,04,FF,FF,8B,76,E4,8B,7E,E2,8E,5E,FC,8B,E5
DATA  5D,CA,06,00

'
IntNo% = &H11  '按位编码的设备信息列表
InterruptX IntNo%, INreg, OUTreg

CLS
LOCATE 18, 1: PRINT "类Interrupt[X]的中断调用"
PRINT "和数量及类型多变情况下的绝对地址调用"
PRINT "在QBASIC环境下的实现"
LOCATE 2, 1: PRINT CHR$(13); DATE$; CHR$(13); TIME$

' OUTreg.AX% 现在存放着由DOS返回的按位编码的设备信息列表.
' 屏蔽掉不相关的位信息只留下与协处理器相关的第二位.
CoProcessor = OUTreg.ax% AND &H2
' 打印相关信息.
PRINT CHR$(13); CHR$(13); "80x87";
IF OUTreg.ax AND 2 = 2 THEN PRINT "已";  ELSE PRINT "未";
PRINT "找到."

msTest:
aax% = 0
Mouse aax%, -1, -1, -1
PRINT CHR$(13); "鼠标";
IF aax% = -1 THEN PRINT "已";  ELSE PRINT "未"; : msFlag% = -1
PRINT "找到----"

IF msFlag% = -1 THEN PRINT "跳过功能测试.": GOTO testBit

Mouse 1, -1, -1, -1
PRINT "鼠标已打开..."
SLEEP 2

Mouse 2, -1, -1, -1
PRINT "鼠标已关闭."

testBit:
ASMnBytes = 45
DIM SHARED tBit%(INT(ASMnBytes / 2 + .5))
DEF SEG = VARSEG(tBit%(0))
RESTORE tBitData
tPtr% = VARPTR(tBit%(0))
FOR i% = 0 TO ASMnBytes - 1
  READ vlu$: POKE tPtr% + i%, VAL("&H" + vlu$)
NEXT
DEF SEG

tBitData:  '=45 字节
DATA  55,8B,EC,8B,7E,08,8B,1D,8B,7E,06,8B,0D,32,ED,FE
DATA  C9,E3,02,D3,C3,33,C0,F7,D3,F7,C3,00,80,74,02,EB
DATA  01,40,8B,7E,06,89,05,8B,E5,5D,CA,04,00

hzData:
DATA &H0004,&H7FFE,&H4444,&H4444,&H4444,&H7FFC,&H4204,&H0200
DATA &H07F0,&H0810,&H1420,&H62C0,&H0100,&H0600,&H1800,&HE000

RESTORE hzData
PRINT CHR$(13); "移位测值显示汉字:"; CHR$(13); "  罗 ="
P1% = -1
P2% = -1
OfsAddr% = VARPTR(tBit%(0))
DEF SEG = VARSEG(tBit%(0))
FOR i% = 1 TO 16
  READ v%
  FOR j% = 1 TO 16
    jj% = j%
    '原来 CALL testBitFlag (v%, jj%, OfsAddr%)
    CALL ABSOLUTE(P1%, P2%, v%, jj%, OfsAddr%)
    IF jj% THEN cc$ = "#" ELSE cc$ = "."
    LOCATE i%, j% + 22: PRINT cc$;
  NEXT
NEXT
DEF SEG

SLEEP 3
'DECLARE FUNCTION SADDr% (SSEGm%, s$)
s1$ = "这是用来测试SADDr%函数功能的第一个字符串。"
s2$ = "这是第二个字符串。"
CLS
LOCATE 4, 1: PRINT "s1$ = "; s1$
PRINT "s2$ = "; s2$
PRINT
SADDr1% = SADDr%(SSEGm1%, s1$)
PRINT "SSEGm1% ="; SSEGm1%
PRINT "SADDr1% ="; SADDr1%
PRINT
PRINT "44 = 42 + 1 + 1"
PRINT "     42 = s1$字符串的长度,"
PRINT "          1 = QBasic字符串描述符的段地址,"
PRINT "              1 = QBasic字符串描述符的偏移地址."
PRINT
SADDr2% = SADDr%(SSEGm2%, s2$)
PRINT "SSEGm2% ="; SSEGm2%
PRINT "SADDr2% ="; SADDr2%
PRINT
PRINT "SSEGm1% = SSEGm2%,"
PRINT "SADDr1% + 44 = SADDr2%"
SLEEP 4

END

'
'程序二
'
'DATA  55              :'0100  PUSH BP
'DATA  8B,EC           :'0101  MOV  BP,SP
'DATA  83,C4,E2        :'0103  ADD  SP,-1E
'DATA  C7,46,FA,0A,00  :'0106  MOV  WORD PTR [BP-06],0A
'DATA  89,76,E4        :'010B  MOV  [BP-1C],SI
'DATA  89,7E,E2        :'010E  MOV  [BP-1E],DI
'DATA  8C,5E,FC        :'0111  MOV  [BP-04],DS
'DATA  9C              :'0114  PUSHF
'DATA  8F,46,FE        :'0115  POP  [BP-02]
'DATA  8B,76,08        :'0118  MOV  SI,[BP+08]
'DATA  8D,7E,E6        :'011B  LEA  DI,[BP-1A]
'DATA  8B,4E,FA        :'011E  MOV  CX,[BP-06]
'DATA  FC              :'0121  CLD
'DATA  16              :'0122  PUSH SS
'DATA  07              :'0123  POP  ES
'DATA  F3A5            :'0125  REPZ MOVSW
'DATA  55              :'0126  PUSH BP
'DATA  8B,76,0A        :'0127  MOV  SI,[BP+0A]
'DATA  8B,1C           :'012A  MOV  BX,[SI]
'DATA  0A,FF           :'012C  OR BH,BH
'DATA  0F,84,03,00     :'012E  DB F,84,03,00
'DATA  E9,B9,00        :'0132  JMP  01EE
'DATA  80,FB,25        :'0135  CMP  BL,25
'DATA  0F,84,07,00     :'0138  DB F,84,07,00
'DATA  80,FB,26        :'013c  CMP  BL,26
'DATA  0F,85,0E,00     :'013F  DB F,85,E,00
'DATA  B8,08,00        :'0143  MOV AX,8
'DATA  50              :'0146  PUSH AX
'DATA  B8,02,CA        :'0147  MOV  AX,CA02
'DATA  50              :'014A  PUSH AX
'DATA  B8,83,C4        :'014B  MOV  AX,C483
'DATA  50              :'014E  PUSH AX
'DATA  EB,07           :'014F  JMP  0158
'DATA  33,C0           :'0151  XOR  AX,AX
'DATA  50              :'0153  PUSH AX
'DATA  B8,CA,06        :'0154  MOV  AX,06CA
'DATA  50              :'0157  PUSH AX
'DATA  8A,E3           :'0158  MOV  AH,BL
'DATA  B0,CD           :'015A  MOV  AL,CD
'DATA  50              :'015C  PUSH AX
'DATA  0E              :'015D  PUSH CS
'DATA  B8,A5,00        :'015E  MOV  AX,00A5
'DATA  50              :'0161  PUSH AX
'DATA  16              :'0162  PUSH SS
'DATA  8B,C4           :'0163  MOV  AX,SP
'DATA  05,06,00        :'0165  ADD  AX,0006
'DATA  50              :'0168  PUSH AX
'DATA  8B,46,F4        :'0169  MOV  AX,[BP-0C]
'DATA  25,D5,0F        :'016C  AND  AX,0FD5
'DATA  50              :'016F  PUSH AX
'DATA  8B,46,E6        :'0170  MOV  AX,[BP-1A]
'DATA  8B,5E,E8        :'0173  MOV  BX,[BP-18]
'DATA  8B,4E,EA        :'0176  MOV  CX,[BP-16]
'DATA  8B,56,EC        :'0179  MOV  DX,[BP-14]
'DATA  8B,76,F0        :'017C  MOV  SI,[BP-10]
'DATA  8B,7E,F2        :'017F  MOV  DI,[BP-0E]
'DATA  83,7E,FA,08     :'0182  CMP  WORD PTR [BP-06],08
'DATA  0F,84,16,00     :'0186  DB F,84,16,00
'DATA  83,7E,F6,FF     :'018a  CMP  WORD PTR [BP-0A],FFFF
'DATA  84,03,00        :'018F  DB F,84,03,00
'DATA  8E,5E,F6        :'0192  MOV DS,[BP-0A]
'DATA  83,7E,F8,FF     :'0195  CMP  WORD PTR [BP-08],-01
'DATA  0F,84,03,00     :'0199  DB F,84,03,00
'DATA  8E,46,F8        :'019D  MOV  ES,[BP-08]
'DATA  8B,6E,EE        :'01A0  MOV  BP,[BP-12]
'DATA  9D              :'01A3  POPF
'DATA  CB              :'01A4  RETF
'DATA  55              :'01A5  PUSH BP
'DATA  8B,EC           :'01A6  MOV  BP,SP
'DATA  8B,6E,02        :'01A8  MOV  BP,[BP+02]
'DATA  9C              :'01AB  PUSHF
'DATA  8F,46,F4        :'01AC  POP  [BP-0C]
'DATA  FF,76,FE        :'01AF  PUSH [BP-02]
'DATA  9D              :'01B2  POPF
'DATA  89,46,E6        :'01B3  MOV  [BP-1A],AX
'DATA  89,5E,E8        :'01B6  MOV  [BP-18],BX
'DATA  89,4E,EA        :'01B9  MOV  [BP-16],CX
'DATA  89,56,EC        :'01BC  MOV  [BP-14],DX
'DATA  8B,46,DE        :'01BF  MOV  AX,[BP-22]
'DATA  89,46,EE        :'01C2  MOV  [BP-12],AX
'DATA  89,76,F0        :'01C5  MOV  [BP-10],SI
'DATA  89,7E,F2        :'01C8  MOV  [BP-0E],DI
'DATA  8C,5E,F6        :'01CB  MOV  [BP-0A],DS
'DATA  8C,46,F8        :'01CE  MOV  [BP-08],ES
'DATA  8E,5E,FC        :'01D1  MOV  DS,[BP-04]
'DATA  8D,76,E6        :'01D4  LEA  SI,[BP-1A]
'DATA  1E              :'01D7  PUSH DS
'DATA  07              :'01D8  POP  ES
'DATA  8B,7E,06        :'01D9  MOV  DI,[BP+06]
'DATA  8B,4E,FA        :'01DC  MOV  CX,[BP-06]
'DATA  FC              :'01DF  CLD
'DATA  F3,A5           :'01E0  REPZ MOVSW
'DATA  8B,76,E4        :'01E2  MOV  SI,[BP-1C]
'DATA  8B,7E,E2        :'01E5  MOV  DI,[BP-1E]
'DATA  8B,E5           :'01E8  MOV  SP,BP
'DATA  5D              :'01EA  POP  BP
'DATA  CA,06,00        :'01EB  RETF 0006
'DATA  8B,76,0A        :'01EE  MOV  SI,[BP+0A]
'DATA  C7,04,FF,FF     :'01F1  MOV  WORD PTR [SI],FFFF
'DATA  8B,76,E4        :'01F5  MOV  SI,[BP-1C]
'DATA  8B,7E,E2        :'01F8  MOV  DI,[BP-1E]
'DATA  8E,5E,FC        :'01FB  MOV  DS,[BP-04]
'DATA  8B,E5           :'01FE  MOV  SP,BP
'DATA  5D              :'0200  POP  BP
'DATA  CA,06,00        :'0201  RETF 0006
'

'
'程序三
'
'DATA  55           :'0100  PUSH BP
'DATA  8B,EC        :'0101  MOV  BP,SP
'DATA  8B,7E,08     :'0103  MOV  DI,[BP+08]
'DATA  8B,1D        :'0106  MOV  BX,[DI]
'DATA  8B,7E,06     :'0108  MOV  DI,[BP+06]
'DATA  8B,0D        :'010B  MOV  CX,[DI]
'DATA  32,ED        :'010D  XOR  CH,CH
'DATA  FE,C9        :'010F  DEC  CL
'DATA  E3,02        :'0111  JCXZ 0115
'DATA  D3,C3        :'0113  ROL  BX,CL
'DATA  33,C0        :'0115  XOR  AX,AX
'DATA  F7,D3        :'0117  NOT  BX
'DATA  F7,C3,00,80  :'0119  TEST BX,8000
'DATA  74,02        :'011D  JZ 0121
'DATA  EB,01        :'011F  JMP  0122
'DATA  40           :'0121  INC  AX
'DATA  8B,7E,06     :'0122  MOV  DI,[BP+06]
'DATA  89,05        :'0125  MOV  [DI],AX
'DATA  8B,E5        :'0127  MOV  SP,BP
'DATA  5D           :'0129  POP  BP
'DATA  CA,04,00     :'012A  RETF 0004
'
'

'这是对UCDOS特显功能的模拟,需要运行UCDOS及其特显功能模块才能调用!!
SUB ETX (TxCmd$)
INreg.ax = &HE0E: InterruptX &H10, INreg, OUTreg ' CHR$(14)
INreg.ax = &HE5B: InterruptX &H10, INreg, OUTreg ' "["
FOR i = 1 TO LEN(TxCmd$)
  INreg.ax = &HE00 + ASC(MID$(TxCmd$, i, 1))
  InterruptX &H10, INreg, OUTreg
NEXT
INreg.ax = &HE5D: InterruptX &H10, INreg, OUTreg ' "]"
END SUB

SUB InterruptX (IntNo%, InRegs AS RegTypeX, OutRegs AS RegTypeX)
P1% = -1       ' 未被调用 的参数请赋值为 -1
OfsAddr% = VARPTR(intrpt%(0))
DEF SEG = VARSEG(intrpt%(0))
'CALL Absolute(     IntNo%, INreg, OUTreg, OfsAddr%)
'原CALL InterruptX (IntNo%, INreg, OUTreg)
CALL ABSOLUTE(P1%, IntNo%, INreg, OUTreg, OfsAddr%)
DEF SEG
END SUB

SUB Mouse (aax%, bbx%, ccx%, ddx%)
INreg.ax% = aax%
INreg.BX% = bbx%
INreg.CX% = ccx%
INreg.DX% = ddx%
InterruptX &H33, INreg, OUTreg
aax% = OUTreg.ax%
bbx% = OUTreg.BX%
ccx% = OUTreg.CX%
ddx% = OUTreg.DX%
END SUB

FUNCTION SADDr% (SSEGm%, s$)
SSEGm% = CVI(CHR$(PEEK(0)) + CHR$(PEEK(1)))
DEF SEG = VARSEG(s$)
ofs% = VARPTR(s$)
sad% = CVI(CHR$(PEEK(ofs% + 2)) + CHR$(PEEK(ofs% + 3)))
SADDr% = sad%
IF sad% < 0 THEN SADDr% = 32767 + sad%
DEF SEG
END FUNCTION

[ Last edited by 本是 on 2009-7-7 at 04:56 ]



my major is english----my love is dos----my teacher is the buddha----my friends--how about U
2009-7-7 04:51
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
xugaohui
高级用户




积分 774
发帖 293
注册 2003-4-16
来自 湖北仙桃
状态 离线
『第 2 楼』:  

太高深了,但一定要收藏的。



下载
09年7月7日 更新
感谢网友 囧HQY 提供空间
2009-7-7 05:54
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复

请注意:您目前尚未注册或登录,请您注册登录以使用论坛的各项功能,例如发表和回复帖子等。


可打印版本 | 推荐给朋友 | 订阅主题 | 收藏主题



论坛跳转: