diff options
author | Lizzy Fleckenstein <eliasfleckenstein@web.de> | 2023-08-20 10:34:13 +0200 |
---|---|---|
committer | Lizzy Fleckenstein <eliasfleckenstein@web.de> | 2023-08-20 10:34:13 +0200 |
commit | 8da018940e0570ff43d9d94b964ca1470009baec (patch) | |
tree | 1ea9ac1178d5868bddc979618cd4b40cc8c80f38 | |
parent | 26355173f710eea899f55c96cb7dc5f3b5a3bf42 (diff) | |
download | paradox-8da018940e0570ff43d9d94b964ca1470009baec.tar.xz |
document pointer arithmetic
-rw-r--r-- | README.md | 53 |
1 files changed, 49 insertions, 4 deletions
@@ -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). |