# ARM Thumb, no div instructions, 43 bytes

`f7ff fffe` represents placeholders for libc calls, to `scanf` and `printf` respectively.

```lang-none
b503 4669 a008 f7ff fffe bc03 2802 d907
2202 0001 1a89 d003 d8fc 3201 4282 d1f8
a001 f7ff fffe bd00 6425 00
```

Assembly code:
```lang-armasm
        .globl main
        .thumb
        .thumb_func
main:
        push    {r0, r1, lr}
        mov     r1, sp
        adr     r0, printf_scanf_str
        bl      scanf
        pop     {r0, r1}
        cmp     r0, #2
        bls     .Ltrue
        movs    r2, #2
.Lloop1:
        movs    r1, r0
.Ldivloop:
        subs    r1, r2
        beq     .Lfalse
        bhi     .Ldivloop
.Ldivloop_end:
        adds    r2, #1
        cmp     r2, r0
        bne     .Lloop1
.Ltrue:
        @ movs    r1, #1 @ optional, needs odd load address but will print 1 instead of a random nonzero value
.Lfalse:
        adr     r0, printf_scanf_str
        bl      printf
        pop     {pc}

printf_scanf_str:
        .asciz "%d"
```

Accepts a number from stdin, and prints nonzero if it is a prime, or zero if it isn't.

### Walkthrough

Behold, the world's least efficient prime searcher.

It is a brute force modulo check using a subtraction loop with zero shortcuts.

<hr/>

Here, we use a trick with `push` to make space for the `scanf` output *and* save the link register.

`push` will subtract from `sp` and store the registers in ascending order in memory.

So for example, `push {r0, r1, lr}` will end up like this:
```lang-none
| sp + 0 | sp + 4 | sp + 8 |
| argc   | argv   | return |
```
We don't actually care about `argc` - we care about the space on `sp`. We can then just pass the stack pointer directly to `scanf`.

We do sorta care about `argv`. Not about what it points to, but that it is a valid (non-zero) pointer.

`scanf("%d", &r0)`

```lang-armasm
main:
        push    {r0, r1, lr}
        mov     r1, sp
        adr     r0, printf_str
        bl      scanf
```
Then, we can `pop` the result from `scanf` we stored into `r0`, and `argv` into `r1` as the "non-zero" value for our short circuit loop.

```lang-armasm
        pop     {r0, r1}
```
Immediately return true for values <= 2.
```lang-armasm
        cmp     r0, #2
        bls     .Ltrue
```
Begin factorizing against 2.
```lang-armasm
        movs    r2, #2
```
Use a subtraction loop on a copy of `r0` to check if `r0 % r2 == 0`.

Specifically, the `subs` will reach zero on an even multiple and set the zero flag (which corresponds to the `eq` condition). Otherwise, we loop until it underflows (not `hi`)

```lang-armasm
.Lloop1:
        movs    r1, r0
.Ldivloop:
        subs    r1, r2
        beq     .Lfalse
        bhi     .Ldivloop
```
Increment the number we factor against and loop if it is not equal to `r0`.
```lang-armasm
.Ldivloop_end:
        adds    r2, #1
        cmp     r2, r0
        bne     .Lloop1
```
Optionally, with the `true` condition, we set `r1` to `1` if it is a prime. 

But non-zero is "truthy" enough for us even if it is a little ugly. It will either be the last inverted modulo we tested, or the address of `argv`, all of which will be non-zero.

Due to how our subtraction loop works, by the time we jump to `.Lfalse`, `r1` will already be zero.

```lang-armasm
.Ltrue:
        @ movs    r1, #1 @ optional, needs odd load address but will print 1 instead of a random nonzero value
.Lfalse:
```
`r1` is already conveniently (and intentionally) in the right place to forward directly to `printf`, and all we need to do is reload the printf/scanf string to `r0` (no easy way around this) and call `printf`.

Note that due to how `pop` works in Thumb, it isn't really that useful to do tail calls.

```lang-armasm
        adr     r0, printf_scanf_str
        bl      printf
```
Last, pop the return address from `lr` we `push`ed earlier directly into the program counter to return from `main`.
```lang-armasm
        pop     {pc}
```