将 32 位十六进制值分解为 4 个字节 [QB64]

Break up 32-bit hex value into 4 bytes [QB64]

我想问一下,如何将一个32位的十六进制(例如:CEED6644)分解成4个字节(var1 = CE, var2 = ED, var3 = 66, var4 = 44)。在 QB64 或 QBasic 中。我会用它来将几个数据字节存储到一个数组地址中。 像这样:

DIM Array(&HFFFF&) AS _UNSIGNED LONG
Array(&HAA00&) = &HCEED6644&
addr = &HAA00&
SUB PrintChar
SHARED addr

IF var1 = &HAA& THEN PRINT "A"
IF var1 = &HBB& THEN PRINT "B"
IF var1 = &HCC& THEN PRINT "C"
IF var1 = &HDD& THEN PRINT "D"
IF var1 = &HEE& THEN PRINT "E"
IF var1 = &HFF& THEN PRINT "F"
IF var1 = &H00& THEN PRINT "G"
IF var1 = &H11& THEN PRINT "H"

等等...

您可以使用整数除法 (\) 和按位与 (AND) 来完成此操作。

DIM x(0 TO 3) AS _UNSIGNED _BYTE
a& = &HCEED6644&
x(0) = (a& AND &HFF000000&) \ 2^24
x(1) = (a& AND &H00FF0000&) \ 2^16
x(2) = (a& AND &H0000FF00&) \ 2^8
x(3) = a& AND &HFF&
PRINT HEX$(x(0)); HEX$(x(1)); HEX$(x(2)); HEX$(x(3))

请注意,您也可以使用通用 RShift~& 函数代替原始整数除法,因为您真正要做的是移位:

x(0) = RShift~&(a& AND &HFF000000&, 18)
...

FUNCTION RShift~& (value AS _UNSIGNED LONG, shiftCount AS _UNSIGNED BYTE)
    ' Raise illegal function call if the shift count is greater than the width of the type.
    ' If shiftCount is not _UNSIGNED, then you must also check that it isn't less than 0.
    IF shiftCount > 32 THEN ERROR 5
    RShift~& = value / 2^shiftCount
END FUNCTION

在此基础上,您可以创建另一个函数:

FUNCTION ByteAt~%% (value AS _UNSIGNED LONG, position AS _UNSIGNED BYTE)
    'position must be in the range [0, 3].
    IF (position AND 3) <> position THEN ERROR 5
    ByteAt~%% = RShift~&(value AND LShift~&(&HFF&, 8*position), 8*position)
END FUNCTION

请注意,使用了 LShift~& 函数将位向左移动(乘以 2 的幂)。一个可能更好的替代方案是先执行右移,然后只屏蔽低 8 位,从而不需要 LShift~&:

FUNCTION ByteAt~%% (value AS _UNSIGNED LONG, position AS _UNSIGNED BYTE)
    'position must be in the range [0, 3].
    IF (position AND 3) <> position THEN ERROR 5
    ByteAt~%% = RShift~&(value, 8*position) AND 255
END FUNCTION

顺便说一下,另一个名为 FreeBASIC 的类似 QB 的实现有一个实际的 SHR 运算符,像 MODAND 一样使用来直接执行移位操作而不是使用除法,这可能更快。

您还可以使用 QB64 的 DECLARE LIBRARY 功能在 C++ 中创建将执行移位操作的函数:

/*
 * Place in a separate "shift.h" file or something.
 */
unsigned int LShift (unsigned int n, unsigned char count)
{
    return n << count;
}

unsigned int RShift (unsigned int n, unsigned char count)
{
    return n >> count;
}

这是完整的对应 QB64 代码:

DECLARE LIBRARY "shift"
    FUNCTION LShift~& (value AS _UNSIGNED LONG, shiftCount AS _UNSIGNED _BYTE)
    FUNCTION RShift~& (value AS _UNSIGNED LONG, shiftCount AS _UNSIGNED _BYTE)
END DECLARE

x(0) = ByteAt~%%(a&, 0)
x(1) = ByteAt~%%(a&, 1)
x(2) = ByteAt~%%(a&, 2)
x(3) = ByteAt~%%(a&, 3)
END

FUNCTION ByteAt~%% (value AS _UNSIGNED LONG, position AS _UNSIGNED BYTE)
    'position must be in the range [0, 3].
    IF (position AND 3) <> position THEN ERROR 5
    ByteAt~%% = RShift~&(value, 8*position) AND 255
END FUNCTION

如果 QB64 有记录 API,当移位计数太高时,可能会从 C++ 代码中引发 QB64 错误,而不是依赖 C++ 的行为来基本上忽略移位计数那太高了。不幸的是,情况并非如此,它实际上可能会导致比其价值更多的问题。

此片段获取十六进制值的字节对:

DIM Value AS _UNSIGNED LONG
Value = &HCEED6644&
S$ = RIGHT$("00000000" + HEX$(Value), 8)
PRINT "Byte#1: "; MID$(S$, 1, 2)
PRINT "Byte#2: "; MID$(S$, 3, 2)
PRINT "Byte#3: "; MID$(S$, 5, 2)
PRINT "Byte#4: "; MID$(S$, 7, 2)