Skip to content

Instantly share code, notes, and snippets.

@Jiggins
Created May 20, 2015 15:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Jiggins/0ff87e03a44d7afb3946 to your computer and use it in GitHub Desktop.
Save Jiggins/0ff87e03a44d7afb3946 to your computer and use it in GitHub Desktop.

Clock Cycles

The following code takes 6 seconds to run on a DOS box emulator. Calculate the number of clock cycles required for the highlighted code (A) to run?

Ok so for this part you need to count the number of cycles this program will execute. Each comment will tell you how many cycles each instruction takes. E.g. It takes 4 clock cycles to run mov bx, 100. On the jump instructions, you will see something like '16 backward 4 forward', this means if the jump instruction jumps back, it will yake 16 cycles, if it doesn't jump, it will take 4.

In this example, when cx > 0, jnz back1 will take 16 cycles. But when cx == 0, it will take 4 cycles.

Calculation

    +----------------------------- `mov cx, 50000` takes 4 cycles
    |
    |       +---------------------- When cx != 0, `jnz back1` takes 16 cycles + 2 from `dec cx`
    |       |
    |       |         +------------ This happens 49,999 times, on the 50,000th time, cx == 0 so,
    |       |         |
    |       |         |          +- when cx == 0, `jnz back1` only takes 4 cycles + 2 from `dec cx`
    |       |         |          |
B = 4 + ((2 + 16) * 49999) + (4 + 2) = 899992

    +----------------------------- `mov cx, 50000` takes 4 cycles
    |
    |       +---------------------- When cx != 0, `jnz back2` takes 16 cycles + 2 from `dec cx`
    |       |
    |       |         +------------ This happens 49,999 times, on the 50,000th time, cx == 0 so,
    |       |         |
    |       |         |          +- when cx == 0, `jnz back2` only takes 4 cycles + 2 from `dec cx`
    |       |         |          |
C = 4 + ((2 + 16) * 49999) + (4 + 2) = 899992

A =
                       4 ; `mov   bx, 100` Only happens once
   99 * (B + C + 2 + 16) ; When `bx != 0`
  +        B + C + 2 + 4 ; When `bx == 0`
  ----------------------
A =          180,000,192 cycles

Estimate the speed of the emulator expressed in MHz?

speed = 180000192 cycles / 6 seconds = 30000032 Hz
      = 30.000032 MHz

The above answer seems way too high, but theres a reason for that. Modern processors are able to do three operations at once. So this means we can estimate the speed of the processor by dividing this number by 3 giving us about 10 MHz

Why would it not be possible to replace code B and C with a single loop with an initial value of CX=100,000?

Although this would result in the same output, the number of cycles would be reduced since the jump forward at jnz back1, second mov cx and second dec cx would never happen.

Assembly

        mov ah,02
        mov dl,'S'
        int 021h
        mov   bx, 100   ; 4 cycles
back3:  mov   cx, 50000 ; 4
back1:  dec   cx
        jnz   back1     ; 16 backward 4 forward


        mov   cx, 50000 ; 4
back2:  dec   cx        ; 2
        jnz   back2     ; 16 backward 4 forward


        dec   bx        ; 2
        jnz back3       ; 16 backward 4 forward


        mov ah,02
        mov dl,'F'
        int 021h

Python Implementation

cycles = 0

bx = 100; cycles = cycles + 4; # mov   bx, 100
while True:

	# B
	B = 0
	cx = 50000; cycles = cycles + 4; B = B + 4 # mov   cx, 50000

	while True:
		cx = cx - 1; cycles = cycles + 2; B = B + 2 

		if cx != 0:                      # jnz   back1
			cycles = cycles + 16
			B = B + 16
		else:
			cycles = cycles + 4
			B = B + 4
			break

	# C
	C = 0
	cx = 50000; cycles = cycles + 4; C = C + 4 # mov   cx, 50000

	while True:
		cx = cx - 1; cycles = cycles + 2; C = C + 2 

		if cx != 0:                      # jnz   back1
			cycles = cycles + 16
			C = C + 16
		else:
			cycles = cycles + 4
			C = C + 4
			break

	bx = bx - 1; cycles = cycles + 2 # dec bx

	if bx != 0:                      # jnz back3
		cycles = cycles + 16
	else:
		cycles = cycles + 4
		break


print "B =", B           # 899992
print "C =", C           # 899992
print "cycles =", cycles # 180000192

speed = cycles / 6
print "Speed =", speed, "Hz"
print "Speed =", speed/1000000.00, "MHz"
print "Speed =", (speed/1000000.00) / 3, "MHz, with parallel processing"

# Speed = 30000032 Hz
# Speed = 30.000032 MHz
# Speed = 10.0000106667 MHz, with parallel processing
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment