Code snippets
Contents
- C / Shell : Standalone single file compilation / execution (self-executable C file)
- C / x86 : SIMD debugging / exploration (with intrinsics)
- C Raspberry PI Zero 1.3 U-Boot bare metal sample
- JavaScript : Extended Cistercian numerals (base 16 and binary-like)
- Bash : Format directory files raw data into an array of hex / 32-bit chunks
Note : Most of the code here is C compiled with GCC.
The code embed a shell script to compile itself so just run :
sh code.c
C / Shell : Standalone single file compilation / execution
(self-executable C file)
A C / Shell trick to pack the code, compilation and execution
of a C program into a single file which is useful for short
programs, prototypes, debugging or to show off C examples, put this
into a test.c file and run it with sh test.c :
#ifdef d
#!/bin/sh
gcc -Wall -O0 test.c -o out
./out
exit
#endif
// your usual C code
C
/ x86 : SIMD debugging / exploration (with intrinsics)
This is a program i did as an exploration / debugging tool
when i started to use SIMD instructions, it use compiler
intrinsics (see the
intrinsics guide) and just print the content of SIMD registers
(here AVX),
quite useful to quickly evaluate the result of some SIMD code. Just
put it into a simd.c file and run it with sh simd.c
:
#ifdef d
#!/bin/sh
gcc -Wall -mavx2 -m32 -O0 simd.c -o out
./out
exit
#endif
#include <stdio.h>
#include <x86intrin.h>
float input2[8] = {
0.75f, 0.5f, 0.25f, 0.0f
};
float output[8] = {
0
};
int main (void) {
__m256i i1i = _mm256_set_epi32(0, 0, 0, 0, 0, 6,
4, 2);
__m256 v1 = _mm256_cvtepi32_ps(i1i);
__m256 i2 = _mm256_loadu_ps(&input2[0]);
__m256 v2 = _mm256_mul_ps(v1, i2);
__m256 v3 = _mm256_hadd_ps(v2, v2);
_mm256_storeu_ps((float *)output, v3);
for (int i = 0; i < 8; i += 1) {
printf("%f ",
output[i]);
}
printf("\n");
return 0;
}
C Raspberry PI Zero 1.3 U-Boot bare metal sample
Quick way for bare metal PI Zero C program with U-Boot, only
require a GCC for the
target platform and Das U-Boot, on
Ubuntu :
sudo apt-get install
gcc-arm-linux-gnueabihf
Might work without U-Boot but untested, this will produce a
minimal binary which can be a starting point though but might
require more initialization code without U-Boot and address will be
likely 0x8000 instead of 0x80000.
This produce a
sample.bin
file which can be
copied to a SD card with all the others proprietary PI blobs along
with U-Boot binary and configuration stuff (config.txt
etc.)In U-Boot prompt you can then load and run the binary (can be
automated as well in U-Boot config.) :
fatload usb 0:1 0x80000
sample.bin
go 0x80000
sample.c :
#ifdef d
#!/bin/sh
set -e
rm -f *.o *.elf *.bin
arm-linux-gnueabihf-as --warn --fatal-warnings start.s -o
start.o
arm-linux-gnueabihf-gcc -Wall -O3 -march=armv6 -mtune=arm1176jzf-s
-mfloat-abi=soft -ffreestanding -nostdlib -c sample.c -o
sample.o
arm-linux-gnueabihf-ld -T rpi0.ld -nostdlib start.o sample.o -o
sample.elf
arm-linux-gnueabihf-objcopy sample.elf -O binary sample.img
#arm-linux-gnueabihf-objdump -D -b binary -m arm sample.img
--adjust-vma=0x80000
rm *.o *.elf
wc -c sample.img
exit
#endif
void main() {
while (1) {
}
}
rpi0.ld :
ENTRY(_start)
MEMORY
{
ram : ORIGIN = 0x80000, LENGTH = 0x1000000
}
SECTIONS
{
.text : { *(.text) } > ram
.data : { *(.data) } > ram
.bss : { *(.bss) } > ram
}
start.s :
.global _start
.section .text
_start:
ldr sp, =0x80000
bl main
b .
Can also see standalone
U-Boot examples.
JavaScript : Extended Cistercian numerals (base 16 and binary-like)
p5js code to generate an
extended version of Cistercian
numerals programmatically, this can generate pages of numerals,
this sample display the executable binary of one of my tiny intro
as Cistercian numerals
// modified "Cistercian" numerals :
binary-like and extended to base 16 (1 to 65535 range), a whole
glyph is 16-bit
// the binary like property makes it simpler as the drawing is done
per nibble,
// the 4 original (original = corresponding Cistercian glyph)
features below are
// only needed to draw the rest of the nibble digits by layering /
composition :
// 0001 -> original 1
// 0010 -> original 2
// 0100 -> original 4
// 1000 -> original 6
// then to draw nibble values :
// 0110 -> draw original 2 and draw original 4
// 1001 -> draw original 1 and draw original 6
// then the rest of the nibbles are drawn on the 3 other sides with
conventional order :
// upper right, upper left, lower right, lower left
// can either use vertical stave or a dot
// https://en.wikipedia.org/wiki/Cistercian_numerals
// another fun notation is Bibi-binary :
https://en.wikipedia.org/wiki/Bibi-binary
let b = [
// memph32.com executable binary (DOS 32b)
[
0xb01389d5, 0xd1fd11e9, 0x29ca19c1, 0x60c1e908,
0xc1ea0930, 0xc6cd1061, 0xb40c3fe2, 0xe540ebe2,
0,
0,
0,
0,
0,
0,
0, 0
],
]
function setup() {
createCanvas(682, 564)
background(0)
noLoop()
}
function draw() {
let glylen = 4 // length of a mark
let offset = 22 + 22 * width // draw offset
let spacing = 2 // space between glyph
let line_spacing = 2 // space between lines
let cl = 0 // current line
let stave = false // draw vertical stave ? otherwise draw a
centered dot to identify 0
loadPixels()
for (let ln = 0; ln < b.length; ln += 1) {
let data = b[ln]
let cr = 128 + random(128) | 0
let cg = 128 + random(128) | 0
let cb = 128 + random(128) | 0
// put data on other "pages" when it reach a
treshold
if ((ln + 1) % 12 == 0) offset += 328 - 520 *
width
let x = 0
for (let i = 0; i < data.length; i += 1)
{
let n = b[ln][i]
// wrap line to 16x32 bit value
if (i != 0 && (i & 15) == 0)
{
x = 0
cl += 1
}
let xs = 1
let ys = 1
let oy = cl * ((glylen << 1) +
line_spacing)
let y = oy
for (let b = 1; b < 32; b += 4)
{
let nb = (n >> (15
+ b)) & 15
if (b == 1 || b == 17)
{
xs = 1
ys = 1
y = oy
if (b == 17)
{
x += (glylen << 1) + spacing
}
// draw
stave
if (stave)
{
for (let l = 0; l <= (glylen << 1); l += 1) {
let index = (offset + x + (y + l) * width) * 4
pixels[index + 0] = cr
pixels[index + 1] = cg
pixels[index + 2] = cb
}
} else {
let index = (offset + x + (y + glylen) * width) * 4
pixels[index + 0] = cr
pixels[index + 1] = cg
pixels[index + 2] = cb
}
}
// horizontal flip
if (b == 5 || b == 13 ||
b == 21 || b == 29) {
xs = -1
}
// vertical flip
if (b == 9 || b == 25)
{
xs = 1
ys = -1
y += (glylen
<< 1)
}
// draw nibble features
on previously configured quadrant
if ((nb >> 0) & 1)
{
for (let l =
0; l <= glylen; l += 1) {
let index = (offset + x + l * xs + y * width) * 4
pixels[index + 0] = cr
pixels[index + 1] = cg
pixels[index + 2] = cb
}
}
if ((nb >> 1) & 1)
{
for (let l =
0; l <= glylen; l += 1) {
let index = (offset + x + l * xs + (y + glylen * ys) * width) *
4
pixels[index + 0] = cr
pixels[index + 1] = cg
pixels[index + 2] = cb
}
}
if ((nb >> 2) & 1)
{
for (let l =
0; l <= glylen; l += 1) {
let index = (offset + x + l * xs + (glylen * ys + y - l * ys) *
width) * 4
pixels[index + 0] = cr
pixels[index + 1] = cg
pixels[index + 2] = cb
}
}
if ((nb >> 3) & 1)
{
for (let l =
0; l <= glylen; l += 1) {
let index = (offset + x + glylen * xs + (y + l * ys) * width)
* 4
pixels[index + 0] = cr
pixels[index + 1] = cg
pixels[index + 2] = cb
}
}
}
// next glyph
x += (glylen << 1) +
spacing
}
// next line
cl += 1
}
updatePixels()
}
Bash : Format directory files raw data into an array of hex / 32-bit chunks
This was used as a source to the Cistercian program above to generate my tiny executable binaries as Cistercian glyphs.#!/bin/bash
# Directory containing the binary files
DIRECTORY="/home/binaries"
OUTPUT_FILE="output.txt"
# Clear the output file if it exists
> "$OUTPUT_FILE"
# Loop through all files in the directory
for file in $(find "$DIRECTORY" -type f -exec du -b {} + | sort -nr
| awk '{print $2}'); do
if [ -f "$file" ]; then
filename=$(basename
"$file")
echo "// $filename"
>> "$OUTPUT_FILE"
echo "[" >>
"$OUTPUT_FILE"
# Convert binary file to
hex, format in 32-bit chunks, and modify format
xxd -p -c 4 "$file" |
awk '
{
# Ensure the hex dump is padded to exactly 8 characters
(32-bit)
hex_value = sprintf("0x%08s", $0);
gsub(" ", "0", hex_value); # Replace spaces with zeroes
printf "%s%s", hex_value, (NR % 8 == 0 ? ",\n" : ", ");
}' >>
"$OUTPUT_FILE"
echo "]," >>
"$OUTPUT_FILE" # Closing bracket on a new line
echo "Processed:
$file"
fi
done
echo "All files have been processed and saved in $OUTPUT_FILE."
back to top


