assemblyzig

How do I look at the assembly output of a Ziglang program?


Zig version

0.11.0-dev.3299+34865d693

The problem

I want to be able to see the assembly output of my program, ideally with file names and line numbers mapping to the assembly instructions so I can quickly reason about where they've come from.

Files in project

build.zig

const std = @import("std");

pub fn build(b: *std.Build.Builder) !void {
    // Determine compilation target
    const target = b.standardTargetOptions(.{});

    // Setup optimisation settings
    const optimize = b.standardOptimizeOption(.{});

    // Create executable for our example
    const exe = b.addExecutable(.{
        .name = "app",
        .root_source_file = .{ .path = "main.zig" },
        .target = target,
        .optimize = optimize,
    });

    // Install the executable into the prefix when invoking "zig build"
    b.installArtifact(exe);
}

main.zig

const std = @import("std");

pub fn main() void {
    std.debug.print("Hello, {s}!\n", .{"World"});
}

Solution

  • At least in Zig 0.14.0 std.Build.Step.Compile no longer has an emit_asm property.

    However, you can emit the assembly with one of these methods:

    Method 1: Add assembly output step

    Modify your build.zig file accordingly:

    const std = @import("std");
    
    const outputExecutableName = "MyApplication";
    
    pub fn build(builder: *std.Build) !void {
        // Example builder.addExecutable call:
        //const executable = builder.addExecutable(.{ ... });
    
        const installAssembly = builder.addInstallBinFile(executable.getEmittedAsm(), outputExecutableName ++ ".s");
        builder.getInstallStep().dependOn(&installAssembly.step);
    
        // ...
    }
    

    This will output a file named MyApplication.s in the zig-out/bin/ directory whenever you build.

    Method 2: zig build-exe -femit-asm[=path] option

    1. Get the full zig build-exe ... command by first running zig build --verbose. This may list out multiple commands depending on the steps you have defined in your build.zig file, make sure to copy the first one which is the zig build-exe ... --listen=- one.
    2. The command ends with --listen=-, replace that part with -femit-asm or -femit-asm=filename.s and run it. This will generate the assembly file.

    Here's a script of the above:

    #!/bin/sh
    output=$(zig build --verbose 2>&1 | head -n 1 | sed 's/--listen=-/-femit-asm/')
    $output
    

    This method outputs a file matching path if it's supplied via -femit-asm=path otherwise, if your main output file is MyApplication.elf for example, it will output MyApplication.elf.s in the current working directory.