Sat 8 Apr 21:45:49 UTC 2023
https://wokwi.com/projects/361477027261167617
100032b2: 4c09 ldr r4, [pc, #36] ; (100032d8 <setup+0x48>)
100032d8: 200015d8 .word 0x200015d8
saw this in Serial Monitor:
unsigned int ram = (unsigned int) &c;
unsigned int *rptr;
rptr = (unsigned int *) ram;
sprintf(buffer, "%4x", rptr);
Serial1.println(buffer);
Confirmation bias: think it has the right thing but
could be operational for the wrong reason.
How to prove it was passed the address and not some
8-bit value as is the concern. Trying to not pass that
value but rather passing the address of the int that
holds that value.
Older:
Seemed like 'it worked' as wanted - gained an 8-bit
value from ram storage, to say how many blinks the
LED does.
The earlier success was based on passing not an address
but an integer to the asm routine.
Present effort appears to use the storage address which
idk it learns during compilation.
None of these explanations are to be viewed as accurate.
Notes to self. Conjectures only. ;)
See Described.md is newer (also not done at all yet ;)
recently:
Mon 3 Apr 20:22:49 UTC 2023
https://wokwi.com/projects/361031383558845441
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.