英特尔制造的现代8086兼容处理器包含易于访问的外围设备,可产生适当的随机性。使用该rdrand
指令来驱动该外设,如果该外设不可用或超出熵,则该指令会生成随机位模式或设置进位标志。
以下针对80386 Linux的简短程序通过cpuid
指令检查外围设备是否可用,并尝试生成随机数。如果没有外围设备或随机数,则程序将以状态终止1
。如果可以生成一个随机数,则打印出a 1
或a 0
,并且程序以退出状态终止0
。
另存为rand.s
并组装
as --32 -o rand.o rand.s
ld -melf_i386 -o rand rand.o
这是整个程序集:
.globl _start
.type _start,@function
_start:
# check if the cpuid instruction is available by trying to
# toggle the id flag in the eflags register
pushfl
mov (%esp),%eax
btc $21,%eax # toggle id bit
push %eax
popfl # check if id bit was saved
pushfl
pop %eax # load new flags
pop %ecx # load original flags
xor %ecx,%eax # difference is in %eax
bt $21,%eax # check if bit was flipped
jnc .Lfailure
# if we reach this part, we have a cpuid instruction
# next, check if rdrand exists
mov $1,%eax # load cpuid leaf 1
cpuid
bt $30,%ecx # is rdrnd available?
jnc .Lfailure
# let's try to get some random data
rdrand %ax # don't waste randomness; one bit would suffice
jnc .Lfailure # no randomness available
and $1,%eax # isolate one bit of randomness
add $0x30,%al # 0x30 = '0'
push %eax
mov $4,%eax # prepare a write system call
mov $1,%ebx
mov %esp,%ecx # where we placed the data before
mov %ebx,%edx # one byte
int $0x80
# okay, we're done here. Let's exit
mov %ebx,%eax # do an exit system call with status 0
xor %ebx,%ebx
int $0x80
.Lfailure:
mov $1,%eax # do an exit system call with status 1
mov %eax,%ebx
int $0x80
.size _start,.-_start
并转储产生的77个字节的机器代码:
08048098 <_start>:
8048098: 9c pushf
8048099: 8b 04 24 mov (%esp),%eax
804809c: 0f ba f8 15 btc $0x15,%eax
80480a0: 50 push %eax
80480a1: 9d popf
80480a2: 9c pushf
80480a3: 58 pop %eax
80480a4: 59 pop %ecx
80480a5: 31 c8 xor %ecx,%eax
80480a7: 0f ba e0 15 bt $0x15,%eax
80480ab: 73 2f jae 80480dc <_start+0x44>
80480ad: b8 01 00 00 00 mov $0x1,%eax
80480b2: 0f a2 cpuid
80480b4: 0f ba e1 1e bt $0x1e,%ecx
80480b8: 73 22 jae 80480dc <_start+0x44>
80480ba: 66 0f c7 f0 rdrand %ax
80480be: 73 1c jae 80480dc <_start+0x44>
80480c0: 83 e0 01 and $0x1,%eax
80480c3: 04 30 add $0x30,%al
80480c5: 50 push %eax
80480c6: b8 04 00 00 00 mov $0x4,%eax
80480cb: bb 01 00 00 00 mov $0x1,%ebx
80480d0: 89 e1 mov %esp,%ecx
80480d2: 89 da mov %ebx,%edx
80480d4: cd 80 int $0x80
80480d6: 89 d8 mov %ebx,%eax
80480d8: 31 db xor %ebx,%ebx
80480da: cd 80 int $0x80
80480dc: b8 01 00 00 00 mov $0x1,%eax
80480e1: 89 c3 mov %eax,%ebx
80480e3: cd 80 int $0x80