Skip to content

Commit c8ae029

Browse files
authored
Update CPUID example
Using the updated code from rust-lang/rust#90083
1 parent ebbc1ab commit c8ae029

File tree

1 file changed

+25
-14
lines changed

1 file changed

+25
-14
lines changed

src/unsafe/asm.md

+25-14
Original file line numberDiff line numberDiff line change
@@ -206,28 +206,39 @@ This state is generally referred to as being "clobbered".
206206
We need to tell the compiler about this since it may need to save and restore this state around the inline assembly block.
207207

208208
```rust
209-
let ebx: u32;
210-
let ecx: u32;
211-
209+
let mut ebx: u32;
210+
let mut edx: u32;
211+
let mut ecx: u32;
212212
unsafe {
213213
asm!(
214+
"push rbx",
214215
"cpuid",
215-
// EAX 4 selects the "Deterministic Cache Parameters" CPUID leaf
216-
inout("eax") 4 => _,
217-
// ECX 0 selects the L0 cache information.
218-
inout("ecx") 0 => ecx,
219-
lateout("ebx") ebx,
220-
lateout("edx") _,
216+
"mov {0:e}, ebx",
217+
"pop rbx",
218+
// String is stored as ascii in ebx, edx, ecx in order
219+
// Because ebx is reserved, we get a scratch register and move from
220+
// ebx into it in the asm. The asm needs to preserve the value of
221+
// that register though, so it is pushed and popped around the main asm
222+
// (in 64 bit mode for 64 bit processors, 32 bit processors would use ebx)
223+
out(reg) ebx,
224+
out("edx") edx,
225+
out("ecx") ecx,
226+
// EAX 0 selects CPUID parameter and manufacturer ID
227+
inout("eax") 0 => _,
221228
);
222229
}
223230

224-
println!(
225-
"L0 Cache: {}",
226-
((ebx >> 22) + 1) * (((ebx >> 12) & 0x3ff) + 1) * ((ebx & 0xfff) + 1) * (ecx + 1)
227-
);
231+
// Turn the resulting values into a string
232+
let mut s = Vec::new();
233+
for val in [ebx, edx, ecx] {
234+
for b in val.to_ne_bytes() {
235+
s.push(b);
236+
}
237+
}
238+
println!("CPU Manufacturer ID: {}", std::str::from_utf8(&s).unwrap());
228239
```
229240

230-
In the example above we use the `cpuid` instruction to get the L1 cache size.
241+
In the example above we use the `cpuid` instruction to read the CPU manufacturer ID.
231242
This instruction writes to `eax`, `ebx`, `ecx`, and `edx`, but for the cache size we only care about the contents of `ebx` and `ecx`.
232243

233244
However we still need to tell the compiler that `eax` and `edx` have been modified so that it can save any values that were in these registers before the asm. This is done by declaring these as outputs but with `_` instead of a variable name, which indicates that the output value is to be discarded.

0 commit comments

Comments
 (0)