How to calculate MIPS of my processor?

architecture, performance, performance-testing, preprocessor, x86

Solution

In line with what you wanted, here's some bootloader code that executes a kind of a benchmark that can be probably used to measure the MIPS in a way. The main objective here was being low-level, and I believe that this is the lowest level at which you can actually program with the PC, unless you're willing to replace your BIOS or something.

Anyway, this is the code for a floppy image that, when booted, will try to execute four instructions (two `add`s, one `sub`, and one conditional jump) one million times. How many times the instructions are executed is controlled by the `ITERS` macro. By raising or lowering it you can specify how many iterations are supposed to be made.

Time is measured by using the `rdtsc` instruction, which returns the number of processor ticks made since its power-up as a 64-bit number in registers `edx` and `eax`. By computing the difference of this value before executing the loop and before, we get the number of ticks that the processor spent executing it. That value is then output to the screen by using the BIOS 10h call as a hexadecimal value. The actual time spent on it is, obviously, dependent on the processor clock's frequency.

Here's the source. If you compile it using NASM with `-f bin`, you'll get the floppy image which should be then written to a floppy using some raw block writing program, for example `dd`. Then, when booting, choose the floppy as the boot medium. All that may also work with a USB drive, but that's much more BIOS-dependent. As with all stuff that's so low-level, I take no responsibility for the results of actually executing this software on your computer.

bits 16
org 0x7c00

ITERS equ 1000000

jmp 0x0000:start

start:
    cli
    xor ax, ax
    mov ds, ax
    mov ss, ax
    mov sp, stack_end

    rdtsc
    mov [old_rdtsc], eax
    mov [old_rdtsc+4], edx
    mov eax, ITERS

.loop:
    add ebx, ecx
    add ecx, edx

    sub eax, 1
    jnz .loop

    rdtsc

    sub eax, [old_rdtsc]
    sbb edx, [old_rdtsc+4]

    mov si, 15

.fillbuf_eax:
    mov edi, eax
    shr eax, 4
    and di, 0xf
    mov bl, [hex_chars+di]
    mov [str_buf+si], bl
    sub si, 1
    cmp si, 7
    ja .fillbuf_eax

.fillbuf_edx:
    mov edi, edx
    shr edx, 4
    and di, 0xf
    mov bl, [hex_chars+di]
    mov [str_buf+si], bl
    sub si, 1
    jns .fillbuf_edx

    mov ah, 0xe
    xor bx, bx
.bios_write:
    pusha
    mov al, [str_buf+bx]
    int 10h
    popa
    add bx, 1
    cmp bx, 16
    jb .bios_write

    sti

.halt:
    hlt
    jmp .halt

hex_chars db "0123456789ABCDEF"
old_rdtsc resq 1
str_buf resb 16

STACK_SIZE equ 200
stack resb STACK_SIZE
stack_end equ $

times 510-($-$$) db 0x90
db 0x55, 0xaa

On my rather old AMD Athlon XP 1700+, I get `0x1e8596` as a result of executing this code, which is equal to 2000278 CPU ticks. As the CPU runs at 1466MHz, this is more or less equal to approximately 1,36ms.

Problem

I have an old PC. I want to calculate MIPS(Million Instruction Per Second) and DMIPS of its processor exactly. What can I do for this?

Original source