PowerBasic与C做长整形数据参数传递时,堆栈的处理技巧。

前言:

      函数的参数是通过堆栈来处理的,32位系统一般是在EBP寄存器做增减的。长整形的偏移量为8个字节。如果汇编去访问函数参数变量则可以使用dword ptr [ebp+8]、dword ptr [ebp+16]这样的形式来访问。这里就不探讨汇编的了。

探讨:

       如果要用C编写一个函数,提供给Pb的程序使用(参数为一个正的长整形数据,返回值也为一个正长整形),那么PB中如何定义和正确传递参数和返回值呢?

      显然如果是一个长整形(64位)的传递则没有什么可说的,直接使用PB提供的QUAD数据类型作为传递及接收类型。但是传递正的长整形由于和带符号的长整型取值范围不同,使用QUAD变量类型则不是安全的了,可能会得到一个非正确的值。

说明:

举例:C代码

Ulong ComputePacket(Ulong a)
{
   Ulong b = 0;
   b = a + 147463586973328;
   return b;
}

将上面这个函数生成DLL后,提供给PB调用。我们看到C原型中参数定义为一个8字节Ulong型变量,取值范围位2^64。函数运行后将在堆栈上申请一个8字节的空间用于存放参数变量。由于参数变量类型指定为Ulong型,C编译器则会按0~2^64这个数值范围运算。而PB编译器确是按-2^63~0~2^63-1这个取值范围处理。显然在数值超范围传递过程中存在溢出问题。

那么如何确保参数传递安全了?

下面PB实例说明:

//============================================================
// 不安全的函数声明
//============================================================
DECLARE FUNCTION ComputePacket LIB "TEST.dll" ALIAS 
                 "ComputePacket@8" (BYVAL Data1 AS QUAD)

//虽然也是在堆栈申请8字节空间,并压入Data1的数据,但是由于QUAD的取值范围问题
//可能出现数据边界溢出的风险。

上面演示用PB引用函数声明,虽然也是在堆栈申请8字节,并压入Data1的数据,但是由于QUAD的取值范围问题可能出现数据边界溢出的风险。

由于C系统的ULong型位正数8字节,在PB32位系统虽然没有类型定义,但是也可以用两个DWORD字形数据替代,两个DWORD正好也是8字节,且PB编译器会按两个0~2^32来处理,正好代表了Ulong型的高位和低位值。

安全函数声明如下:

//============================================================
// 安全的函数声明
//============================================================
DECLARE FUNCTION ComputePacket LIB "TEST.dll" ALIAS 
                 "ComputePacket@8" (BYVAL bHigh AS DWORD, BYVAL bLow AS DWORD) AS DWORD

//在函数过程堆栈顶部申请两个4字节空间,分别压入bHigh和bLow的数据, 返回值用DWORD型接收地址。
//不要用QUAD去接收值(不安全)


同理用其他兼容64位的编程系统生成的DLL,做参数传递的过程时也可以如上声明。

总结:

最后用FreeBasic做为函数提供方,编写原型返回值不要用Ulongint,而要注意PB32位的数值类型,应该传递地址提供给PB访问。

// 参数Data1堆栈申请8字节。
// 返回参数Uinteger等价于PB的Dword型,用于接收数据地址。
// 不要用Ulongint型作为返回类型

Function ComputePacketKey(ByVal Data1 As Ulongint) As Uinteger Export
   Dim b As Ulongint = 0
   b = Data1 + 53487329187932
   Function = Cast(Uinteger, VarPtr(b))
End Function

PB引用函数如下:

// 将84563247289342代入函数用于计算

Type Uint64
  low  As Dword
  high As Dword
End Type

Local pBuf As Uint64 Ptr

pBuf = ComputePacketKey( 84563247289342\(2^32), (84563247289342 And &HFFFFFFFF) )


// 返回值

@pBuf.high*(2^32) + @pBuf.low

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值