The current syntax of the `asm { }` body follows the gcc extended style as documented in https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html
This has been the case in gdc long before D1 v1.001 was released.
This has been argued that it rather counters what is considered tasteful D style code.
Consider the existing style:
asm pure nothrow @nogc {
"cmoveq %1, %2, %[result]" // insn
: [result] "=r" (result) // outputs
: "r" (test), "r" (newvalue), // inputs
"[result]" (oldvalue)
: "memory"; // clobbers
}
Then consider what that would look like if output/inputs were a hash, and clobbers an array:
asm pure nothrow @nogc {
"cmoveq %1, %2, %[result]" // insn
: [result = "=r": result] // outputs
: ["r": test, "r": newvalue, // inputs
"[result]": oldvalue]
: ["memory"]; // clobbers
}
Then going one further and replacing the colons with commas.
asm pure nothrow @nogc {
"cmoveq %1, %2, %[result]", // insn
[result = "=r": result], // outputs
["r": test, "r": newvalue, // inputs
"[result]": oldvalue],
["memory"]; // clobbers
}
---
Some examples of what this might look like in other cases:
asm nothrow @nogc {
"xchg %h0, %b0", ["+a": num];
}
asm nothrow @nogc {
"mtfsf 255,%1", ["=X": sum], ["f": fpenv];
}
asm nothrow @nogc {
"", [], [], ["memory"]; // volatile barrier.
}
asm pure nothrow @nogc {
"bsfl %1,%0", ["=r": dwRes], ["r": dwSomeValue], ["cc"];
}
asm nothrow @nogc {
"rdtsc\n\t"
"shl $32, %%rdx\n\t"
"or %%rdx, %0",
["=a": msr], [], ["rdx"];
}
asm nothrow @nogc {
/* lots of asm here */
"#n=%1 ap=%8=%12 lda=%13 x=%7=%10 y=%0=%2 alpha=%9 o16=%11\n"
"#a0=%3 a1=%4 a2=%5 a3=%6",
[ // outputs
"+m": *cast(double[10]*) y,
"+&r": n, // 1
"+b": y, // 2
"=b": a0, // 3
"=&b": a1, // 4
"=&b": a2, // 5
"=&b": a3, // 6
],
[ // inputs
"m": *cast(double[10]*) x,
"m": *cast(double*) ap,
"d": alpha, // 9
"r": x, // 10
"b": 16, // 11
"3": ap, // 12
"4": lda, // 13
],
[ // clobbers
"cr0",
"vs32","vs33","vs34","vs35","vs36","vs37",
"vs40","vs41","vs42","vs43","vs44","vs45","vs46","vs47"
];
}
int frob(int x)
{
int y;
asm {
"frob %%r5, %1; jc %l[error]; mov (%2), %%r5",
[/* No outputs. */],
["r": x, "r": &y],
["r5", "memory"],
[Lerror];
}
return y;
Lerror:
return -1;
}
int main()
{
int iInt = 1;
top:
asm nothrow @nogc {
"some assembler instructions here",
[/* No outputs. */],
["q": iInt, "X": char.sizeof + 1, "i": 42],
[/* No clobbers. */],
[top];
}
}
Comment #1 by ibuclaw — 2020-07-16T15:22:16Z
(In reply to Iain Buclaw from comment #0)
> Then going one further and replacing the colons with commas.
>
> asm pure nothrow @nogc {
> "cmoveq %1, %2, %[result]", // insn
> [result = "=r": result], // outputs
> ["r": test, "r": newvalue, // inputs
> "[result]": oldvalue],
> ["memory"]; // clobbers
> }
>
Could even drop the order dependency and re-use struct literal syntax of using labels to denote "fields" of the asm statement.
asm pure nothrow @nogc {
insn: "cmoveq %1, %2, %[result]",
clobbers: ["memory"],
inputs: ["r": test, "r": newvalue,
"[result]": oldvalue],
outputs: [result = "=r": result],
}
And so in the last example.
> int main()
> {
> int iInt = 1;
> top:
> asm nothrow @nogc {
> "some assembler instructions here",
> [/* No outputs. */],
> ["q": iInt, "X": char.sizeof + 1, "i": 42],
> [/* No clobbers. */],
> [top];
> }
> }
It can be abbreviated to:
int main()
{
int iInt = 1;
top:
asm nothrow @nogc {
"some assembler instructions here",
inputs: ["q": iInt, "X": char.sizeof + 1, "i": 42],
labels: [top];
}
}
Comment #2 by ibuclaw — 2023-02-15T20:23:31Z
Another alternative that may prove nicer, is the use of `arg => value` instead. This also allows for each argument/property of the GCC-style assembler statement to be optionally added.
However, there is also DIP88 to consider, which has adopted `arg: value` for named parameters. So can't ignore the original alternative syntax suggested in 2020.
If going for named arguments, can also add a few more to expose the underbelly of the implementation to the user, for example `volatile` and `inline`.
Alternative syntax #1
```
asm @safe @nogc nothrow pure {
"insn-template", // can be CTFE-able expression with string result
inputs => ("a", value), // simple example, single input/output
outputs => [ // complex example, multiple input/outputs
("=a", result),
("=g", overflow)
],
clobber => "eax", // or ["eax", "memory", ...]
goto => label, // or [label1, label2, ...]
volatile => true, // default true, accept "false" as optimization
inline => true, // default false, allow pragma(inline, true) to
// set if not specified
}
```
Alternative syntax #2
```
asm @safe @nogc nothrow pure {
"insn-template", // can be CTFE-able expression with string result
inputs: ("a", value), // simple example, single input/output
outputs: [ // complex example, multiple input/outputs
("=a", result),
("=g", overflow)
],
clobber: "eax", // or ["eax", "memory", ...]
goto: label, // or [label1, label2, ...]
volatile: true, // default true, accept "false" as optimization
inline: true, // default false, allow pragma(inline, true) to
// set if not specified
}
```
Example 1:
```
int foo(int count)
{
version (GNU_Alternate1_Asm)
{
asm { "dec %0, jb %l[stop]",
goto => stop,
outputs => ("+r", count);
volatile => false;
}
}
else version (GNU_Alternate2_Asm)
{
asm { "dec %0, jb %l[stop]",
goto: stop,
outputs: ("+r", count);
volatile: false;
}
}
else // old-style syntax
{
asm { "dec %0, jb %l[stop]"
: "+r" (count)
: /* No inputs */
: /* No clobbers */
: stop;
}
}
return count;
stop:
return 0;
}
```
Example 2:
```
version (GNU_Alternate1_Asm)
{
asm pure nothrow @nogc {
"cpuid",
outputs => [("=a", a), ("=b", b)],
inputs => ("a", 0x8000_001E),
clobber => ["ecx", "edx"];
}
}
else version (GNU_Alternate2_Asm)
{
asm pure nothrow @nogc {
"cpuid",
outputs: [("=a", a), ("=b", b)],
inputs: ("a", 0x8000_001E),
clobber: ["ecx", "edx"];
}
}
else // old-style syntax
{
asm pure nothrow @nogc {
"cpuid"
: "=a" (a), "=b" (b)
: "a" (0x8000_001E)
: "ecx", "edx";
}
}
```
Comment #3 by robert.schadek — 2024-12-13T19:07:10Z