Skip to content

Instantly share code, notes, and snippets.

@jakergrossman
Last active September 3, 2021 19:27
Show Gist options
  • Select an option

  • Save jakergrossman/ea102157aa7b2e4a0ff0128691b7fff9 to your computer and use it in GitHub Desktop.

Select an option

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
;
; 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