aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLizzy Fleckenstein <eliasfleckenstein@web.de>2023-08-20 10:34:13 +0200
committerLizzy Fleckenstein <eliasfleckenstein@web.de>2023-08-20 10:34:13 +0200
commit8da018940e0570ff43d9d94b964ca1470009baec (patch)
tree1ea9ac1178d5868bddc979618cd4b40cc8c80f38
parent26355173f710eea899f55c96cb7dc5f3b5a3bf42 (diff)
downloadparadox-8da018940e0570ff43d9d94b964ca1470009baec.tar.xz
document pointer arithmetic
-rw-r--r--README.md53
1 files changed, 49 insertions, 4 deletions
diff --git a/README.md b/README.md
index 71cad2c..966e2f2 100644
--- a/README.md
+++ b/README.md
@@ -45,15 +45,23 @@ diff paradox paradox2
## Additional notes
+### run.sh
+
For convenience and in accordance with the CG spec, paradox includes a `run.sh` script that will automatically compile and execute a file.
```sh
./run.sh my_file.false
```
-Syntax errors are emitted as `%fatal` NASM-directives, so you will see them at the assembly stage.
+### Error handling
+
+Due to lack of `stderr` access in FALSE, syntax errors are emitted as `%fatal` NASM-directives, so you will see them at the assembly stage. `bootstrap.lua` uses stderr and a nonzero exit code to signal errors.
+
+### I/O Buffering
-Paradox issues syscalls for I/O directly without buffering; ß/B are no-ops in paradox.
+Paradox currently does not buffer I/O (using syscalls directly) but will do so in the future. B/ß are no-ops.
+
+### Inline assembly
Paradox has its own inline assembly syntax: anything between backticks is emitted as assembly, like so:
@@ -71,6 +79,43 @@ syscall
The output should be just "hi", without "bye".
-## A challenge for the reader
+### Pointer arithmetic
+
+Paradox (coincidentally) supports pointer arithmetic. Pointers and numbers can be added and subtracted using `+` and `-`.
+
+Note that addition and subtraction (as well as other arithmetic and bitwise operations) operate on 32-bit numbers while pointers are 64-bit, so it will only work reliably as long as the pointers are in the appropriate range.
+
+ `;` can be used to read from a pointer; `:` can be used to write to a pointer. Both operations read/write 64 bits.
+
+To read and write individual bytes, one can use bitwise operations.
+
+Variables and lambdas are pointers.
+
+#### String pointers
+
+`["my_stringy"]$12+;$@21+;+\[$@$@>][1-$;,\]#%%10,` will print my_stringy in reverse (ygnirts_ym). This works with any string. This is due to the binary layout of lambdas containing a single string (consisting of just a syscall to print out the string):
+
+```
+0000000000401002 <fun_1>:
+ 401002: b8 01 00 00 00 mov eax,0x1
+ 401007: bf 01 00 00 00 mov edi,0x1
+ 40100c: 48 be 1e 10 40 00 00 movabs rsi,0x40101e
+ 401013: 00 00 00
+ 401016: ba 0a 00 00 00 mov edx,0xa
+ 40101b: 0f 05 syscall
+ 40101d: c3 ret
+```
+
+A pointer to the string is stored at offset 12, and the length is stored at offset 21.
+
+Strings are stored in the data section, so it is possible to write to them.
+
+It is possible to make memory allocations using strings by compiling your program like so:
+
+```sh
+(echo "[\"$(head -c YOUR_ALLOCATION_SIZE /dev/zero)\"]" && cat your_source_file.false) | ./paradox
+```
+
+In the program, you can then use `12+;` at the beginning of the file to extract a pointer to your allocation.
-Check the output of `["my_stringy"]$12+;$@21+;+\[$@$@>][1-$;,\]#%%10,`. Replace my_stringy by a different string and check the output. Try to make sense of how & why this works.
+Since all operations fetch 64-bits, it is recommended to set the allocation size to 7 bytes higher than desired (if you wish to fetch/write the last few bytes of the allocation individually).