1、在日常PB编程中,大家都会体会到其内置的位移函数(SHIFT LEFT / SHIFT RIGHT),没有返回值。这个给编程带来了不便。其实我们可以通过宏定义去实现位左、右移的功能。
MACRO shift_left (a,b) = (a*(2^b))
MACRO shift_right(a,b) = (a\(2^b))
2、PB编译器支持8位,32位及64位数据类型,但是却不支持无符号长型(ULONG/Uint64)这样的类型数据。只支持64位的QUAD有符号长型,长度为8字节。取值范围-2^63 to 2^63 -1,而无符号长型的取值范围是2^64,那么是否可以在32位PB下进行长整形数据运算呢?在查看了网上一些资料后,在PB下做了如下尝试,供喜好PB编程借鉴。
自定义UQUAD数据类型
TYPE UQUAD DWORD '4字节对齐 64位 8字节 整形
high AS DWORD
low AS DWORD
END TYPE
整数形任意类型数字转换为长型函数:
SUB IntToUint64(BYVAL a AS VARIANT, b AS UQUAD)
LOCAL high_a,low_a,high_b,low_b AS DWORD
b.high = 0
b.low = 0
SELECT CASE VARIANTVT(a)
CASE %VT_I8
b.high = HI(DWORD,VARIANT#(a))
b.low = LO(DWORD,VARIANT#(a))
CASE %VT_UI1,%VT_UI2,%VT_UI4,%VT_BOOL
IF VARIANT#(a)>0 THEN ' 正数时处理方法
b.high = 0
b.low = VARIANT#(a)
ELSE '负数时处理方法
! mov eax, a
! cdq
! mov high_b, eax
! mov low_b, edx
b.high = high_b
b.low = low_b
END IF
CASE ELSE
b.high = 0
b.low = 0
END SELECT
END SUB
64位整数型加法函数:
SUB Uint64_Add(BYVAL a AS UQUAD, BYVAL b AS UQUAD, c AS UQUAD)
LOCAL high_a, low_a, high_b, low_b, high_c, low_c AS DWORD
high_a = a.high : low_a = a.low
high_b = b.high : low_b = b.low
! mov eax, high_a
! mov edx, low_a
! add eax, high_b
! adc edx, low_b
! mov high_c, eax
! mov low_c, edx
c.high = high_c
c.low = low_c
END SUB
64位整数型减法函数:
SUB Uint64_Sub(BYVAL a AS UQUAD, BYVAL b AS UQUAD, c AS UQUAD)
LOCAL high_a, low_a, high_b, low_b, high_c, low_c AS DWORD
high_a = a.high : low_a = a.low
high_b = b.high : low_b = b.low
! mov eax, high_a
! mov edx, low_a
! sub eax, high_b
! sbb edx, low_b
! mov high_c, eax
! mov low_c, edx
c.high = high_c
c.low = low_c
END SUB
64位整形数据的位移两个函数:
SUB Uint64_ShiftRight(BYVAL a AS UQUAD, BYVAL n AS DWORD, b AS UQUAD)
LOCAL high_a, low_a, high_b, low_b AS DWORD
high_a = a.high : low_a = a.low
! mov eax, low_a
! mov edx, high_a
! mov cl, n
! shrd eax, edx, cl
! shr edx, cl
! mov low_b, eax
! mov high_b, edx
b.high = high_b
b.low = low_b
END SUB
SUB Uint64_ShiftLeft(BYVAL a AS UQUAD, BYVAL n AS DWORD, b AS UQUAD)
LOCAL high_a, low_a, high_b, low_b AS DWORD
high_a = a.high : low_a = a.low
! mov eax, low_a
! mov edx, high_a
! mov cl, n
! shld eax, edx, cl
! shr edx, cl
! mov low_b, eax
! mov high_b, edx
b.high = high_b
b.low = low_b
END SUB
4字节Long有符号长型转8字节ULONG无符号长型:
SUB LongToUint64(BYVAL a AS LONG, b AS UQUAD)
LOCAL high_b, low_b AS DWORD
! mov eax, a
! cdq
! mov high_b, eax
! mov low_b, edx
b.high = high_b
b.low = low_b
END SUB