You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/unsafe/asm.md
+10-9Lines changed: 10 additions & 9 deletions
Original file line number
Diff line number
Diff line change
@@ -232,25 +232,24 @@ fn main() {
232
232
// three entries of four bytes each
233
233
letmutname_buf= [0_u8; 12];
234
234
// String is stored as ascii in ebx, edx, ecx in order
235
-
// Because ebx is reserved, we get a scratch register and move from
236
-
// ebx into it in the asm. The asm needs to preserve the value of
237
-
// that register though, so it is pushed and popped around the main asm
235
+
// Because ebx is reserved, the asm needs to preserve the value of it.
236
+
// So we push and pop it around the main asm.
238
237
// (in 64 bit mode for 64 bit processors, 32 bit processors would use ebx)
239
238
240
239
unsafe {
241
240
asm!(
242
241
"push rbx",
243
242
"cpuid",
244
-
"mov [{0}], ebx",
245
-
"mov [{0} + 4], edx",
246
-
"mov [{0} + 8], ecx",
243
+
"mov [rdi], ebx",
244
+
"mov [rdi + 4], edx",
245
+
"mov [rdi + 8], ecx",
247
246
"pop rbx",
248
247
// We use a pointer to an array for storing the values to simplify
249
248
// the Rust code at the cost of a couple more asm instructions
250
249
// This is more explicit with how the asm works however, as opposed
251
250
// to explicit register outputs such as `out("ecx") val`
252
251
// The *pointer itself* is only an input even though it's written behind
253
-
in(reg) name_buf.as_mut_ptr(),
252
+
in("rdi") name_buf.as_mut_ptr(),
254
253
// select cpuid 0, also specify eax as clobbered
255
254
inout("eax") 0=>_,
256
255
// cpuid clobbers these registers too
@@ -269,9 +268,11 @@ This instruction writes to `eax` with the maximum supported `cpuid` argument and
269
268
270
269
Even though `eax` is never read we still need to tell the compiler that the register has been modified so that the compiler can save any values that were in these registers before the asm. This is done by declaring it as an output but with `_` instead of a variable name, which indicates that the output value is to be discarded.
271
270
272
-
This code also works around the limitation that `ebx` is a reserved register by LLVM. That means that LLVM assumes that it has full control over the register and it must be restored to its original state before exiting the asm block, so it cannot be used as an output. To work around this we save the register via `push`, read from `ebx` inside the asm block into a temporary register allocated with `out(reg)` and then restoring `ebx` to its original state via `pop`. The `push` and `pop` use the full 64-bit `rbx` version of the register to ensure that the entire register is saved. On 32 bit targets the code would instead use `ebx` in the `push`/`pop`.
271
+
This code also works around the limitation that `ebx` is a reserved register by LLVM. That means that LLVM assumes that it has full control over the register and it must be restored to its original state before exiting the asm block, so it cannot be used as an input or output **except** if the compiler uses it to fulfill a general register class (e.g. `in(reg)`). This makes `reg` operands dangerous when using reserved registers as we could unknowingly corrupt out input or output because they share the same register.
273
272
274
-
This can also be used with a general register class (e.g. `reg`) to obtain a scratch register for use inside the asm code:
273
+
To work around this we use `rdi` to store the pointer to the output array, save `ebx` via `push`, read from `ebx` inside the asm block into the array and then restoring `ebx` to its original state via `pop`. The `push` and `pop` use the full 64-bit `rbx` version of the register to ensure that the entire register is saved. On 32 bit targets the code would instead use `ebx` in the `push`/`pop`.
274
+
275
+
This can also be used with a general register class to obtain a scratch register for use inside the asm code:
0 commit comments