;
; CPUTEST.ASM - Copyright (C) 1993 - Tony Doimeadios - All Rights Reserved
;
;         Made-----------: 09/30/93
;         Last Modified--: 10/01/93
;
;         This sub will move memory, to time the CPU "speed"
;         Moving 8,000,000 bytes, 25,000 at a time (80 times)
;
    
    DOSSEG
    .MODEL LARGE
    .STACK
    .DATA?
Buffer1 db  25000 DUP (?)       ;buffer to copy from
Buffer2 db  25000 DUP (?)       ;buffer to copy to

    .DATA
StartLow    dw  0               ;variable to store the low word of start ticks
FinishLow   dw  0               ;variable to store the low word of stop ticks
Counter     dw  0               ;variable to store loop counter
Dummy       dw  0               ;dummy word variable for variable-2-reg proc

            ;1234567890123456789012345678901234567890123456789012
Output1  db 'It took       timer ticks to move 8 million bytes...',13,10,'$'
Output2  db 'It took       timer ticks to do 8 million register-to-register moves...',13,10,'$'
Output3  db 'It took       timer ticks to do 8 million variable-to-register moves...',13,10,'$'
Output4  db 'It took       timer ticks to move 100 million bytes...',13,10,'$'
    
    .CODE
    mov ax,@Data
    mov ds,ax                   ;set DS to point to the data segment


;---------------------------------------------------------------------
    ;MEMORY MOVES
    ;
    ;timing loop
    ;
    xor  AX,AX                  ;look at the low system timer byte
    int 1Ah                      ;how many clock ticks since midnight
    mov StartLow,dx             ;save it (low word)
    
    
    ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    mov Counter,0               ;initialize the loop counter

DoIt1:    
    call MoveBytes              ;call the memory mover proc
    inc Counter                 ;inc the counter
    cmp Counter,40*8            ;40 loops = 1 million
    jne DoIt1                   ;if it's not the required # of loops, do more
    ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


    ;timing loop
    ;
    xor  AX,AX                  ;look at the low system timer byte
    int 1Ah                      ;how many clock ticks since midnight
    mov FinishLow,dx            ;save it (low word)


    ;get difference from start and stop times
    ;
    xor ax,ax                   ;zero out register
    mov ax,FinishLow            ;put stop times in
    sub ax,StartLow             ;sub start from it - ax now holds difference

    mov bx,SEG Output1          ;get segment of Output1 string
    mov ds,bx                   ;put it in ds
    mov bx,OFFSET Output1+12    ;offset is 13 characters into the string
    mov cx,5                    ;convert 5 digits
    call Num2Str

    mov bx,SEG Output1          ;get segment of Output1 string
    mov ds,bx                   ;put it in ds
    mov bx,Offset Output1       ;get offset of string
    call PrintString            ;print string
;---------------------------------------------------------------------
;---------------------------------------------------------------------




;---------------------------------------------------------------------
;---------------------------------------------------------------------
    ;REGISTER TO REGISTER
    ;
    ;timing loop
    ;
    xor ax,ax                   ;look at the low system timer byte
    int 1Ah                      ;how many clock ticks since midnight
    mov StartLow,dx             ;save it (low word)

    
    ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    mov Counter,0               ;initialize the loop counter

DoIt2:    
    call MoveReg                ;call the memory mover proc
    inc Counter                 ;inc the counter
    cmp Counter,40*8            ;40 loops = 1 million
    jne DoIt2                   ;if it's not the required # of loops, do more
    ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


    ;timing loop
    ;
    xor ax,ax                   ;look at the low system timer byte
    int 1Ah                      ;how many clock ticks since midnight
    mov FinishLow,dx            ;save it (low word)


    ;get difference from start and stop times
    xor ax,ax                   ;zero out register
    mov ax,FinishLow            ;put stop times in
    sub ax,StartLow             ;sub start from it - ax now holds difference

    mov bx,SEG Output2          ;get segment of Output1 string
    mov ds,bx                   ;put it in ds
    mov bx,OFFSET Output2+12    ;offset is 13 characters into the string
    mov cx,5                    ;convert 5 digits
    call Num2Str

    mov bx,SEG Output2          ;get segment of Output1 string
    mov ds,bx                   ;put it in ds
    mov bx,Offset Output2       ;get offset of string
    call PrintString            ;print string
;---------------------------------------------------------------------
;---------------------------------------------------------------------




;---------------------------------------------------------------------
;---------------------------------------------------------------------
    ;VARIABLE TO REGISTER
    ;
    ;timing loop
    ;
    xor ax,ax                   ;look at the low system timer byte
    int 1Ah                      ;how many clock ticks since midnight
    mov StartLow,dx             ;save it (low word)

    
    ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    mov Counter,0               ;initialize the loop counter

DoIt3:    
    call MemReg                ;call the memory mover proc
    inc Counter                 ;inc the counter
    cmp Counter,40*8            ;40 loops = 1 million
    jne DoIt3                   ;if it's not the required # of loops, do more
    ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


    ;timing loop
    ;
    xor ax,ax                   ;look at the low system timer byte
    int 1Ah                      ;how many clock ticks since midnight
    mov FinishLow,dx            ;save it (low word)
    
    ;get difference from start and stop times
    xor ax,ax                   ;zero out register
    mov ax,FinishLow            ;put stop times in
    sub ax,StartLow             ;sub start from it - ax now holds difference

    mov bx,SEG Output3          ;get segment of Output1 string
    mov ds,bx                   ;put it in ds
    mov bx,OFFSET Output3+12    ;offset is 13 characters into the string
    mov cx,5                    ;convert 5 digits
    call Num2Str

    mov bx,SEG Output3          ;get segment of Output1 string
    mov ds,bx                   ;put it in ds
    mov bx,Offset Output3       ;get offset of string
    call PrintString            ;print string
;---------------------------------------------------------------------
;---------------------------------------------------------------------




;---------------------------------------------------------------------
;---------------------------------------------------------------------
    ;MEMORY MOVES (requested by Richard)
    ;
    ;timing loop
    ;
    xor ax,ax                   ;look at the low system timer byte
    int 1Ah                      ;how many clock ticks since midnight
    mov StartLow,dx             ;save it (low word)

    
    
    ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    mov Counter,0               ;initialize the loop counter

DoIt4:    
    call MoveBytes              ;call the memory mover proc
    inc Counter                 ;inc the counter
    cmp Counter,40*100          ;40 loops = 1 million
    jne DoIt4                   ;if it's not the required # of loops, do more
    ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


    ;timing loop
    ;
    xor ax,ax                   ;look at the low system timer byte
    int 1Ah                      ;how many clock ticks since midnight
    mov FinishLow,dx            ;save it (low word)


    ;get difference from start and stop times
    ;
    xor ax,ax                   ;zero out register
    mov ax,FinishLow            ;put stop times in
    sub ax,StartLow             ;sub start from it - ax now holds difference

    mov bx,SEG Output4          ;get segment of Output1 string
    mov ds,bx                   ;put it in ds
    mov bx,OFFSET Output4+12    ;offset is 13 characters into the string
    mov cx,5                    ;convert 5 digits
    call Num2Str

    mov bx,SEG Output4          ;get segment of Output1 string
    mov ds,bx                   ;put it in ds
    mov bx,Offset Output4       ;get offset of string
    call PrintString            ;print string

    jmp short Done              ;done - bail out
;---------------------------------------------------------------------
;---------------------------------------------------------------------




;---------------------------------------------------------------------
; Subroutine to convert a binary number to a text string.
;
; Input:
;       AX = number to convert
;       DS:BX = pointer to end of string to store text in
;       CX = number of digits to convert
;
; Output: None
;
; Registers destroyed: AX, BX, CX, DX, SI
;
Num2Str   PROC
        mov     si,10                      ;used to divide by 10
ConvertLoop:
        sub     dx,dx                      ;convert AX to doubleword in DX:AX
        div     si                         ;divide number by 10. Remainder is in
                                           ; DX--this is a one-digit decimal
                                           ; number. Number/10 is in AX
        add     dl,'0'                     ;convert remainder to a text character
        mov     [bx],dl                    ;put this digit in the string
        dec     bx                         ;point to the location for the
                                           ; next most-significant digit
        loop    ConvertLoop                ;do the next digit, if any
        ret
Num2Str   ENDP
;---------------------------------------------------------------------


;---------------------------------------------------------------------
; Subroutine to print a string on the display.
;
; Input:
;       DS:BX = pointer to string to print
;
; Output: None
;
; Registers destroyed: None
;
PrintString     PROC
        push    ax
        push    dx              ;preserve registers in this sub
        mov     ah,9            ;DOS print string function #
        mov     dx,bx           ;point DS:DX to the string to print
        int     21h             ;invoke DOS to print the string
        pop     dx              ;restore registers we changed
        pop     ax              ;
        ret                     ;
PrintString     ENDP
;---------------------------------------------------------------------




;---------------------------------------------------------------------
MoveBytes PROC
    
    mov ax,SEG Buffer1          ;get segment of ROM BIOS
    mov es,ax                   ;put it in ds
    mov di,OFFSET Buffer1       ;get offset of buffer

    mov ax,SEG Buffer2          ;get segment of Buffer2
    mov ds,ax                   ;put it in es
    mov si,0                    ;get offset of buffer

    mov cx,25000                ;gonna move 25000 bytes
    rep movsb                   ;do it until cx=0

    ret                         ;done - bail out

MoveBytes ENDP
;---------------------------------------------------------------------




;---------------------------------------------------------------------
MoveReg PROC
    mov cx,25000                ;setup for 25000 times
    
MoveLoop:
    mov es,ax                   ;do register to register move
    loop MoveLoop               ;do it 25000 times

    ret                         ;done - bail out

MoveReg ENDP
;---------------------------------------------------------------------




;---------------------------------------------------------------------
MemReg PROC
    mov cx,25000                ;setup for 25000 times
    
MemLoop:
    mov dx,Dummy                ;do variable to register move
    loop MemLoop                ;do it 25000 times

    ret                         ;done - bail out

MemReg ENDP
;---------------------------------------------------------------------




Done:
    mov ax,4C00h
    int 21h
    END
