I’m currently playing with the idea of removing string literals and replacing them with regular tokens which I stringify in a syntax extension. This has 3 main benefits:
- It’s more lightweight and looks more integrated.
- Input operands can be declared and used in one place.
- It’s easier to write macros with inline assembly depending on arguments to the macro.
Here’s an example of what it could look like:
asm! {
cli;
swapgs;
mov ds, {a = user_segment};
mov {r = &thread.registers.rip};
iretq;
}
Note that the semicolons will expand to newlines in the generated assembly.
I also suggest that an asm! macro could return it’s outputs instead of mutating existing variables.
let ret = asm! {
inw {a=>}, {dN = port};
};
I’m not sure what syntax would be desired for all the options or how it should be escaped in the middle of the assembly. I’m looking for input on that. However to make parsing easier I suggest to place options in matches braces after the opening brace.
let mut result: u32;
asm! {
[b = arg, b -> r2, -eax, :name:r, alignstack, pure, intel]
jmp label;
label:
mov :name, {r = 1 + 2};
mov {r -> result}, :name;
}
A possibility is also to put outputs at the end using the escape syntax:
let (eax, ebx) = asm! {
{a = 1, b = 3}
add eax, 1;
add ebx, 1;
{= (a, b)}
};
I think we should support this syntax for major architectures (ARM and x86) and allow string literals in case Rust’s lexer or our escape method isn’t compatible with some assembly dialect. Note that ARM will require another escape syntax than curly braces.
Inline assembly should have implicit side effects by default which you can opt out of using the pure attribute. Intel syntax should also be default on x86. The syntax to use on x86 should be added as a crate attribute since people using AT&T syntax aren’t extinct yet.
For reference: