Skip to content

Instantly share code, notes, and snippets.

@jamesdiacono
Last active October 16, 2024 15:37
Show Gist options
  • Save jamesdiacono/bc9337520727876e09bafaf98225019c to your computer and use it in GitHub Desktop.
Save jamesdiacono/bc9337520727876e09bafaf98225019c to your computer and use it in GitHub Desktop.
The DEC64 number type for Linux (x64 and ARM), MacOS (Intel and Silicon) and Android. Include these files alongside https://github.com/douglascrockford/DEC64.
#!/bin/sh
# Translates DEC64's Windows-compatible MASM on stdin to
# UNIX-compatible NASM on stdout. Not general purpose.
# 0. Use the UNIX calling convention.
# 1. Replace equ with %define.
# 2. Replace public with global.
# 3. Replace unary macro with %macro.
# 4. Replace nullary macro with %macro.
# 5. Replace endm with %endmacro.
# 6. Replace if with %if.
# 7. Replace endif with %endif.
# 8. Replace named with positional parameter.
# 9. Replace segment with section.
# 10. Replace qword with dq.
# 11. Remove execute segment.
# 12. Flatten nested index: [a][b] -> [a+b].
# 13. Remove extraneous suffix matter.
# 14. Remove extraneous suffix matter.
# 15. Remove title.
sed \
-E \
-e "s/^UNIX equ 0/%define UNIX 1/g" \
-e "s/^(\w+)\s+equ\s+(.+)/%define \1 \2/g" \
-e "s/^public /global /g" \
-e "s/^(\w+) macro function/%macro \1 1/g" \
-e "s/^(\w+) macro/%macro \1 0/g" \
-e "s/^ endm/ %endmacro/g" \
-e "s/^ if / %if /g" \
-e "s/^ endif/ %endif/g" \
-e "s/^ (call|jmp)\s+function/ \1 %1/g" \
-e "s/^dec64_data segment para read/dec64_code section .text/g" \
-e "/^dec64_data ends/d" \
-e "s/^ qword/ dq /g" \
-e "/^dec64_code segment para execute/d" \
-e "s/(ptr )?\[(.+?)\]\[(.+?)\]/[\2+\3]/g" \
-e "/^dec64_code ends/d" \
-e "/^ end\b/d" \
-e "/^title /d"
#!/bin/bash
# This script builds and runs the DEC64 tests for an ARM64 Android device. It
# takes no arguments.
# DEC64's ARM source must be tweaked slightly to make it compatible with
# the Android NDK's clang:
# 0. Comments start with a double slash, not a semicolon.
# 1. The global directive, like all directives, is preceeded by a period.
# 2. The area directive is not supported. We do, however, align.
# 3. Labels must be suffixed with a colon.
# 4. An 8 byte constant is declared with .quad rather than dcq.
# 5. When shifting an address offset, an extra comma is required.
# 6. The end directive is unnecessary.
sed \
-E \
-e "s_;_//_g" \
-e "s/global ([a-z0-9_]+) \\[func\\]/.global \1/g" \
-e "s/area dec64, align=8, code, readonly/.align 8/g" \
-e "s/^([a-z0-9_]+)/\1:/g" \
-e "s/dcq/.quad/g" \
-e "s/x([0-9]) lsl 3/x\1, lsl 3/g" \
-e "/ end/d" \
<dec64.s \
>dec64.android.s \
|| exit
build_and_run() {
# Compile, assemble and link a source file into a binary executable, then
# transfer and run that executable on a connected Android device.
src=$1
bin=$2
# The tests shift negative integers on purpose, so we suppress that warning.
"NDK/toolchains/llvm/prebuilt/darwin-x86_64/bin/aarch64-linux-android32-clang" \
-Wno-shift-negative-value \
-o $bin \
dec64_string.c \
dec64_math.c \
dec64.android.s \
$src \
&& adb push ./$bin /data/local/tmp/$bin \
&& adb shell /data/local/tmp/$bin
}
build_and_run dec64_test.c dec64_test \
&& build_and_run dec64_string_test.c dec64_string_test \
&& build_and_run dec64_math_test.c dec64_math_test \
|| exit
# This script has been tested on a Samsung A52 5G device running Android 12,
# using the Android NDK r25b.
#!/bin/sh
# This script builds and runs the DEC64 tests for an x64 machine running MacOS
# (Darwin).
./masm_to_nasm.sh <dec64.asm >dec64.nasm || exit
# Assemble dec64.o. We prefix the function names with an underscore, because
# that is what clang expects.
nasm -f macho64 --prefix _ dec64.nasm || exit
build_and_run() {
# Compile, assemble and link a source file into a binary executable, then run
# it.
# We opt out of creating a position independent executable (a PIE), because we
# depend on absolute addressing. Without passing the linker the -no_pie flag,
# we get a warning like
# PIE disabled. Absolute addressing (perhaps -mdynamic-no-pic) not allowed in
# code signed PIE, but used in pack_increase from dec64.o.
# because of lines in dec64.nasm like
# mov r10, [r10+r9*8]
# The tests shift negative integers on purpose, so we suppress that warning.
src=$1
bin=$2
clang \
-Wl,-no_pie \
-Wno-shift-negative-value \
-o $bin \
dec64_string.c \
dec64_math.c \
dec64.o \
$src \
&& ./$bin
}
# Build and run each test.
build_and_run dec64_test.c dec64_test \
&& build_and_run dec64_string_test.c dec64_string_test \
&& build_and_run dec64_math_test.c dec64_math_test \
|| exit
# This script has been tested on MacOS 11.4 (Big Sur), using NASM
# v2.15.05 and clang 13.0.0.
#!/bin/bash
# This script builds and runs the DEC64 tests for a Macintosh with an Apple
# Silicon processor. It takes no arguments.
# DEC64's ARM source must be tweaked slightly to make it compatible with clang:
# 0. Comments start with a double slash, not a semicolon.
# 1. The global directive, like all directives, is preceeded by a period.
# 2. The area directive is not supported. We do, however, align.
# 3. Labels must be suffixed with a colon.
# 4. An 8 byte constant is declared with .quad rather than dcq.
# 5. When shifting an address offset, an extra comma is required.
# 6. The end directive is unnecessary.
# 7. The names of entrypoints require a leading underscore to link correctly.
sed \
-E \
-e "s_;_//_g" \
-e "s/global ([a-z0-9_]+) \\[func\\]/.global \1/g" \
-e "s/area dec64, align=8, code, readonly/.align 8/g" \
-e "s/^([a-z0-9_]+)/\1:/g" \
-e "s/dcq/.quad/g" \
-e "s/x([0-9]) lsl 3/x\1, lsl 3/g" \
-e "/ end/d" \
-e "s/dec64_/_dec64_/g" \
<dec64.s \
>dec64.silicon.s \
|| exit
build_and_run() {
# Compile, assemble and link a source file into a binary executable, then
# run it.
src=$1
bin=$2
# The tests shift negative integers on purpose, so we suppress that warning.
clang \
-Wno-shift-negative-value \
-o $bin \
dec64.silicon.s \
dec64_string.c \
dec64_math.c \
$src \
&& ./$bin
}
build_and_run dec64_test.c dec64_test \
&& build_and_run dec64_string_test.c dec64_string_test \
&& build_and_run dec64_math_test.c dec64_math_test \
|| exit
# This script has been tested on a 2021 MacBook Pro with an M1 Pro processor.
#!/bin/bash
# This script builds and runs the DEC64 tests for Linux running on a 64-bit
# ARM processor.
# DEC64's ARM source must be tweaked slightly to make it compatible with gcc:
# 0. Comments start with a double slash, not a semicolon.
# 1. The global directive, like all directives, is preceeded by a period.
# 2. The area directive is not supported. We do, however, align.
# 3. Labels must be suffixed with a colon.
# 4. An 8 byte constant is declared with .quad rather than dcq.
# 5. When shifting an address offset, an extra comma is required.
# 6. The end directive is unnecessary.
sed \
-E \
-e "s_;_//_g" \
-e "s/global ([a-z0-9_]+) \\[func\\]/.global \1/g" \
-e "s/area dec64, align=8, code, readonly/.align 8/g" \
-e "s/^([a-z0-9_]+)/\1:/g" \
-e "s/dcq/.quad/g" \
-e "s/x([0-9]) lsl 3/x\1, lsl 3/g" \
-e "/ end/d" \
<dec64.s \
>dec64.linux.s \
|| exit
build_and_run() {
# Compile, assemble and link a source file into a binary executable, then
# run it.
src=$1
bin=$2
gcc \
-o $bin \
dec64.linux.s \
dec64_string.c \
dec64_math.c \
$src \
&& ./$bin
}
build_and_run dec64_test.c dec64_test \
&& build_and_run dec64_string_test.c dec64_string_test \
&& build_and_run dec64_math_test.c dec64_math_test \
|| exit
# This script has been tested on Debian 12 (Bookworm) with gcc v12.2.0.
#!/bin/sh
# This script builds and runs the DEC64 tests for an x64 machine running Linux.
./masm_to_nasm.sh <dec64.asm >dec64.nasm || exit
# Assemble dec64.o.
nasm -f elf64 dec64.nasm || exit
build_and_run() {
# Compile, assemble and link a source file into a binary executable, then
# run it.
# We opt out of creating a position independent executable (a PIE), because we
# depend on absolute addressing. Without passing the the -no-pie flag, we get a
# warning like
# /usr/bin/ld: dec64.o: warning: relocation in read-only section `.text'
# /usr/bin/ld: warning: creating DT_TEXTREL in a PIE
# because of lines in dec64.nasm like
# mov r10, [r10+r9*8]
# We explicitly disable an executable stack to avoid a warning like
# /usr/bin/ld: warning: dec64.o: missing .note.GNU-stack section implies executable stack
src=$1
bin=$2
gcc \
-no-pie \
-z noexecstack \
-o $bin \
dec64_string.c \
dec64_math.c \
dec64.o \
$src \
&& ./$bin
}
# Build and run the tests.
build_and_run dec64_test.c dec64_test \
&& build_and_run dec64_string_test.c dec64_string_test \
&& build_and_run dec64_math_test.c dec64_math_test \
|| exit
# This script has been tested on Debian GNU/Linux 12 (Bookworm), using NASM
# v2.16.01 and gcc v12.2.0.
@jamesdiacono
Copy link
Author

I have just added test_linux_arm.sh.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment