Chapter 27 - Compilers and Assemblers #

[TODO] Better Firmware with LLVM/Clang

Common Flags and When to Use them #

These flags are not universal, instead they’re from GCC. GCC and Clang are the big two compilers you’ll see a lot and these flags should be mostly the same between the two. Of course, there are many, many other compilers, but I’m going to start with the common stuff

-o (Output) #

Note, this is a lowercase ‘o’

You should’ve seen this already, I’m mentioning it mostly to give a brief review of what a flag is, it’s basically just another term for an argument to a program where the program is run as program-name argument1 argument2 ... but, usually flags are prefixed by - or --

in the case of -o it just means, use the next argument as the output name, so using

gcc input.c -o myprogram gives you an executable named myprogram instead of just input.

Warnings #

Just, read this: - It’s a lot more in depth than anything I could write here. It’s focused on Embedded development, but should be broadly applicable.

-S (aSSembly) #

-v (Verbose) #

Optimization #

Note, this is an uppercase ‘O’

And now we can get to fun stuff. -O is generally used in levels, here with no space, so there’s -O, -O2, -O3, and -Ofast are for speed, and -Os is for size of the binary. (or -Oz for clang)

Technically, -Ofast can break your code. This is rather unlikely though.

Each of these will take longer to compile but be more aggressive about optimizing the assembly code that is generated from your input. For example, let’s look at the code

int mult(int m, int n){
    char a[m][n];
    return sizeof(a);

This is a very stupid multiply function. Effectively, it’s multiplying two numbers by making a matrix of size m by n, and then counting the number of spots in that matrix instead of just multiplying the two numbers. I’ve embedded a GodBolt page below with this code on the left, and it’ll show the assembly output on the right. At the top you should be able to see a box to type compiler options, go ahead and put in -O. You should see a huge long mess of assembly that used multiple imul (multiply) instructions be reduced to 3 lines of assembly with only a single multiply. The compiler has figured out that what we were doing was a stupid multiply and optimized it for us.

Here there’s no difference between -O and O3, but with more complex code there often is. Just keep in mind that this is a trade off, there is the upfront cost of a longer compile time.

[TODO] Code Size Optimization: GCC Compiler Flags (Interrupt)

-march, -mtune, -flto, -msse4.2, -mavx, -mavx2 #

-ansi #

Stripping (Not like that, perv) #

Strip command [Wikipedia]

Understanding compilers and common compiler flags #

How expensive is integer-overflow trapping in C++? / Hacker News Comments on article

How the cpython compiler works

CS 6120: Advanced Compilers: The Self-Guided Online Course

Recommended compiler and linker flags for GCC (Red Hat)


Making a compiler and assembler, DIY language eso-lang style

Making an interpreted language #

Making a compiled language #

Garbage Collection #

Garbage Collection Algorithms + Writing a memory allocator

Continued Reading #

At this point I highly recommend ‘The Art of Exploitation’ by Jon Erickson

Fun things #

Malloc Geiger (Github)

If you would like to support my development of OpGuides, please consider supporting me on Patreon or dropping me some spare change on Venmo @vegadeftwing - every little bit helps ❤️