Skip to content

Better documentation example for inline assembly. #7488

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

Open
tecanec opened this issue Dec 18, 2020 · 2 comments
Open

Better documentation example for inline assembly. #7488

tecanec opened this issue Dec 18, 2020 · 2 comments
Labels
contributor friendly This issue is limited in scope and/or knowledge of Zig internals. docs
Milestone

Comments

@tecanec
Copy link
Contributor

tecanec commented Dec 18, 2020

The example for inline assembly currently found in the documentation looks like this:

pub fn main() noreturn {
    const msg = "hello world\n";
    _ = syscall3(SYS_write, STDOUT_FILENO, @ptrToInt(msg), msg.len);
    _ = syscall1(SYS_exit, 0);
    unreachable;
}

pub const SYS_write = 1;
pub const SYS_exit = 60;

pub const STDOUT_FILENO = 1;

pub fn syscall1(number: usize, arg1: usize) usize {
    return asm volatile ("syscall"
        : [ret] "={rax}" (-> usize)
        : [number] "{rax}" (number),
          [arg1] "{rdi}" (arg1)
        : "rcx", "r11"
    );
}

pub fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) usize {
    return asm volatile ("syscall"
        : [ret] "={rax}" (-> usize)
        : [number] "{rax}" (number),
          [arg1] "{rdi}" (arg1),
          [arg2] "{rsi}" (arg2),
          [arg3] "{rdx}" (arg3)
        : "rcx", "r11"
    );
}

The example depicts an use-case of inline assembly that may be found in real applications. However, the problem with this example is that the only instruction demonstrated, syscall, doesn't require that its operands get specified. This means that it can't illustrate how to use named input and output constraints to specify instruction parameters. I'd argue that showing how to use these in an example is more important than using an instruction that would often be found in the wild. (I, myself, have been confused by this example.)

I'd suggest an example that looks more like this: (This may not be a definitive example, but it should illustrate my point.)

pub fn main() noreturn {
    std.debug.warn("7-4={}\n", .{subtractWithAssembly(7, 4)});
    exitWithAssembly(); 
    unreachable;
}

pub fn subtractWithAssembly(a: usize, b: usize) usize {
    return asm volatile (
        \\ mov %[a], %[ret]
        \\ sub %[b], %[ret]
        : [ret] "=r" (-> usize)
        : [a] "r" (a),
          [b] "r" (b)
        :
    );
}

pub fn exitWithAssembly() noreturn {
    const SYS_exit: usize = 60;

    _ = asm volatile (
        \\ syscall
        :
        : [number] "{rax}" (SYS_exit),
          [arg1] "{rdi}" (0)
        : "rax", "rcx", "r11"
    );
}

Besides showing how to use named inputs and outputs, it also shows the order of operands and how to use non-specific registers. Both can be learnt about by looking elsewhere outside of zig's own docs, and the former is platform-specific, so we can't document it for every platform, but I still think it's better to show them in the example than not. (I actually considered filing an issue to allow non-specific registers for inline asm until I did some actual research, because of how useful they are for writing near-zero-overhead bindings for instructions.)

@Vexu Vexu added contributor friendly This issue is limited in scope and/or knowledge of Zig internals. docs labels Dec 18, 2020
@Vexu Vexu added this to the 0.8.0 milestone Dec 18, 2020
@ghost
Copy link

ghost commented Dec 18, 2020

I'm not sure how necessary this is with current syntax, given that we ripped it wholesale from LLVM. If anything, I'd say we could do with less detail, and a note pointing interested readers to the relevant LLVM docs, so people don't think it was a deliberate compatibility decision. We will need our own assemblers at some point, so we have a chance to create our own syntax; #215 has some ideas for that, and #5241 has a concrete plan.

@BinaryWarlock
Copy link

It should document the other constraints, such as "m", "rm" ("is r,m" any different?), and "i" as well.

@andrewrk andrewrk modified the milestones: 0.8.0, 0.9.0 Jun 4, 2021
@andrewrk andrewrk modified the milestones: 0.9.0, 0.11.0 Nov 24, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
contributor friendly This issue is limited in scope and/or knowledge of Zig internals. docs
Projects
None yet
Development

No branches or pull requests

4 participants