That's pretty much a reproducible, simple task, that u could write for Basic, Pascal, C, and pretty much any script/compile/interpret language. The syntax of the loop is the only thing that would need massaging. Some may need variable declaration.
Yeah it'll give u an average of how long it would take the interpreted code, but the difference between the simplest of instruction and the resulting machine language can be enormous.
If it was wholey necessary to use a higher level language to write the program, something like C gives u the ability to include assembly into ur coding. This way u can have all ur bs coding for window gadgets, requesters etc, with something like a 'run' button that u could use for the user to run ur assembly.
Assembly, 68k being my favourite after 6502 - but looks pretty much the same in all machine languages as it's a merely simple loop:
move.l $counter_address, d0
move.l #$98967f, d1; (10000000 -1)
loop: add.b #$01,d2
dbra d1, loop
sub.l $counter_address,d0
rts
This will return d0 as the time it took to complete the loop. U can do what u like with d0 after that in the higher level language.
Problem u have is that there isn't a simple one command for adding. U have longword, word and byte wize adding in 68k, similarly other machine languages have their variations, especially 32 & 64bit even psuedo 32bit on 16bit machines.
If u look at a machine language reference manual, generally a small pocket book that details all the processors instructions, it'll give u clock times that it takes to execute each command and it's l/w/b variation.
Similarly other machine languages won't have simple instructions like dbra, which is decrease and branch (goto) if the result isn't negative. Without that u would have to contaminate ur study further with subtract 1 from the 10000000 value with a seperate compare command and another branch command - something that compilers do if ur lucky and I believe 8086 still does.
What we're saying here is that u wouldn't be averaging the time to execute an addition command, it's addition and the commands that control the loop.
Theoretically, if u did:
move.l $counter_address, d3
move.l #$98967f, d1; (10000000 -1)
loop1: dbra d1, loop1
sub.l $counter_address,d3
move.l $counter_address, d0
move.l #$98967f, d1; (10000000 -1)
loop2: add.b #$01,d2
dbra d1, loop2
sub.l $counter_address,d0
sub.l d3,d0
rts
U would be taking the time to do a loop with no instruction in it away from the one with the addition instruction. This 'should' negate the loop command timing.
(ofc, prior to calling this/these routines, the original values of the d0-d3 variables will be saved)
Now, in comparison to this, u can test a read from memory address command. In theory, this tests memory reading. Again u can have byte, word and longword variations, but just changing the loop to:
move.l $counter_address, d3
move.l #$98967f, d1; (10000000 -1)
loop1: dbra d1, loop1
sub.l $counter_address,d3
move.l $counter_address, d0
move.l #$98967f, d1; (10000000 -1)
loop2: move.b $random-memory-location-in-free-memory-pool,d2
dbra d1, loop2
sub.l $counter_address,d0
sub.l d3,d0
rts
Here u will have 2 values that will define bytewize command speeds. iirc, byte operations and word operations are said to take the same time.
This ofc is complete bs if ur wishing to just use a loop scripted or compiled using ur example.
What I may suggest is to make a bad example that much more identifying to the add++ command, u could similarly do:
t=clock();
for i=1:10000000
{
}
T1= clock() - t;
t=clock();
for i=1:10000000
{
j++;
}
T2= clock() - t - T1;
Here again u've done ur best to remove the time it takes the pc to do just the loop itself without a command. Myself I would dislike it's overall accuracy cos of what the machine language looks like after a compile, but it'd be the best attempt in a higher level language.