I've only used the STM32 series a little but can't think how it would be possible to make it totally clock independent. You could read the PLL settings but wouldn't have a way to know the crystal frequency without another time reference. There might be a few tricks I'm not aware of using things like the internal RC oscillator in the watchdog and other peripherals to provide that external reference but I'm not sure if it would be worth it and the accuracy wouldn't be as good as using a value calculated from the crystal frequency.
Personally I'd either read the family guide and calculate how many cycles the loop should take and calculate the constant from that if fairly high accuracy was required or otherwise just take a guess at the initial value and call with a fairly high value like 1000mS and measure with a scope how long it's really taking and adjust from there.
In your case you mentioned milliseconds (although above code mentions microseconds) so your constant would be fairly large so maybe you could use something like the following without introducing an unacceptable amount of error:
#define STM32_CLOCK_HZ 72000000UL
#define STM32_CYCLES_PER_LOOP 6 // This will need tweaking or calculating
void delay_ms(const uint32_t ms)
ms *= STM32_CLOCK_HZ / 1000 / STM32_CYCLES_PER_LOOP;
asm volatile(" mov r0, %[ms] \n\t"
"1: subs r0, #1 \n\t"
" bhi 1b \n\t"
: [ms] "r" (ms)
At least then you have an easy to read / update constant for the real clock rate of the system.