Embedding machine code in Zig instead of using inline assembly
Object files vs. raw machine code Assembling Calling from Zig A larger example with fast memcpy and syscalls Zig supports inline assembly, which is useful when: Writing an operating system, which requires direct access to special CPU registers and controllers Implementing syscalls in standard libraries Accessing microcontroller features on embedded systems Handwriting a performance-critical hot-path function where the optimizer doesn’t do the right thing Inline assembly, however, can quickly get unwieldy, and getting the input/output constraints right can be tricky....
Cache Me If You Can
Cache lines A little Zig surprise The code The numbers Hyperthreading adds a twist Cache topology How come making a struct in Zig less densely packed can give a 56% performance increase, with far less variability? This post takes a look at false sharing and how it can be caused by packed data layouts and unintended field reorderings. ...
Async CPU bound workers in Zig
Zig has async/await support, which is typically used for IO bound operations. In this article, however, we’ll use async/await to simplify writing a simple concurrent worker. Goal: use all the cores on the machine to find a randomly selected 64-bit number whose lower N bits are all cleared. How it works Instead of manually spinning up threads, we’re just going to use async/await, along with pub const io_mode = .evented; which informs the standard library to use a non-blocking event loop....
Bio - All your parentheses are belong to us
In a previous Zig post, we wrote a small postfix notation calculator. This post takes a look at something that take prefix notation to the extreme: a new language in the Lisp family called Bio The goal of this project is to make it easy to play around with Lisp dialect ideas and to make a well-documented and readable Lisp interpreter for others to learn from. This article aims to point out some key areas people stumble on when writing a basic Lisp interpreter....
Some notes on using Zig with Valgrind
Zig has a very nice built-in memory leak detector in its General Purpose Allocator (GPA), but sometimes you have to break out Valgrind to get to the bottom of things. When I first did this, I ran into a couple of problems, which I’m jotting down here along with solutions. Thanks to mikdusan, ifreund and lemonboy for helping me figure out various issues First of all, to get Valgrind going with Zig programs, you’ll have to switch to the C allocator....
Zig scripts?!?
Look at this beauty: //usr/bin/env zig run "$0" -- "$@" ; exit const std = @import("std"); pub fn main() !void { std.log.info("Awesome, it works\n", .{}); } Let’s make it executable and run it: chmod +x myscript.zig ./myscript.zig info: Awesome, it works This works because // is a comment in Zig, and just an empty path component as far as the shell is concerned Thanks to squirl for making the argument passing syntax more robus
A surprisingly capable RPN calculator in about 100 lines of Zig code
Summary: Reverse polish notation is awesome Zig is awesome Before solving quadratic equations and diving into code, let’s see if 2 + 2 is still 4: 2 2 + M0 = 4 Phew! Notice how every answer is placed in the next available memory slot. This will be useful in our next example where we calculate the two solutions to a quadratic equation: First we input the known values so these get memory slots we can reference, rather than repeating the constants....
Running Zig binaries on a KaiOS device
The goal here is to: Cross-compile a Zig program Root a KaiOS device, and then install and run the cross-compiled program on the device We’re not making a GUI app or anything here, just a small “Hello world” program that we’ll cross-compile and run on the device. All sorts of interesting things can be done from this point on. I’m using Android’s adb to push files to the device and to get a shell, so you’ll have to install that first if you wanna follow along....