2

32 ビットの 16 進数 (例: CEED6644) を 4 バイト (var1 = CE、var2 = ED、var3 = 66、var4 = 44) に分割する方法を教えてください。QB64 または QBasic で。これを使用して、複数のデータ バイトを 1 つの配列アドレスに格納します。このようなもの:

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"

等々...

4

2 に答える 2

2

これを行うには、整数除算 ( \) とビットごとの AND ( 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 のような実装には、orの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++ の動作に依存して高すぎるシフト カウントを本質的に無視するのではなく、シフト カウントが高すぎるときに C++ コードから QB64 エラーを発生させることができる可能性があります。残念ながら、これは当てはまりません。実際には、必要以上に多くの問題を引き起こす可能性があります。

于 2016-08-05T05:13:59.513 に答える
0

このスニップは、16 進数値のバイト ペアを取得します。

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)
于 2016-08-08T19:46:39.540 に答える