.byteexpects zero or more expressions, separated by commas. Each expression is assembled into the next byte.
Minimal runnable example
.byte spits out bytes wherever you are.
If you happen to be in the text segment, then that byte might get run like code.
Here’s a Linux x86_64 implementation of
exit(0) with a
nop thrown in:
produces the exact same executable as:
nop is encoded as the byte
Here’s the method to run the example:
as -o my_exit.o my_exit.s && ld -s -o my_exit my_exit.o && ./my_exit
One use case: new instructions
One use case is when new instructions are added to a CPU ISA, but only very edge versions of the assembler would support it.
So project maintainers may choose to inline the bytes directly to make it compilable on older assemblers.
See for example this Spectre workaround on the Linux kernel with the analogous
.inst directive: https://github.com/torvalds/linux/blob/94710cac0ef4ee177a63b5227664b38c95bbf703/arch/arm/include/asm/barrier.h#L23
A new instruction was added for Spectre, and the kernel decided to hardcode it for the time being.