简体   繁体   English

生成一个随机的 32 位数字以存储在 64 位寄存器中

[英]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可以把任何价值从0x000000000xFFFFFFFFeax You have a few choices for how to handle this:对于如何处理此问题,您有几种选择:

  1. Compare it with 4294967295 , or equivalently 0xFFFFFFFF , the maximum unsigned 32-bit number, instead.将其与4294967295或等效的0xFFFFFFFF (最大的 32 位无符号数)进行比较。
  2. Do 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对比较有符号整数的结果进行操作,这将导致您现在看到的21474836484294967295被解释为-2147483648-1
  3. Instead of having the upper 32 bits of 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保持一个介于-21474836482147483647之间的值,而不是介于04294967295之间。

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最终介于04294967295之间,则选择选项 1 或 2。如果您希望rax最终介于-21474836482147483647 ,则选择选项 3。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM