userland: add assembly support

Move arm assembly cheat here, and start some work on x86 cheat as well.
This commit is contained in:
Ciro Santilli 六四事件 法轮功
2019-03-22 00:00:00 +00:00
parent 4943c9ed2e
commit 287c83f3f9
117 changed files with 3870 additions and 547 deletions

17
userland/arch/arm/c/add.c Normal file
View File

@@ -0,0 +1,17 @@
/* 1 + 2 == 3 */
#include <assert.h>
#include <inttypes.h>
int main(void) {
uint32_t in0 = 1, in1 = 2, out;
__asm__ (
"add %[out], %[in0], %[in1];"
: [out] "=r" (out)
: [in0] "r" (in0),
[in1] "r" (in1)
);
assert(in0 == 1);
assert(in1 == 2);
assert(out == 3);
}

1
userland/arch/arm/c/build Symbolic link
View File

@@ -0,0 +1 @@
../build

View File

@@ -0,0 +1 @@
../build

View File

@@ -0,0 +1,35 @@
#include <inttypes.h>
void _start(void) {
uint32_t exit_status;
/* write */
{
char msg[] = "hello\n";
uint32_t syscall_return;
register uint32_t r0 __asm__ ("r0") = 1; /* stdout */
register char *r1 __asm__ ("r1") = msg;
register uint32_t r2 __asm__ ("r2") = sizeof(msg);
register uint32_t r8 __asm__ ("r7") = 4; /* syscall number */
__asm__ __volatile__ (
"svc 0;"
: "+r" (r0)
: "r" (r1), "r" (r2), "r" (r8)
: "memory"
);
syscall_return = r0;
exit_status = (syscall_return != sizeof(msg));
}
/* exit */
{
register uint32_t r0 __asm__ ("r0") = exit_status;
register uint32_t r7 __asm__ ("r7") = 1;
__asm__ __volatile__ (
"svc 0;"
: "+r" (r0)
: "r" (r7)
:
);
}
}

15
userland/arch/arm/c/inc.c Normal file
View File

@@ -0,0 +1,15 @@
/* Increment a variable in inline assembly. */
#include <assert.h>
#include <inttypes.h>
int main(void) {
uint32_t my_local_var = 1;
__asm__ (
"add %[my_local_var], %[my_local_var], #1;"
: [my_local_var] "+r" (my_local_var)
:
:
);
assert(my_local_var == 2);
}

View File

@@ -0,0 +1,28 @@
/* https://stackoverflow.com/questions/53960240/armv8-floating-point-output-inline-assembly */
#include <assert.h>
int main(void) {
float my_float = 1.5;
__asm__ (
"vmov s0, 1.0;"
"vadd.f32 %[my_float], %[my_float], s0;"
: [my_float] "+t" (my_float)
:
: "s0"
);
assert(my_float == 2.5);
/* Undocumented %P
* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89482
*/
double my_double = 1.5;
__asm__ (
"vmov.f64 d0, 1.0;"
"vadd.f64 %P[my_double], %P[my_double], d0;"
: [my_double] "+w" (my_double)
:
: "d0"
);
assert(my_double == 2.5);
}

View File

@@ -0,0 +1,32 @@
/* Like inc.c but less good since we do more work ourselves.
*
* Just doing this to test out the "m" memory constraint.
*
* GCC 8.2.0 -O0 assembles ldr line to:
*
* ....
* ldr r0, [fp, #-12]
* ....
*
* and `-O3` assembles to:
*
* ....
* ldr r0, [sp]
* ....
*/
#include <assert.h>
#include <inttypes.h>
int main(void) {
uint32_t my_local_var = 1;
__asm__ (
"ldr r0, %[my_local_var];"
"add r0, r0, #1;"
"str r0, %[my_local_var];"
: [my_local_var] "+m" (my_local_var)
:
: "r0"
);
assert(my_local_var == 2);
}

View File

@@ -0,0 +1,25 @@
/* GCC 8.2.0 -O0 and -O3 assembles ldr line to:
*
* ....
* movw r3, #<lower address part>
* movt r3, #<higher address part>
* ldr r0, [r3]
* ....
*/
#include <assert.h>
#include <inttypes.h>
uint32_t my_global_var = 1;
int main(void) {
__asm__ (
"ldr r0, %[my_global_var];"
"add r0, r0, #1;"
"str r0, %[my_global_var];"
: [my_global_var] "+m" (my_global_var)
:
: "r0"
);
assert(my_global_var == 2);
}

View File

@@ -0,0 +1,38 @@
/* https://github.com/cirosantilli/arm-assembly-cheat#register-variables */
#include <assert.h>
#include <inttypes.h>
int main(void) {
register uint32_t r0 __asm__ ("r0");
register uint32_t r1 __asm__ ("r1");
uint32_t new_r0;
uint32_t new_r1;
{
/* We must set the registers immediately before calling,
* without making any function calls in between.
*/
r0 = 1;
r1 = 2;
__asm__ (
/* We intentionally use an explicit r0 and r1 here,
* just to illustrate that we are certain that the
* r0 variable will go in r0. Real code would never do this.
*/
"add %[r0], r0, #1;"
"add %[r1], r1, #1;"
/* We have to specify r0 in the constraints.*/
: [r0] "+r" (r0),
[r1] "+r" (r1)
:
:
);
/* When we are done, we must immediatly assign
* the register variables to regular variables.
*/
new_r0 = r0;
new_r1 = r1;
}
assert(new_r0 == 2);
assert(new_r1 == 3);
}