Mon 3 Apr 18:01:54 UTC 2023
See Described.md is newer (also not done at all yet ;)
recently:
https://wokwi.com/projects/361010171246176257
posted with:
Mon 3 Apr 15:34:33 UTC 2023
https://wokwi.com/projects/361000597782398977 or later
I.
// cloop.c
#include "hardware/gpio.h"
#include <Arduino.h>
void experiment_a_asm();
void setup() {
char *ram;
volatile int p = 7; // volatile int p = 7;
ram = (char*)p;
ram--;
experiment_a_asm(ram);
}
void loop() {
while(-1);
}
// ENiD,
----------------------- in assembly ------------
L410-438, sketch.lst:
ldr r3, =COUNT
1000326c: 00f00000 .word 0x00f00000
10003270 <setup>:
void experiment_a_asm();
void setup() {
char *ram;
volatile int p = 7; // volatile int p = 7;
10003270: 2307 movs r3, #7
void setup() {
10003272: b507 push {r0, r1, r2, lr}
volatile int p = 7; // volatile int p = 7;
10003274: 9301 str r3, [sp, #4]
ram = (char*)p;
10003276: 9801 ldr r0, [sp, #4]
ram--;
10003278: 3801 subs r0, #1
experiment_a_asm(ram);
1000327a: f7ff ffea bl 10003252 <experiment_a_asm>
}
1000327e: bd07 pop {r0, r1, r2, pc}
10003280 <loop>:
void loop() {
while(-1);
10003280: e7fe b.n 10003280 <loop>
This is extremely interesting. ;)
The compiler optimized away all the b.s. in the first round (before
asking it to make int p a volatile int). Huge difference.
Try it the other way (backspace over that one word 'volatile') to
see just how different it is.
quick demo:
------------------------- without volatile ------------
same code without 'volatile' (only that one word was erased):
ldr r3, =COUNT
1000326c: 00f00000 .word 0x00f00000
10003270 <setup>:
#include "hardware/gpio.h"
#include <Arduino.h>
void experiment_a_asm();
void setup() {
10003270: b510 push {r4, lr}
char *ram;
int p = 7; // volatile int p = 7;
ram = (char*)p;
ram--;
experiment_a_asm(ram);
10003272: 2006 movs r0, #6
10003274: f7ff ffed bl 10003252 <experiment_a_asm>
}
10003278: bd10 pop {r4, pc}
1000327a <loop>:
void loop() {
while(-1);
1000327a: e7fe b.n 1000327a <loop>
II.
Now look at the changes arising from:
volatile static int p = 7; // volatile int p = 7;
ldr r3, =COUNT
1000326c: 00f00000 .word 0x00f00000
10003270 <setup>:
#include "hardware/gpio.h"
#include <Arduino.h>
void experiment_a_asm();
void setup() {
10003270: b510 push {r4, lr}
char *ram;
volatile static int p = 7; // volatile int p = 7;
ram = (char*)p;
10003272: 4b02 ldr r3, [pc, #8] ; (1000327c <setup+0xc>)
10003274: 6818 ldr r0, [r3, #0]
experiment_a_asm(ram);
10003276: f7ff ffec bl 10003252 <experiment_a_asm>
}
1000327a: bd10 pop {r4, pc}
1000327c: 20000a80 .word 0x20000a80
10003280 <loop>:
void loop() {
while(-1);
10003280: e7fe b.n 10003280 <loop>
III. and drop 'volatile' but keep 'static':
(unwanted optimization - not the outcome sought)
(buzzkill)
void setup() {
10003270: b510 push {r4, lr}
char *ram;
static int p = 7; // volatile int p = 7;
ram = (char*)p;
experiment_a_asm(ram);
10003272: 2007 movs r0, #7
10003274: f7ff ffed bl 10003252 <experiment_a_asm>
}
10003278: bd10 pop {r4, pc}
1000327a <loop>:
void loop() {
while(-1);
1000327a: e7fe b.n 1000327a <loop>
IV. Need to go over it again; however, 'volatile static'
seemed required (both words) to get the intuitive thing going
(allocate a specific address and 'use it' (store stuff in it).
Maybe. Very new to this approach. 3 Apr 2023 11:51 UTC
V. Recently (but not currently):
ldr r3, =COUNT
1000326c: 00f00000 .word 0x00f00000
10003270 <setup>:
#include "hardware/gpio.h"
#include <Arduino.h>
void experiment_a_asm();
void setup() {
10003270: b510 push {r4, lr}
char *ram;
volatile static int p = 7; // volatile int p = 7;
ram = (char*)p;
10003272: 4b02 ldr r3, [pc, #8] ; (1000327c <setup+0xc>)
10003274: 6818 ldr r0, [r3, #0]
experiment_a_asm(ram);
10003276: f7ff ffec bl 10003252 <experiment_a_asm>
}
1000327a: bd10 pop {r4, pc}
1000327c: 20000a80 .word 0x20000a80
10003280 <loop>:
void loop() {
while(-1);
10003280: e7fe b.n 10003280 <loop>
VI. This could be useful:
void setup() {
char *ram;
volatile static int p; // volatile int p = 7;
ram = (char*)p;
p = 233;
experiment_a_asm(ram);
}
Lines 410-432 13:11:04 UTC:
10003268: 00000200 .word 0x00000200
ldr r3, =COUNT
1000326c: 00f00000 .word 0x00f00000
10003270 <setup>:
void setup() {
char *ram;
volatile static int p; // volatile int p = 7;
ram = (char*)p;
p = 233;
10003270: 22e9 movs r2, #233 ; 0xe9
void setup() {
10003272: b510 push {r4, lr}
ram = (char*)p;
10003274: 4b02 ldr r3, [pc, #8] ; (10003280 <setup+0x10>)
10003276: 6818 ldr r0, [r3, #0]
p = 233;
10003278: 601a str r2, [r3, #0]
experiment_a_asm(ram);
1000327a: f7ff ffea bl 10003252 <experiment_a_asm>
}
1000327e: bd10 pop {r4, pc}
10003280: 20001eec .word 0x20001eec
The thinking here is:
(analysis in next saved edit ;)
r2 gets #233 (volatile static int p = 233)
and is wasted. Never used.
Try again (maybe backtrack here if nothing useful found)
VII.
Experimental analysis (the theory is surely wrong but
must start somewhere)
13:49 UTC 3 Apr 2023
ldr r3, =COUNT
1000326c: 00f00000 .word 0x00f00000
10003270 <setup>:
void experiment_a_asm();
void setup() {
char *ram;
volatile static int p; // volatile int p = 7;
ram = (char*)p;
10003270: 4b04 ldr r3, [pc, #16] ; (10003284 <setup+0x14>)
void setup() {
10003272: b510 push {r4, lr}
ram = (char*)p;
10003274: 681a ldr r2, [r3, #0]
p = 233;
10003276: 22e9 movs r2, #233 ; 0xe9
10003278: 601a str r2, [r3, #0]
experiment_a_asm(p);
1000327a: 6818 ldr r0, [r3, #0]
1000327c: f7ff ffe9 bl 10003252 <experiment_a_asm>
}
10003280: bd10 pop {r4, pc}
10003282: 46c0 nop ; (mov r8, r8)
10003284: 20001eec .word 0x20001eec
10003270 <setup>:
void experiment_a_asm();
10003270: 4b04 ldr r3, [pc, #16] ; (10003284 <setup+0x14>)
r3 gets 0x10003270 + 0x14 (0x10003284)
now r3 holds 0x10003284 a 32-bit address in rom
10003272: b510 push {r4, lr}
push guard r4 lr
ram = (char*)p;
10003274: 681a ldr r2, [r3, #0]
r2 gets the contents of rom address 0x10003284, no offset
r2 now holds a 32-bit constant, 0x20001eec
r2 holds 'ram' (a char* pointing to volatile static int p)
So r2 holds a static ram storage location where contents of p,
soon to be #233, is to be stored.
So r2 now holds an integer (p)'s storage location in ram, which
is known to itself (soon) hold #233 (soon but not yet!)
p = 233;
10003276: 22e9 movs r2, #233 ; 0xe9
r2 held 0x20001eec and nothing was done with it yet.
move an expression into r2
That expression is just a constant, #233
end of story on r2.
Can't move a 32-bit value into '#233' (that'd be nonsense)
So the movs instruction here must mean that
the address 0x20001eec receives #233 .. this seems likely
to be correct but is far from proven (here/now).
10003278: 601a str r2, [r3, #0]
r2
nope.
r2 is a register and #233 was moved into it, end of story.
fail. ;)
NEXT: 14:10 UTC
ldr r3, =COUNT
1000326c: 00f00000 .word 0x00f00000
10003270 <setup>:
#include "hardware/gpio.h"
#include <Arduino.h>
void experiment_a_asm();
void setup() {
10003270: b510 push {r4, lr}
push guard r4 lr
char *ram;
volatile static int p; // volatile int p = 7;
ram = (char*)p;
10003272: 4b02 ldr r3, [pc, #8] ; (1000327c <setup+0xc>)
r3 gets contents of rom address 0x10003270, offset #8 (0x1000327c)
1000327c: 20001eec .word 0x20001eec
r3 now holds a 32-bit ram address, 0x20001eec
char *ram;
volatile static int p; // volatile int p = 7;
ram = (char*)p;
10003274: 6818 ldr r0, [r3, #0]
r0 gets contents of 0x20001eec
.. which have never been defined. ;)
NOT BAD.
14:23 UTC next:
ldr r3, =COUNT
1000326c: 00f00000 .word 0x00f00000
10003270 <setup>:
void setup() {
char *ram;
volatile static int p; // volatile int p = 7;
ram = (char*)p;
p = 233;
10003270: 22e9 movs r2, #233 ; 0xe9
void setup() {
10003272: b510 push {r4, lr}
ram = (char*)p;
10003274: 4b02 ldr r3, [pc, #8] ; (10003280 <setup+0x10>)
10003276: 6818 ldr r0, [r3, #0]
p = 233;
10003278: 601a str r2, [r3, #0]
experiment_a_asm(ram);
1000327a: f7ff ffea bl 10003252 <experiment_a_asm>
}
1000327e: bd10 pop {r4, pc}
10003280: 20001eec .word 0x20001eec
10003284 <loop>:
void loop() {
while(-1);
10003284: e7fe b.n 10003284 <loop>
...
10003288 <_ZN6RP204015_SystickHandlerEv>:
10003270 <setup>:
void setup() {
char *ram;
volatile static int p; // volatile int p = 7;
ram = (char*)p;
p = 233;
10003270: 22e9 movs r2, #233 ; 0xe9
r2 ( a register with no init at all so far ) gets a const #233
void setup() {
10003272: b510 push {r4, lr}
ram = (char*)p;
10003274: 4b02 ldr r3, [pc, #8] ; (10003280 <setup+0x10>)
r3 gets contents of rom address 0x10003270, offset of #8 (0x10003280)
10003280: 20001eec .word 0x20001eec
r3 now holds a 32-bit ram address, 0x20001eec
ram = (char*)p;
10003274: 4b02 ldr r3, [pc, #8] ; (10003280 <setup+0x10>)
10003276: 6818 ldr r0, [r3, #0]
r0 gets contents of address held by r3 with no offset.
r0 now holds nothing initialized at all. Oops.
NEXT 14:46 UTC:
void setup() {
char *ram;
volatile static int p; // volatile int p = 7;
p = 233;
ram = (char*)p;
experiment_a_asm(ram);
}
10003268: 00000200 .word 0x00000200
ldr r3, =COUNT
1000326c: 00f00000 .word 0x00f00000
10003270 <setup>:
void experiment_a_asm();
void setup() {
char *ram;
volatile static int p; // volatile int p = 7;
p = 233;
10003270: 22e9 movs r2, #233 ; 0xe9
void setup() {
10003272: b510 push {r4, lr}
p = 233;
10003274: 4b02 ldr r3, [pc, #8] ; (10003280 <setup+0x10>)
10003276: 601a str r2, [r3, #0]
ram = (char*)p;
10003278: 6818 ldr r0, [r3, #0]
experiment_a_asm(ram);
1000327a: f7ff ffea bl 10003252 <experiment_a_asm>
}
1000327e: bd10 pop {r4, pc}
10003280: 20001eec .word 0x20001eec
10003284 <loop>:
void loop() {
while(-1);
10003284: e7fe b.n 10003284 <loop>
Now look. Describe. ;) 14:48 UTC:
10003270 <setup>:
void experiment_a_asm();
void setup() {
char *ram;
volatile static int p; // volatile int p = 7;
p = 233;
10003270: 22e9 movs r2, #233 ; 0xe9
r2 ( a register with no init at all so far ) gets a const #233
ram = (char*)p;
10003274: 4b02 ldr r3, [pc, #8] ; (10003280 <setup+0x10>)
r3 gets contents of rom address 0x10003270, offset of #8 (0x10003280)
10003280: 20001eec .word 0x20001eec
r3 now holds a 32-bit ram address, 0x20001eec
okay going to use r2 now:
p = 233;
10003276: 601a str r2, [r3, #0]
r3 gets #233 - 'store #233 into 0x20001eec, a ram address, no offset'
So we don't even care about this #233 anymore as it is now held
in ram.
Is this ram location the same as p? sure looks like it.
ram = (char*)p;
10003278: 6818 ldr r0, [r3, #0]
r0 gets rut roh it gets #233 so its address is lost.
experiment_a_asm(ram);
1000327a: f7ff ffea bl 10003252 <experiment_a_asm>
tough crowd. Trying 'address of' this time ('&').
Monday 3 Apr 15:01:52 UTC 2023:
void setup() {
char *ram;
volatile static int p; // volatile int p = 7;
p = 233;
ram = (char*)p;
experiment_a_asm(&ram);
}
10003268: 00000200 .word 0x00000200
ldr r3, =COUNT
1000326c: 00f00000 .word 0x00f00000
10003270 <setup>:
#include "hardware/gpio.h"
#include <Arduino.h>
void experiment_a_asm();
void setup() {
10003270: b507 push {r0, r1, r2, lr}
char *ram;
volatile static int p; // volatile int p = 7;
p = 233;
10003272: 22e9 movs r2, #233 ; 0xe9
10003274: 4b03 ldr r3, [pc, #12] ; (10003284 <setup+0x14>)
ram = (char*)p;
experiment_a_asm(&ram);
10003276: a801 add r0, sp, #4
p = 233;
10003278: 601a str r2, [r3, #0]
ram = (char*)p;
1000327a: 681b ldr r3, [r3, #0]
1000327c: 9301 str r3, [sp, #4]
experiment_a_asm(&ram);
1000327e: f7ff ffe8 bl 10003252 <experiment_a_asm>
}
10003282: bd07 pop {r0, r1, r2, pc}
10003284: 20001eec .word 0x20001eec
3284 is new pc offset computed and still holds 0x20001eec
10003270 <setup>:
#include "hardware/gpio.h"
#include <Arduino.h>
void experiment_a_asm();
void setup() {
10003270: b507 push {r0, r1, r2, lr}
that wasn't expected. ;)
char *ram;
volatile static int p; // volatile int p = 7;
p = 233;
10003272: 22e9 movs r2, #233 ; 0xe9
r2 ( a register with no init at all so far ) gets a const #233
char *ram;
volatile static int p; // volatile int p = 7;
p = 233;
10003274: 4b03 ldr r3, [pc, #12] ; (10003284 <setup+0x14>)
r3 gets contents of rom address 0x10003270, offset of #12 (0x10003284)
10003284: 20001eec .word 0x20001eec
r3 now holds a 32-bit ram address, 0x20001eec
ram = (char*)p;
experiment_a_asm(&ram);
10003276: a801 add r0, sp, #4
p = 233;
10003278: 601a str r2, [r3, #0]
ram = (char*)p;
1000327a: 681b ldr r3, [r3, #0]
1000327c: 9301 str r3, [sp, #4]
abandon this. ;)
NEXT: 15:17 UTC trafalmador
10003268: 00000200 .word 0x00000200
ldr r3, =COUNT
1000326c: 00f00000 .word 0x00f00000
10003270 <setup>:
void experiment_a_asm();
void setup() {
char *ram;
volatile static int p; // volatile int p = 7;
p = 233;
10003270: 22e9 movs r2, #233 ; 0xe9
void setup() {
10003272: b510 push {r4, lr}
p = 233;
10003274: 4b03 ldr r3, [pc, #12] ; (10003284 <setup+0x14>)
10003276: 601a str r2, [r3, #0]
ram = (char*)p;
10003278: 681b ldr r3, [r3, #0]
uint32_t addr = *ram ;
1000327a: 7818 ldrb r0, [r3, #0]
experiment_a_asm(addr);
1000327c: f7ff ffe9 bl 10003252 <experiment_a_asm>
}
10003280: bd10 pop {r4, pc}
10003282: 46c0 nop ; (mov r8, r8)
10003284: 20001eec .word 0x20001eec
10003288 <loop>:
That's looking very good now. ;)
END.