生成一个随机的 32 位数字存储在 64 位寄存器中
Generate a random 32-bit number to store in a 64-bit register
我想生成一个随机的 32 位数字。我为此使用 rdrand
。但是,我遇到了一些问题。由于数字不能超过 32 位,所以我做的是 rdrand eax
。问题出在这里:
我需要能够在 64 位寄存器中引用这个 32 位数字,因为我的代码库的其余部分使用 64 位寄存器。我想我可以用 xor
清除 rax
到它自己,然后只用 rdrand eax
加载它的一半。那我可以看看rax
,一半最多32位,另一半清零
当我将 rax
与最大 32 位数字大小 2147483647 进行比较时,我得到的结果非常不一致。一半时间,退出代码为 1,这意味着 rax
中的数字实际上小于 32 位。但另一半时间我得到 0。这几乎就像 eax
中的结果并不总是小于或等于 2147483647,考虑到 [=20],这是出乎意料的=] 文档说。
有谁知道我的思维过程出了什么问题?我很想知道。 (注意:我在 macOS 上使用 Clang 进行组装。)
.global _main
.text
# how to generate a 32-bit random number that is in rax?
_main:
xor rax, rax # clear the top half of the eax-rax register pair
rdrand eax # a 32-bit number in rax
cmp rax, 2147483647
jle smaller_than_32 # rax <= MAX_32_BIT
xor rdi, rdi
jmp end
smaller_than_32:
mov rdi, 1
end:
mov rax, 0x2000001
syscall
2147483647
,或等效地,0x7FFFFFFF
,是最大的 signed 32 位数字。 rdrand eax
可以在eax
中放入从0x00000000
到0xFFFFFFFF
的任何值。对于如何处理此问题,您有几种选择:
- 与
4294967295
比较,或等价于0xFFFFFFFF
,最大无符号 32位数字,而不是。
- 做
cmp eax, 2147483647
而不是 cmp rax, 2147483647
。由于 jle
对比较有符号整数的结果进行操作,这将导致您现在看到的 2147483648
到 4294967295
被解释为 -2147483648
到 -1
.
- 不是让
rax
的高 32 位始终为零,而是让它们匹配 eax
的符号位(这被称为 符号扩展).您可以通过在 rdrand eax
之后立即执行 movsx rax, eax
来做到这一点。这将导致 rax
保持 -2147483648
和 2147483647
之间的值,而不是 0
和 4294967295
之间的值。
如您所料,任何这些更改都会导致您的条件跳转始终被采用。如果您希望 rax
最终介于 0
和 4294967295
之间,请选择选项 1 或 2。如果您希望 rax
最终介于 -2147483648
之间和 2147483647
,然后选择选项 3。
我想生成一个随机的 32 位数字。我为此使用 rdrand
。但是,我遇到了一些问题。由于数字不能超过 32 位,所以我做的是 rdrand eax
。问题出在这里:
我需要能够在 64 位寄存器中引用这个 32 位数字,因为我的代码库的其余部分使用 64 位寄存器。我想我可以用
xor
清除rax
到它自己,然后只用rdrand eax
加载它的一半。那我可以看看rax
,一半最多32位,另一半清零当我将
rax
与最大 32 位数字大小 2147483647 进行比较时,我得到的结果非常不一致。一半时间,退出代码为 1,这意味着rax
中的数字实际上小于 32 位。但另一半时间我得到 0。这几乎就像eax
中的结果并不总是小于或等于 2147483647,考虑到 [=20],这是出乎意料的=] 文档说。
有谁知道我的思维过程出了什么问题?我很想知道。 (注意:我在 macOS 上使用 Clang 进行组装。)
.global _main
.text
# how to generate a 32-bit random number that is in rax?
_main:
xor rax, rax # clear the top half of the eax-rax register pair
rdrand eax # a 32-bit number in rax
cmp rax, 2147483647
jle smaller_than_32 # rax <= MAX_32_BIT
xor rdi, rdi
jmp end
smaller_than_32:
mov rdi, 1
end:
mov rax, 0x2000001
syscall
2147483647
,或等效地,0x7FFFFFFF
,是最大的 signed 32 位数字。 rdrand eax
可以在eax
中放入从0x00000000
到0xFFFFFFFF
的任何值。对于如何处理此问题,您有几种选择:
- 与
4294967295
比较,或等价于0xFFFFFFFF
,最大无符号 32位数字,而不是。 - 做
cmp eax, 2147483647
而不是cmp rax, 2147483647
。由于jle
对比较有符号整数的结果进行操作,这将导致您现在看到的2147483648
到4294967295
被解释为-2147483648
到-1
. - 不是让
rax
的高 32 位始终为零,而是让它们匹配eax
的符号位(这被称为 符号扩展).您可以通过在rdrand eax
之后立即执行movsx rax, eax
来做到这一点。这将导致rax
保持-2147483648
和2147483647
之间的值,而不是0
和4294967295
之间的值。
如您所料,任何这些更改都会导致您的条件跳转始终被采用。如果您希望 rax
最终介于 0
和 4294967295
之间,请选择选项 1 或 2。如果您希望 rax
最终介于 -2147483648
之间和 2147483647
,然后选择选项 3。