[英]Generate a random 32-bit number to store in a 64-bit register
I want to generate a random 32-bit number.我想生成一个随机的 32 位数字。 I am using
rdrand
for this.我正在为此使用
rdrand
。 However, I am having some problems.但是,我遇到了一些问题。 Since the number can be no more than 32 bits large, I am doing
rdrand eax
.由于数字不能超过 32 位,我正在执行
rdrand eax
。 Here is where the problem arises:这是出现问题的地方:
I need to be able to refer to this 32-bit number in a 64-bit register since the rest of my codebase uses 64-bit registers.我需要能够在 64 位寄存器中引用这个 32 位数字,因为我的代码库的其余部分使用 64 位寄存器。 I figured that I could clear
rax
with a xor
to itself, and then only load half of it with rdrand eax
.我想我可以用自己的
xor
来清除rax
,然后只用rdrand eax
加载它的一半。 Then I could look at rax
, have one half be at most a 32-bit number, and the other half be cleared.然后我可以查看
rax
,其中一半最多是 32 位数字,另一半被清除。
When I compare rax
with the maximum 32-bit number size, 2147483647 , I get very inconsistent results.当我将
rax
与最大 32 位数字大小2147483647 进行比较时,我得到的结果非常不一致。 Half of the time, the exit code is 1, meaning that the number in rax
is, in fact, smaller than 32-bits.一半的时间,退出代码是 1,这意味着
rax
中的数字实际上小于 32 位。 But the other half of the time I get 0. It's almost like the result in eax
is not always less than or equal to 2147483647 , which is unexpected given what this documentation says.但另一半时间我得到 0。这几乎就像
eax
的结果并不总是小于或等于2147483647 ,鉴于此文档所说,这是出乎意料的。
Does anyone know what is going wrong in my thought process?有谁知道我的思维过程出了什么问题? I am very curious to know.
我很想知道。 (Note: I'm assembling with Clang on macOS.)
(注意:我在 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
, or equivalently, 0x7FFFFFFF
, is the maximum signed 32-bit number. 2147483647
或等效的0x7FFFFFFF
是最大的有符号32 位数字。 rdrand eax
can put any value from 0x00000000
to 0xFFFFFFFF
in eax
. rdrand eax
可以把任何价值从0x00000000
到0xFFFFFFFF
在eax
。 You have a few choices for how to handle this:对于如何处理此问题,您有几种选择:
4294967295
, or equivalently 0xFFFFFFFF
, the maximum unsigned 32-bit number, instead.4294967295
或等效的0xFFFFFFFF
(最大的 32 位无符号数)进行比较。cmp eax, 2147483647
instead of cmp rax, 2147483647
.cmp eax, 2147483647
而不是cmp rax, 2147483647
。 Since jle
operates on the result of comparing signed integers, this will cause what you're now seeing as 2147483648
through 4294967295
to instead be interpreted as -2147483648
through -1
.jle
对比较有符号整数的结果进行操作,这将导致您现在看到的2147483648
到4294967295
被解释为-2147483648
到-1
。rax
always be zero, have them match the sign bit of eax
instead (this is known as sign-extending ).rax
的高 32 位始终为零,而是让它们与eax
的符号位匹配(这称为符号扩展)。 You can do this by doing movsx rax, eax
right after rdrand eax
.movsx rax, eax
之后rdrand eax
执行movsx rax, eax
来完成此操作。 This will cause rax
to hold a value between -2147483648
and 2147483647
instead of between 0
and 4294967295
.rax
保持一个介于-2147483648
和2147483647
之间的值,而不是介于0
和4294967295
之间。 Any of those changes will result in your conditional jump always being taken, as you expect.如您所料,任何这些更改都会导致您的条件跳转始终被执行。 If you want
rax
to end up being between 0
and 4294967295
, then choose option 1 or 2. If you want rax
to end up being between -2147483648
and 2147483647
, then choose option 3.如果您希望
rax
最终介于0
和4294967295
之间,则选择选项 1 或 2。如果您希望rax
最终介于-2147483648
和2147483647
,则选择选项 3。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.