回 帖 发 新 帖 刷新版面

主题:[讨论]关于QB调用汇编的参数传递(拙见,请大家指正)

例如:调用汇编取得系统的日期(月、日)
CALL ABSOLUTE (X,Y,ASMPROGRAM())
我想应该是把X,Y这两个在QB中定义过的变量的地址先压入堆栈,而BP这个寄存器因为在执行完汇编代码之后要用它来寻址而传递参数,所以在汇编代码的最开头我们要自己把BP入栈,并且在转到汇编子程序时系统自动把QB主程序的CS:IP入栈,这样的话当汇编子程序刚执行完PUSH BP后堆栈的内容应该是:
……(堆栈内先前的内容,省略),X,Y(我们定义的变量,保存汇编子程序传递的数值用),CS,IP,BP。
而汇编语言返回的值一般都在寄存器中,这样就要求我们在汇编子程序中把寄存器中的值存到X,Y变量的地址中,这样才能返回月,日(我所举的例子中)怎么返回呢?
还是在这个例子中说,当汇编子程序执行完中断之后,月保存在DH寄存器中,日保存在DL寄存器中。
在把X,Y压入堆栈后又压入CS,IP,BP分别占两个字节一共六个字节,所以当我们编写的汇编代码的先头和最后应该这样写:
PUSH BP(BP入栈,保存BP,刚才提到过)
MOV BP,SP(把栈顶地址传到BP寄存器中,SP指向栈顶是固定的,不能用来寻址)
…………(省略号代表中间自己写的汇编代码,省略号以上是汇编子程序的开头部分,以下是汇编子程序的结束部分)
MOV BX,[BP+6](本句的意思是把Y变量的地址传送到基址寄存器BX中,刚才提到过MOV BP,SP后BP指向的就是栈顶,[BP+6]里面存放的就是我们定义的Y变量的地址,注意一点堆栈是由高地址向低地址发展的,所以先入栈的要比后入栈的地址高,而Y入栈之后又有CS,IP,BP入栈一共六个字节,所以Y的地址就是栈顶地址加6)
MOV [BX],DH(因为BX存放的是Y的地址,所以[BX]即是Y,此句意思是把DH(月)放入Y中
MOV BX,[BP+8](此句和MOV BX,[BP+6]一样,因为X比Y更早入栈所以要加8,我试过加7,但是结果不正确,我想是因为QB中X,Y定义的时候分别占两个字节吧)
MOV [BX],DL(把日期放到X变量的地址中,即:X=日期)
POP BP(刚才把BP入栈了,现在把它出栈,要不会出错的)
RET 2(返回QB主程序时把CS,IP出栈)
最后在QB中PRINT X,Y就输出日期和月份了
同理,想返回更多的参数可以以此类推
昨天研究时的一点想法,有错误的话请高手们定告诉我!谢谢大家。

回复列表 (共9个回复)

沙发

昨天研究时的一点想法,有错误的话请高手们一定告诉我!谢谢大家。

板凳

具体操作请参考HELP关于call absolute的说明
关于数据类型你可以看一下HELP里的说明
寄存器一般是分高低字节,按照长度类型值配对调入读出就是了.
节选 :

'The following example uses the Absolute routine to execute a
'machine-language program stored in an array. The program prints a
'message indicating whether or not a math coprocessor is installed.

'Note: To use the Absolute routine, you must load the Quick library
'QBX.QLB using the /L switch when you begin QBX.

'AsmBytes is a label; nASMBYTES is a symbolic constant.
CONST nASMBYTES = 14
DEFINT A-Z
DIM AsmProg(1 TO (nASMBYTES / 2))

'The machine-language program stored as data to read into the array.
AsmBytes:
DATA &H55              : 'PUSH BP        Save base pointer.
DATA &H8B, &HEC        : 'MOV  BP,SP     Get our own.
DATA &HCD, &H11        : 'INT  11H       Make the ROM-BIOS call.
DATA &H8B, &H5E, &H06  : 'MOV  BX,[BP+6] Get argument address.
DATA &H89, &H07        : 'MOV  [BX],AX   Save list in argument.
DATA &H5D              : 'POP  BP        Restore base pointer.
DATA &HCA, &H02, &H00  : 'RET  2         Pop argument off stack
                         '               and make far return.
'Get the starting offset of the array.
P = VARPTR(AsmProg(1))
'Poke the machine-language program into the array.
DEF SEG = VARSEG(AsmProg(1))   'Change the segment.
FOR I = 0 TO nASMBYTES - 1
   READ J
   POKE (P + I), J
NEXT I

'Execute the program. The program expects a single integer argument.
CALL Absolute(X%, VARPTR(AsmProg(1)))
DEF SEG   ' Restore the segment.
'X% now contains bit-encoded equipment list returned by DOS.
'Mask off all but the coprocessor bit (bit 2).
CoProcessor = X% AND &H2
'Print the appropriate message.
IF CoProcessor = 2 THEN
    PRINT "Math coprocessor present."
ELSE
    PRINT "No math coprocessor."
END IF
END

3 楼

首先谢谢MOZ
你发的程序我看到了,在编辑窗口输入ABSOLUTE之后右击,在EXAMPLE里,我就是基于它研究如何嵌入汇编的,因为在网上详细介绍的较少,我只能依靠这个程序一点点想。我所说的是如何把汇编子程序返回的值传到QB中(比如月,日)的方法或者可以说原理,你说的帮助我也看了DETAIL,我想我也应该算是有一点英语基础吧,但是看这些东西还是有些头疼,更何况那些英语基础稍差的QB爱好者呢,呵呵,不好意思。MOZ是高手,我很折服,希望你帮我找一找我所说的错误的地方,使我更加进步,谢谢!

4 楼

不好意思,很惭愧,我不是高手,我对英语也不擅长,至于汇编,我实在没时间与精力去学习这些低层的东西了。很抱歉帮不上忙。

5 楼

呵呵,MOZ太谦虚了,从你的代码里我能看出来你是一个高手,我很佩服。我想如果用QB编个小软件的话(当然解决个数学问题除外,什么鸡免同笼啊、猴子摘桃啊等等,呵呵)掌握一些汇编还是有必要的,从你QB这么高的造诣来看你对汇编也应该很精通,以后还要多指教啊,呵呵

6 楼

想要用QB调用系统功能,参考中断资料就可以了.
我从来不用汇编,也不懂,总记不住那些指令,
至于抬举我的,不过是这些分数,都是我当副版主的权利自己给自己加的,
并不能表现我的多少造诣.实在是惭愧.

我用QB普遍用于文件处理数据处理和一些显示的交互(当然是DOS机了)
还有这里很多很多的试卷问题,所以并没有学习汇编的迫切欲望.

7 楼

MOZ此言差矣
之所以说挺佩服你不是因为你的分数,看过你回答别人的几个问题,可以说QB用得应该是炉火纯青了,呵呵,既然这样大家以后一起研究吧。

8 楼

呵呵

你们两个家伙就互相吹捧吧。。。吹吧....

看。天上一头quickbasic画的牛

9 楼

哈哈哈哈,那我就此打住了,不过我确实觉得MOZ水平确实不错。

我来回复

您尚未登录,请登录后再回复。点此登录或注册