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 can hold 的最大值是十进制的 7FFFFFFF 或 2147483647 那么我应该如何解决这个问题呢?即使我使用单一数据类型,它也总是返回没有无符号数字的负数。

根据 MSDN Long 类型

长(长整数)变量存储为带符号的 32 位(4 字节)数字,值范围从 -2,147,483,648 到 2,147,483,647。Long 的类型声明字符是和号 (&)。

但是 FFFFFFFF 的值等于 -1 或 4294967294 溢出。

我想我对此感到困惑。

编辑:

由于这似乎有点复杂,我编写了一个小的 Shell 代码来使用 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

问题是VB6将任何仅从“F”退出的十六进制数转换为-1

这将使您的函数使用 -1 作为其上限,并使其返回 0

通过将 8 位数字分成 2 个具有 4 位数字的变量,您仍然会遇到同样的问题,因为 VB6 仍会将 &HFFFF 转换为 -1,这将使您的函数再次返回 0。

一种解决方案是在转换前将 &H10000 添加到 4 位变量,并在转换完成后减去 Val("&H10000")。

之后,您可以使用这 2 个值获得 2 个随机数,并将它们组合成 1 个随机的 8 位十六进制数。

下面是一个测试项目,它显示了我的意思:

'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 回答
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函数时,您将 0 传递给 Lowerbound,将 -1 传递给 Upperbound

为了在 Vb.NET 中解决此问题,请使用&HFFFFFFFFL&HFFFFFFFF&表示 Long 类型文字。从上面的示例中,我不确定如何在 VB6 中像在 VB.NET 中一样快速地解决这个问题。我想你需要编写自己的函数来将大的 HEX 数字转换为 double 并传递数字而不是 HEX。

编辑:我认为 VB6 不允许您转换&HFFFFFFFF为基数 16 以外的任何值,它会溢出并导致 -1:

编辑 2:您可以通过添加&到末尾将一些十六进制数字转换为其他数据类型:

&HFFFF = -1
&HFFFF& = 65535

尽管如此,VB6 中的十六进制数似乎还是有限制的(仅基数 16?),因为:

VB.NET:
&HFFFFFFFF&=4294967295

VB6:
&HFFFFFFFF&=-1

MSDN:键入字符(Visual Basic)

编译器通常将整数文字解释为十进制(以 10 为基数)数字系统。您可以使用 &H 前缀将整数文字强制为十六进制(以 16 为基数),并且可以使用 &O 前缀将其强制为八进制(以 8 为基数)。前缀后面的数字必须适合数字系统。

于 2013-05-01T19:47:47.323 回答
0

Rnd只会给你 24 位随机性,因为它返回一个Single.

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

将从两个 16 位随机整数构造一个 32 位值。

更新 - 好吧,它不会,因为正如 Hrqls 指出的那样,&HFFFF-1在 VB 中。反而:

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