1 ;; rdrand.asm - written and placed in public domain by Jeffrey Walton and Uri Blumenthal.
2 ;; Copyright assigned to the Crypto++ project.
4 ;; This ASM file provides RDRAND to downlevel Microsoft tool chains.
5 ;; Everything "just works" under Visual Studio. Other platforms will
6 ;; have to run MASM/MASM-64 and then link to the object files.
8 ;; set ASFLAGS=/nologo /D_M_X86 /W3 /Cx /Zi /safeseh
9 ;; set ASFLAGS64=/nologo /D_M_X64 /W3 /Cx /Zi
10 ;; "C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\ml.exe" %ASFLAGS% /Fo rdrand-x86.obj /c rdrand.asm
11 ;; "C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\amd64\ml64.exe" %ASFLAGS64% /Fo rdrand-x64.obj /c rdrand.asm
13 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
14 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
16 TITLE MASM_RDRAND_GenerateBlock source file
17 SUBTITLE Microsoft specific ASM code to utilize RDRAND for down level Microsoft toolchains
19 PUBLIC MASM_RDRAND_GenerateBlock
21 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
22 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
24 ;; C/C++ Function prototypes (both are fastcall)
26 ;; extern "C" void __fastcall MASM_RDRAND_GenerateBlock(byte* ptr, size_t size);
28 ;; extern "C" void __fastcall MASM_RDRAND_GenerateBlock(byte* ptr, size_t size);
30 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
31 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
33 IFDEF _M_X86 ;; Set via the command line
38 ;; Fastcall calling conventions exports
39 ALIAS <@MASM_RDRAND_GenerateBlock@8> = <MASM_RDRAND_GenerateBlock>
43 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
44 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
46 IFDEF _M_X86 ;; Set via the command line
53 ;; No need for Load_Arguments due to fastcall
54 ;; ECX (in): arg1, byte* buffer
55 ;; EDX (in): arg2, size_t bsize
57 MASM_RDRAND_GenerateBlock PROC ;; arg1:DWORD, arg2:DWORD
59 MWSIZE EQU 04h ;; machine word size
64 RDRAND_GenerateBlock_Top:
66 ;; Check remaining size
68 je RDRAND_GenerateBlock_Return
71 ;; RDRAND is not available prior to VS2012. Just emit
72 ;; the byte codes using DB. This is `rdrand eax`.
75 ;; If CF=1, the number returned by RDRAND is valid.
76 ;; If CF=0, a random number was not available.
84 jb RDRAND_Partial_Machine_Word
86 RDRAND_Full_Machine_Word:
88 mov DWORD PTR [buffer], eax
89 add buffer, MWSIZE ;; No need for Intel Core 2 slow workarounds, like
90 sub bsize, MWSIZE ;; `lea buffer,[buffer+MWSIZE]` for faster adds
93 jmp RDRAND_GenerateBlock_Top
96 RDRAND_Partial_Machine_Word:
98 ;; Test bit 1 to see if size is at least 2
100 jz RDRAND_Bit_1_Not_Set
102 mov WORD PTR [buffer], ax
106 RDRAND_Bit_1_Not_Set:
108 ;; Test bit 0 to see if size is at least 1
110 jz RDRAND_Bit_0_Not_Set
112 mov BYTE PTR [buffer], al
116 RDRAND_Bit_0_Not_Set:
118 ;; We've hit all the bits
120 RDRAND_GenerateBlock_Return:
126 MASM_RDRAND_GenerateBlock ENDP
130 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
131 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
133 IFDEF _M_X64 ;; Set via the command line
140 ;; No need for Load_Arguments due to fastcall
141 ;; RCX (in): arg1, byte* buffer
142 ;; RDX (in): arg2, size_t bsize
144 MASM_RDRAND_GenerateBlock PROC FRAME ;; arg1:QWORD, arg2:QWORD
146 MWSIZE EQU 08h ;; machine word size
153 RDRAND_GenerateBlock_Top:
155 ;; Check remaining size
157 je RDRAND_GenerateBlock_Return
160 ;; RDRAND is not available prior to VS2012. Just emit
161 ;; the byte codes using DB. This is `rdrand rax`.
162 DB 048h, 0Fh, 0C7h, 0F0h
164 ;; If CF=1, the number returned by RDRAND is valid.
165 ;; If CF=0, a random number was not available.
173 jb RDRAND_Partial_Machine_Word
175 RDRAND_Full_Machine_Word:
177 mov QWORD PTR [buffer], rax
182 jmp RDRAND_GenerateBlock_Top
184 ;; 1,2,3,4,5,6,7 bytes remain
185 RDRAND_Partial_Machine_Word:
187 ;; Test bit 2 to see if size is at least 4
189 jz RDRAND_Bit_2_Not_Set
191 mov DWORD PTR [buffer], eax
195 RDRAND_Bit_2_Not_Set:
197 ;; Test bit 1 to see if size is at least 2
199 jz RDRAND_Bit_1_Not_Set
201 mov WORD PTR [buffer], ax
205 RDRAND_Bit_1_Not_Set:
207 ;; Test bit 0 to see if size is at least 1
209 jz RDRAND_Bit_0_Not_Set
211 mov BYTE PTR [buffer], al
215 RDRAND_Bit_0_Not_Set:
217 ;; We've hit all the bits
219 RDRAND_GenerateBlock_Return:
225 MASM_RDRAND_GenerateBlock ENDP
229 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
230 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;