5

I have the following assembly code for 8086

MOV AL, [BX]
OUT DX, AL

The bus clock frequency is 1MHz. Access to memory is done without WAIT, and to I/O with one WAIT tick. How I can calculate the duration of this program?

2
  • 8
    It depends how many wait states the IO access is set to have on the hardware. The question is not answerable. The standard values are in the CPU hardware manual.
    – Justme
    Commented Nov 22, 2020 at 13:24
  • 1
    This looks suspiciously like unattempted homework, especially given the 1 MHz clock which points towards a microcomputer "trainer" and not a useful system. Additionally it's not really a retrocumputing question, just a bad question about what happens to be a fairly old chip. Commented Nov 23, 2020 at 22:14

3 Answers 3

7

I have the following assembly code for 8086

To start with basic timing for 8086 (*1) in CPU clocks is 21 clock cycles.

MOV AL,[BX] (*2)

13 cycles, consisting of 8 cycles for the instruction (MOV reg8,mem) plus 5 to calculate the address from [BX]. Since it's a byte access, no penalty for misalignment can happen.

OUT DX, AL

8 cycles, all for the instruction.

In addition it depends on the prefetch queue being filled or not, as code fetches are additional. Above code is 3 bytes (8A 07 EE), so two code fetches are necessary. Depending on the prior instructions they could be already loaded, adding zero cycles, or 4 additional cycles per fetch, adding 4 or 8 cycles total.

Since move's 13 clocks leaves a lot of room (only 4 are needed to get the data), the OUT usually can be fetched in parallel, leaving the total penalty here at 0 or 4 CPU clocks. In real world application the queue is rarely empty, as only a few high performance instructions can empty it when executed in sequence.

Base line: Prefetch wait is usually zero and thus doesn't matter, and if it does, one needs to analyze the instructions before that sequence.

The bus clock frequency is 1MHz.

Is that memory cycle or CPU clock? These are not the same and bus clock is an ambiguous term here.

Access to memory is done without WAIT, and to I/O with one WAIT tick.

What is a 'Wait tick'? Mind to specify it, preferably in CPU clocks?

How I can calculate the duration of this program?

As usual by adding up the clock cycles and multiply them by the clock period used.


*1 - If your question is about an 8088, as used in the original PC, then it's actually 29, as described here.

*2 - Please do not use white-spaces within parameters. Even if your assembler copes with it, it may introduce incompatibilities and hard to correct problems when using a different environment.

1
  • 1
    I thought the only 8086 instructions took different lengths of time from 8088 ones in the absence of prefetch delays were aligned 16-bit loads and stores. Since both the load and store use 8-bit operands, I don't see a basis for disparity there. Also, I don't think it's exactly uncommon for even the 8086 prefetch queue to run dry. Something like add reg,immed16 will gobble two words from the prefetch queue but only have time to reload one. Memory operands may be a net prefetch gain, but most register operands will represent a net prefetch loss, even if not a full word's worth.
    – supercat
    Commented Nov 23, 2020 at 5:00
12

On the 8088 and 8086, execution involves two parallel processes--memory access and internal computation--and will be limited by the speed of whichever is slower. Generally, on the 8088 execution speed will be limited by memory access, while the 8086 will be better balanced. Every memory cycle on the 8088 or 8086 takes a minimum of four cycles, and on most machines they will usually take exactly four cycles except when e.g. accessing display-card memory, or when a DRAM refresh occurs [which may be thought of as introducing a few spontaneous memory accesses beyond those issued by the CPU; while there are situations where it may be possible to arrange DRAM refreshes to occur exactly once per loop with predictable timing, it's usually best to think of it as some additional overhead that can't be precisely predicted, but is small in any case].

Any time the main CPU isn't asking for a memory access and there fewer than four bytes (8088) or three two-byte words (8086) of code have been fetched ahead of the current execution point, the prefetch unit will initiate a code fetch, which will take four cycles. To figure out how long a sequence of instructions will take, one would need to figure out when these operations will occur, and then add to every instruction's execution time the amount of time it would spend waiting either for an instruction to be fetched, or for the bus unit to finish a prefetch operation.

If an instruction is preceded and followed by instructions like MUL which take a long time to execute without performing many memory accesses, then prefetch time will be irrelevant. If it's preceded and followed by long sequences of instructions like "add reg,immed16" which take longer to fetch than to execute, the internal execution time may be irrelevant. On the 8086, a sequence of "add reg,immed16" would each have an execution time of 4 cycles, but replacing instructions in the prefetch buffer would take eight, meaning that as the processor starts executing the last such instruction, the prefetch buffer will be empty, and it will get one word loaded into it during the instruction.

Although the nominal execution time of "mov al,[bx]" would be 13 cycles, execution under those circumstances would likely take 16 cycles (since a prefetch would likely start one the cycle before the MOV would have requested its memory access, forcing it to wait three cycles for the prefetch to complete) but during those 16 cycles, three instructions would have been prefetched. If the instruction was followed by a sequence of more big-but-fast instructions, the presence of those words in the prefetch buffer could eliminate eight cycles worth of waiting later on.

10

I am afraid that the answer is "it could take any time, depending on circumstances and the real WAIT condition". WAIT states have unpredictable length, so there is no exact way to answer your question.

The general answer, theoreticaly valid for every CPU (and really valid for the most of 8bit CPUs), is:

  1. Take an "instruction timing chart" and count:
  • MOV AL,[BX] takes 12 + 5 = 17 T cycles,
  • OUT DX, AL takes 12 T cycles (without WAIT!!!)

So together it will take 29 T cycles. (EDIT: My mistake, it's a timing for the 8088, not 8086)

  1. You know the frequency of the clock, so one T takes 1/freq seconds. 1MHz means each T takes 1 µs.

  2. Simply multiple, and you can see your code should take 29 µs.

BUT! It will be affected in the real environment by different influences, from real IC latency to internal pipelining mechanism, which allows to pre-decode the second instruction during the execution of the first one.

7
  • 1
    You're aware that you used 8088 timing?
    – Raffzahn
    Commented Nov 22, 2020 at 15:28
  • My fault, but I did not find the 8086 timing... :( Commented Nov 22, 2020 at 19:57
  • 2
    Try the original manuals - Bitsavers is your friend (or trust my numbers :))
    – Raffzahn
    Commented Nov 22, 2020 at 20:10
  • 2
    theoreticaly valid for every CPU ... Take an "instruction timing chart" and count - Nope, pipelined, superscalar, and especially out-of-order execution each made that less and less true. Performance isn't one-dimensional anymore, even ignoring memory stalls and branch misses. On modern CPUs like Skylake, Zen, or Cortex A76, it's basically 3-dimensions, and sustained throughput is governed by the worst bottleneck. Front-end uops, back-end port pressure, or a long dependency chain. See this Q&A on SO and the links from it. Commented Nov 23, 2020 at 6:15
  • 1
    Anyway, your answer works for retro CPUs, but don't pretend it even theoretically applies to all CPUs. (To get even more crazy, Transmeta Crusoe's dynamic recompilation for an internal VLIW core would be an example of a CPU where even the 3-dimensional cost model probably doesn't work; basically opaque. But that's a rare exception; most modern CPUs run their ISA directly, so "just" superscalar pipelined, and maybe out-of-order.) Commented Nov 23, 2020 at 6:22

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .