Last active
September 3, 2021 19:27
-
-
Save jakergrossman/ea102157aa7b2e4a0ff0128691b7fff9 to your computer and use it in GitHub Desktop.
Short routine to demonstrate seeding random numbers with clock_gettime & getpid in x86 assembly
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ; | |
| ; rndlong.asm - demo routine to generate a random 64-bit value (long) in x86 assembly | |
| ; | |
| ; The algorithm was drawn from tempname.c in the glibc source. Relevant files: | |
| ; https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/posix/tempname.c;h=ff38f1e31fe36af8852ad7670cf9b547f40b36de;hb=HEAD | |
| ; https://sourceware.org/git/?p=glibc.git;a=blob;f=include/random-bits.h;h=077b46736cda38353078316de1890ac7a3a9874a;hb=HEAD | |
| ; | |
| ; Building, Linking, and Running: | |
| ; | |
| ; $ nasm -felf64 rndlong.asm | |
| ; $ ld rndlong.o -o rndlong | |
| ; $ ./rndlong | |
| ; | |
| global _start | |
| ; | |
| ; Definitions | |
| ; | |
| struc timespec ; timespec struct for clock_gettime | |
| sec: resq 1 | |
| nsec: resq 1 | |
| endstruc | |
| ; syscall manpages: | |
| WRITE: equ 1 ; write(2) | |
| GETPID: equ 39 ; getpid(2) | |
| EXIT: equ 60 ; exit(2) | |
| CLOCK_GETTIME: equ 228 ; clock_gettime(2) | |
| STDOUT: equ 1 ; constants | |
| CLOCK_MONOTONIC: equ 1 | |
| section .text | |
| _start: | |
| mov rax, CLOCK_GETTIME ; clock_gettime(CLOCK_MONOTONIC, &tv) | |
| mov rdi, CLOCK_MONOTONIC | |
| mov rsi, tv | |
| syscall | |
| cmp rax, 0 ; clock_gettime() ok? | |
| jl err ; ...no | |
| ; | |
| ; shuffle the lower bits | |
| ; to minimize clock bias | |
| ; | |
| mov rax, [tv+sec] ; rax = tv.sec ^ tv.nsec | |
| xor rax, [tv+nsec] | |
| mov rdi, rax ; rax ^= (rax << 24) | (rax >> 8) | |
| mov rsi, rax | |
| shl l rdi, 24 ; rdi = rax << 24 | |
| shr rsi, 8 ; rsi = rax >> 8 | |
| or rdi, rsi ; rdi = (rax << 24) | (rax >> 8) | |
| xor rax, rdi | |
| mov [rnd], rax ; store rnd so far | |
| mov rax, GETPID ; getpid() | |
| syscall ; never fails | |
| rol rax, 32 ; [rnd] ^= getpid() << 32 | |
| xor [rnd], rax ; [rnd] is now our secret sauce | |
| mov rax, WRITE ; output [rnd] to stdout | |
| mov rdi, STDOUT ; this is just for it to go | |
| mov rsi, rnd ; somewhere to see, normally | |
| mov rdx, 8 ; the random value would be used | |
| syscall ; for something | |
| cmp rax, 0 ; write() ok? | |
| jl err ; ...no | |
| mov rax, EXIT ; exit(0) | |
| xor rdi, rdi ; 0 = good return | |
| syscall | |
| err: | |
| mov rax, EXIT | |
| mov rdi, 1 ; 1 = bad return | |
| syscall | |
| section .bss | |
| rnd: resq 1 ; random value | |
| tv: resb timespec_size ; return data from clock_gettime() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment