1

Visual Basic 6.0 で 0 から &HFFFFFFFF までの乱数を生成する方法はありますか?

私は次の機能を使用しています

Function RandomNumberLong(Lowerbound As Long, Upperbound As Long) As Long
    RandomNumberLong = Clng((Upperbound - Lowerbound + 1) * Rnd + Lowerbound)
End Function

私が使用する場合

x = RandomNumberLong(0,&HFFFFFFFF)

常に 0 を返します

ここでの問題は、保持できる long の最大値が 7FFFFFFF または 10 進数で 2147483647 であることです。単一のデータ型を使用しても、符号なしの数値なしで常に負を返します。

MSDNのロングタイプによると

long (long integer) 変数は、値が -2,147,483,648 ~ 2,147,483,647 の範囲の符号付き 32 ビット (4 バイト) 数値として格納されます。Long の型宣言文字はアンパサンド (&) です。

しかし、FFFFFFFF の値は -1 または 4294967294 に等しく、オーバーフローします。

私はこれについて混乱していると思います。

編集:

これは少し複雑に思えるので、代わりに RDTSC 命令を使用して、符号付きおよび符号なしを含む長い乱数を生成するように、小さなシェル コードをコーディングしました。

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _ 
(Destination As Any, Source As Any, ByVal Length As Long)

Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" _ 
(ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long

Option Explicit

 Private Sub Form_Load()
 Dim x(1 To 10) As Byte, VAL As Long

    CopyMemory x(1), &H60, 1 'PUSHAD
    CopyMemory x(2), &H310F, 2 'RDTSC EAX holds a random value

    CopyMemory x(4), &HA3, 1 'MOV EAX
    CopyMemory x(5), VarPtr(VAL), 4 'Pointer of variable // MOV DWORD [VAL],EAX 

    CopyMemory x(9), &H61, 1 'POPAD
    CopyMemory x(10), &HC3, 1 'RET
    CallWindowProc VarPtr(x(1)), 0, 0, 0, 0 'Call the shellcode

    MsgBox VAL
    End Sub
4

4 に答える 4

1

実は、VB6Longは 32 ビットの符号付き整数データ型です。そのため、単純に保存できません&HFFFFFFFFMSDN)。しかし、(1)Longとにかく使用しても問題ないように見え、(2)ユースケースが何であるかを説明せず、プラスの範囲でのみ動作することが本当に重要であるかどうかを説明していません.

次の関数を使用してLong、データ型の全範囲Long(つまり from-&H80000000から&H7FFFFFFF)からランダムな値を生成できます。

Function RandomNumberLong() As Long
    RandomNumberLong = &H7FFFFFFF * Rnd() + (-1 - &H7FFFFFFF) * Rnd()
End Function
于 2013-05-01T22:48:19.903 に答える
1

&HFFFFFFFF- は 32 ビットの符号付き整数を表し、 の値は&HFFFFFFFF整数をオーバーフローして次のようになり-1 ます。したがって、RandomNumberLong関数を呼び出すときは、Lowerbound に 0 を渡し、Upperbound に -1 を渡します。

Vb.NET でこれを修正するには、 or を使用&HFFFFFFFFL&HFFFFFFFF&て Long 型リテラルを示します。上記の例のVB.NETと同じように、VB6でこれをすばやく修正する方法がわかりません。大きな HEX 数値を double に変換し、HEX の代わりに数値を渡すには、独自の関数を作成する必要があると思います。

&HFFFFFFFF編集: VB6 では、オーバーフローして -1 になる base 16 以外に変換することはできないと思います:

&編集 2:最後に追加することで、一部の 16 進数を他のデータ型に変換できます。

&HFFFF = -1
&HFFFF& = 65535

それでも、VB6 の 16 進数には制限があるようです (基数 16 のみ?)。

VB.NET:
&HFFFFFFFF&=4294967295

VB6:
&HFFFFFFFF&=-1

MSDN: タイプ文字 (Visual Basic)

コンパイラは通常、整数リテラルを 10 進数 (基数 10) の数値システムであると解釈します。&H プレフィックスを使用して整数リテラルを強制的に 16 進数 (基数 16) にすることができ、&O プレフィックスを使用して強制的に 8 進数 (基数 8) にすることができます。プレフィックスに続く数字は、番号システムに適している必要があります。

于 2013-05-01T19:47:47.323 に答える
1

問題は、VB6 が "F" だけで終了する 16 進数を -1 に変換することです。

これにより、関数は上限として -1 を使用し、0 を返します。

8 桁を 4 桁の 2 つの変数に分けることで、VB6 が &HFFFF を -1 に変換し、関数が再び 0 を返すという同じ問題が発生します。

解決策は、変換前に 4 桁の変数に &H10000 を加算し、変換後に Val("&H10000") を減算することです。

その後、これら 2 つの値を使用して 2 つの乱数を取得し、それらを組み合わせて 1 つのランダムな 8 桁の 16 進数にすることができます。

以下は、私が何を意味するかを示すテストプロジェクトです。

'1 form with:
'  1 command button: name=Command1
Option Explicit

Private Sub Command1_Click()
  Dim strX As String
  Dim lngX As Long
  strX = RndHex("FFFFFFFF")
  lngX = Val("&H" & strX)
  Caption = strX & " = " & CStr(Hex$(lngX)) & " = " & CStr(lngX)
End Sub

Function RndHex(strMax As String) As String
  Dim strMax1 As String, strMax2 As String
  Dim lngMax1 As Long, lngMax2 As Long
  Dim lngVal1 As Long, lngVal2 As Long
  Dim strVal1 As String, strVal2 As String
  'make sure max is 8 digits
  strMax1 = Right$("00000000" & strMax, 8)
  'split max in 2 parts
  strMax2 = Right$(strMax1, 4)
  strMax1 = Left$(strMax1, 4)
  'convert max values from string to values
  lngMax1 = Val("&H1" & strMax1) - Val("&H10000")
  lngMax2 = Val("&H1" & strMax2) - Val("&H10000")
  'calculate separate random values
  lngVal1 = CLng(lngMax1 + 1) * Rnd
  lngVal2 = CLng(lngMax2 + 1) * Rnd
  'convert values to 4 digit hex strings
  strVal1 = Right$("0000" & Hex$(lngVal1), 4)
  strVal2 = Right$("0000" & Hex$(lngVal2), 4)
  'combine 2 random values and return the result as an 8 digit hex string
  RndHex = strVal1 & strVal2
End Function

Private Sub Form_Load()
  'seed random generator with system timer
  Randomize
End Sub

上記のプロジェクトを実行し、コマンド ボタンをクリックして、フォームのキャプションに値を表示します。

于 2013-05-02T07:26:59.427 に答える
0

Rndを返すため、24 ビットのランダム性しか得られませんSingle

 RandomNumberLong = Clng(&HFFFF * Rnd()) + (Clng(&HFFFF * Rnd()) * &H10000)

2 つの 16 ビット ランダム整数から 32 ビット値を構築します。

更新 - Hrqls が指摘しているように、VB にあるため、そうではありませ&HFFFF-1。その代わり:

 RandomNumberLong = Clng(65535 * Rnd()) + (Clng(65535 * Rnd()) * 65536)
于 2013-05-01T18:53:02.173 に答える