I want to generate a random 32-bit number. I am using rdrand
for this. However, I am having some problems. Since the number can be no more than 32 bits large, I am doing 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. I figured that I could clear rax
with a xor
to itself, and then only load half of it with rdrand eax
. Then I could look at rax
, have one half be at most a 32-bit number, and the other half be cleared.
When I compare rax
with the maximum 32-bit number size, 2147483647 , I get very inconsistent results. Half of the time, the exit code is 1, meaning that the number in rax
is, in fact, smaller than 32-bits. 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.
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.)
.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. rdrand eax
can put any value from 0x00000000
to 0xFFFFFFFF
in eax
. You have a few choices for how to handle this:
4294967295
, or equivalently 0xFFFFFFFF
, the maximum unsigned 32-bit number, instead.cmp eax, 2147483647
instead of 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
.rax
always be zero, have them match the sign bit of eax
instead (this is known as sign-extending ). You can do this by doing movsx rax, eax
right after rdrand eax
. This will cause rax
to hold a value between -2147483648
and 2147483647
instead of between 0
and 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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.