You cannot do this in general, but in some senses, you very much can, and there have been a few historical cases in which you indeed had to.
The Atari 2600 (or Atari Video Computer System) was one of the earliest home video game systems and was first released in 1978. As was common for other systems based on it, the system's 6502 processor and its outputted TV signal were run on a synchronized clock, which means that each CPU cycle corresponded to some portion of the TV signal. This fact was very important for the Atari 2600, because unlike later systems of the era, Atari could not afford to give the device a frame buffer, meaning that the CPU had to run code at every scanline to determine what to produce - if this code took over 17.08 microseconds to run, the graphics would not be properly set before the scanline began drawing them. Worse, if the programmer wanted to draw more complex content than what the Atari normally allowed, they had to measure exact times for instructions and change the graphics registers as the beam was being drawn, with a span of 57.29 microseconds for the whole scan line.
However, the Atari 2600, like many other systems based on the 6502, had a very important feature that enabled the careful time management required for this scenario: the CPU, the RAM, and the TV signal all ran off clocks based on the same master clock. The TV signal ran off a 3.98 MHz clock, portioning the times above into an integer number of "color clocks" that managed the TV signal, and a cycle of the CPU and RAM clocks was exactly three color clocks, allowing the CPU's clock to be an accurate measure of time relative to the current progress TV signal. (For more information on this, check out the Stella Programmer's Guide, written for the Stella Atari 2600 emulator).
This operating environment, in addition, meant that every CPU instruction had a defined amount of cycles it would take in every case, and many 6502 developers published this information in reference tables. For instance, consider this entry for the
CMP (Compare Memory with accumulator) instruction, taken from this table:
CMP Compare Memory with Accumulator
A - M N Z C I D V
+ + + - - -
addressing assembler opc bytes cycles
immediate CMP #oper C9 2 2
zeropage CMP oper C5 2 3
zeropage,X CMP oper,X D5 2 4
absolute CMP oper CD 3 4
absolute,X CMP oper,X DD 3 4*
absolute,Y CMP oper,Y D9 3 4*
(indirect,X) CMP (oper,X) C1 2 6
(indirect),Y CMP (oper),Y D1 2 5*
* add 1 to cycles if page boundary is crossed
Using all of this information, Atari 2600 (and other 6502 developers) were able to determine exactly how long their code was taking to execute, and construct routines that did what they needed and still complied with the Atari's TV signal timing requirements. And because this timing was so exact (especially for time-wasting instructions like NOP), they were even able to use it to modify the graphics as they were being drawn.
Of course, the Atari's 6502 is a very specific case, and all of this is possible only because the system had all of the following:
- A master clock that ran everything, including RAM. Modern systems have independent clocks for the CPU and the RAM, with the RAM clock often being slower and the two not necessarily being in sync.
- No caching of any kind - the 6502 always accessed DRAM directly. Modern systems have SRAM caches that make it more difficult to predict the state - while it is perhaps still possible to predict the behavior of a system with a cache, it is definitely more difficult.
- No other programs running simultaneously - the program on the cartridge had complete control of the system. Modern systems run multiple programs at once using non-deterministic scheduling algorithms.
- A clock speed slow enough that signals could travel across the system in time. On a modern system with clock speeds of 4 GHz (for example), it takes a photon of light 6.67 clock cycles to travel the length of a half-meter motherboard - you could never expect a modern processor to interact with something else on the board in just one cycle, since it takes more than one cycle for a signal on the board to even reach the device.
- A well defined clock speed that rarely changes (1.19 MHz in the case of the Atari) - the CPU speeds of modern systems change all the time, while an Atari could not do this without also affecting the TV signal.
- Published cycle timings - the x86 does not define how long any of its instructions take.
All of these things came together to create a system where it was possible to craft sets of instructions that took an exact amount of time - and for this application, that's exactly what was demanded. Most systems do not have this degree of precision simply because there is no need for it - calculations either get done when they get done, or if an exact amount of time is needed, an independent clock can be queried. But if the need is right (such as on some embedded systems), it can still appear, and you will be able to accurately determine how long your code takes to run in these environments.
And I should also add the big massive disclaimer that all of this only applies to constructing a set of assembly instructions that will take an exact amount of time. If what you want to do is take some arbitrary piece of assembly, even in these environments, and ask "How long does this take to execute?", you categorically cannot do that - that is the Halting Problem, which has been proven unsolvable.
EDIT 1: In a previous version of this answer, I stated that the Atari 2600 had no way of informing the processor of where it was in the TV signal, which forced it to keep the entire program counted and synchronized from the very beginning. As pointed out to me in the comments, this is true of some systems like the ZX Spectrum, but is not true of the Atari 2600, since it contains a hardware register that halts the CPU until the next horizontal blanking interval occurs, as well as a function to begin the vertical blanking interval at will. Hence, the problem of counting cycles is limited to each scanline, and only becomes exact if the developer wishes to change content as the scanline is being drawn.