Skip to content

Fix the inline assembly examples #24842

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 30, 2015
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 32 additions & 5 deletions src/doc/trpl/inline-assembly.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ but you must add the right number of `:` if you skip them:
asm!("xor %eax, %eax"
:
:
: "eax"
: "{eax}"
);
# } }
```
Expand All @@ -69,21 +69,21 @@ Whitespace also doesn't matter:
# #![feature(asm)]
# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
# fn main() { unsafe {
asm!("xor %eax, %eax" ::: "eax");
asm!("xor %eax, %eax" ::: "{eax}");
# } }
```

## Operands

Input and output operands follow the same format: `:
"constraints1"(expr1), "constraints2"(expr2), ..."`. Output operand
expressions must be mutable lvalues:
expressions must be mutable lvalues, or not yet assigned:

```
# #![feature(asm)]
# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
fn add(a: i32, b: i32) -> i32 {
let mut c = 0;
let c: i32;
unsafe {
asm!("add $2, $0"
: "=r"(c)
Expand All @@ -100,6 +100,22 @@ fn main() {
}
```

If you would like to use real operands in this position, however,
you are required to put curly braces `{}` around the register that
you want, and you are required to put the specific size of the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't believe this is true, e.g. #24799 (comment) .

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is, I have tried it both ways.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, well it's definitely not always required. E.g. to add to the example above, this also works (the not indicates that the correct register size is being used and it's not just, say, defaulting to eax in some way: the output is fffffffffffffffd):

#![feature(asm)]

fn main() {
    let mut test: u64;
    unsafe {
        asm!("mov $$2, %rax
              not %rax" 
             : "={ax}"(test));
    }
    println!("{:x}", test);
}

What's the other way in your example? (al -> ax?)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, or maybe just {a}? It seems that {ax} always works (I see no difference in the asm between al and ax), but just a presumably means something different to LLVM.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That must be it. Just {a} doesn't work right now.

operand. This is useful for very low level programming, where
which register you use is important:

```
# #![feature(asm)]
# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
# unsafe fn read_byte_in(port: u16) -> u8 {
let result: u8;
asm!("in %dx, %al" : "={al}"(result) : "{dx}"(port));
result
# }
```

## Clobbers

Some instructions modify registers which might otherwise have held
Expand All @@ -112,7 +128,7 @@ stay valid.
# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
# fn main() { unsafe {
// Put the value 0x200 in eax
asm!("mov $$0x200, %eax" : /* no outputs */ : /* no inputs */ : "eax");
asm!("mov $$0x200, %eax" : /* no outputs */ : /* no inputs */ : "{eax}");
# } }
```

Expand All @@ -139,3 +155,14 @@ Current valid options are:
the compiler to insert its usual stack alignment code
3. *intel* - use intel syntax instead of the default AT&T.

```
# #![feature(asm)]
# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
# fn main() {
let result: i32;
unsafe {
asm!("mov eax, 2" : "={eax}"(result) : : : "intel")
}
println!("eax is currently {}", result);
# }
```