Most users are probably using Raspbian on their Raspberry Pi 3. However, Raspbian is designed for all Raspberry Pi devices, back to the original Raspberry Pi, which is ARMv6 with an FPU. This does not take advantage of the 64-bit support on the ARMv8 CPU on the Raspberry Pi 3.
Debian has offered ARM64 support for a while, and being the base distribution for Raspbian, is quite similar. Conveniently, there is a pre-built Debian image for Raspberry Pi 3. You can download it and copy it to a SD card, and it should work out of the box.
On Linux, the simple
dd command showed on the Debian Wiki works. On other platforms, notably Windows, Etcher is reputed to work well and has an easy interface.
The one flaw with this image is that the WiFi does not work.
Update: The 20180108 image now works with WiFi out of the box. The following instructions are no longer necessary.
ARM is unusual among the processors by having the program counter available as a “general purpose” register. Most other processors have the program counter hidden, and its value will only be disclosed as the return address when calling a function. If you want to modify it, a jumping instruction is used.
For example, on the x86, the program counter is called the instruction pointer, and is stored in
eip, which is not an accessible register. After a function call,
eip is pushed onto the stack, at which point it could be examined. Return is done through the
ret instruction which pops the return address off the stack, and jumps there.
Another example: on the MIPS, the program counter is stored into register
31 after executing a
JALR instruction, which is used for function calling. The value in there can be examined, and a return is a register jump
JR to that register.
ARM’s unusual design allows many, many ways of returning from functions. But first, we must understand how function calls work on the ARM.
Sometimes, after many attempts, you realized that to complete your mission, you must access
private fields, or perhaps change
There are many reasons imaginable: the accessors copy the entire object before returning, and that takes a very long time, the authors forgot to provide an accessor, the library function is highly inefficient and you need to do better, …
Are you out of luck? Fortunately, no.
As most probably know, DMOJ uses a sandbox to protect itself from potentially malicious user submissions. An overview of the Linux sandbox has been published by my friend Tudor. However, it doesn’t go deep into the implementation details, many of which differ between Linux and FreeBSD.
At its core, the sandbox,
cptbox, uses the
ptrace(2) API to intercept system calls before and after they are executed, denying access and manipulating results. The core is written in C, hence the name
Perhaps the most obvious difference between Linux and FreeBSD is that on Linux,
ptrace(2) subfunctions are invoked as
ptrace(PTRACE_*), while on FreeBSD, it is
ptrace(PT_*). But this difference is rather superficial compared to the significant internal differences.
Most people, when first starting assembly, still carry over a lot of high level constructs in their assembly programs. A common pattern is to multiply and divide when a bit shift would suffice.
For example, a lot of people would write a program to write out the binary representation of an integer using the divide and modulo operations. This is rather inefficient compared to using shifts. For example, the divide by 2 can be replaced with a right shift by 1, and modulo 2 can be replaced by a bitwise AND with 1.
Aside: interestingly, taking any number modulo a power of two
m is equivalent to doing a bitwise AND with
m-1. The proof of this is left as an exercise for the reader.
This post will address the basics you need to know about shifts to get up to speed on writing good assembly.