im compiling a timer program to display the time required to execute a program
i tried to execute this file(time7.exe) but it has encountered an illegal instruction..
why does it happen?
i try to debug it using turbo debugger but to no avail...

r there anything wrong with the code?? :shock:

the error pop-up window reads:
16bit MS-DOS Subsystem
c:\WINNT\system32\cmd.exe - time7.exe
the NTVDM CPU has encountered an illegal instuction.
CS:015c IP:f31d OP:ff ff ff ff ff

here i include the source code...

LIBSEG           segment byte public "LIB"
assume cs:LIBSEG , ds:LIBSEG

includelib alib.lib
extrn word_to_dec_stdout:far
extrn dword_to_dec_stdout:far
extrn stdout_string:far
extrn quad_multiply1:far
extrn quad_divide:far

timer_low equ 046ch
timer_mode equ 43h
timer0 equ 40h

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -(  TIME   )

           call  calibrate_timer
           call  start_timer

   call CHECK_DOS_MEMORY  ; program to be evaluated time
           call  read_timer
           call  convert_timer
           call  display_timer

push cx
        sub     bx,bx
        mov     es,bx
        mov     bx,es:[413h]            ;get mem. size in 1k blocks
        mov cl,6
        shl bx,cl
; compute our final program location in paragraphs
;  ax = our final offset
        mov cx,bx
        sub cx,ax
        mov ax,cx
        pop cx

public start_timer
start_timer proc far
apush ax,dx,ds
; initialize the 8253 to count down max count of 65536 by setting zero
mov al,00110100b ;select mode
out timer_mode,al ;request mode
call delay
sub ax,ax ;starting count
out timer0,al
call delay
out timer0,al
; wait for timer tick before starting
call delay
in al,timer0
mov ah,al
twait: call delay
in al,timer0
cmp al,ah
je twait
call delay
;wait for interrupt
sub dx,dx
mov ds,dx ;point at seg 0
mov dx,word ptr ds:
ilop: mov ax,word ptr ds:
cmp ax,dx
je ilop
; restart the timer back at count of zero again.
mov al,00110100b ;select mode
out timer_mode,al ;request mode
call delay
sub ax,ax ;starting count
out timer0,al
call delay
out timer0,al
; get the current bios time of day
mov ax,word ptr ds:
mov cs:interrupt_count,ax
apop ds,dx,ax
start_timer endp

delay: jmp d1
d1: jmp d2
d2: jmp d3
d3: jmp d4
d4: ret

public read_timer
read_timer proc far
apush ds,es
mov ax,cs
mov ds,ax
xor ax,ax
mov es,ax
; stop timer by setting mode to zero
out timer_mode,al ;timer interrupts off
call delay
in al,timer0
call delay
mov ah,al
in al,timer0
xchg ah,al
neg ax
mov timer_count,ax ;ax now has 16 bit timer count
; read interrupt count from bios
mov ax,es:
sub ax,interrupt_count
mov interrupt_count,ax
; restart the timer by resetting default value of control word
mov al,00110110b ;binary,mode 3,timer 0
out timer_mode,al
mov al,0
call delay
out timer0,al
call delay
out timer0,al
; return values to caller
mov ax,timer_count
mov dx,interrupt_count

sub ax,calibrate
sbb dx,0 ;calibrate timer value
exit: apop es,ds
read_timer endp

apush si,ds
mov si,cs
mov ds,si

mov cx,word ptr timer_convert+2
mov bx,word ptr timer_convert
call quad_multiply1 ;result to dx,cx,bx,ax
mov si,word ptr hundred_thousand+2
mov di,word ptr hundred_thousand
call quad_divide ;result dx,ax  remainder cx,bx

; dx,ax now contains the total number of micro seconds, cx,bx = remainder
cmp cx,1
je round_up
cmp bx,0c350h ;(100000/2)
jb compute_seconds
add ax,1
adc dx,0 ;round up 1

mov bx,dx
xor dx,dx
xor cx,cx
mov si,word ptr million+2
mov di,word ptr million
call quad_divide ;compute seconds & microseconds
; dx,ax = seconds   cx,bx = microseconds
apop ds,si


public display_timer
apush si,ds

mov si,cs
mov ds,si
mov seconds,ax
mov word ptr microseconds+2,cx
mov word ptr microseconds,bx

mov si,offset msg1
call stdout_string ;display 'Elapsed time ="

mov ax,seconds
call word_to_dec_stdout ;seconds
mov si,offset message_sec
call stdout_string

mov ax,word ptr microseconds
mov dx,word ptr microseconds+2
call dword_to_dec_stdout
mov si,offset message_micro
call stdout_string
apop ds,si

public calibrate_timer
calibrate_timer proc far
apush ax,bx,cx,dx
mov cs:calibrate,0
mov cs:seconds,0
mov cx,8
ct_lp1: push cx
        call start_timer
call read_timer
add cs:seconds,ax
pop cx
loop ct_lp1

mov ax,cs:seconds
mov cl,3
shr ax,cl
mov cs:calibrate,ax

mov cx,5000
ct_lp: call delay
loop ct_lp
apop dx,cx,bx,ax
calibrate_timer endp

timer_count dw 0 ;read from 8253
interrupt_count dw 0 ;read from BIOS

microseconds dd 0 ;total microseconds
seconds dw 0 ;total seconds

calibrate dw 0 ;calibration factor from read_timer

timer_convert dd 83809 ;838.096 nsec per tick
hundred_thousand dd 100000
million dd 1000000

msg1 db 0dh,0ah,0dh,0ah,'Elapsed time = ',0
message_sec db ' (seconds)   ',0
message_micro db ' (Micro seconds)',0dh,0ah,0

end start

Posted on 2007-05-09 01:30:25 by wogok
Doesn't start: need some kind of exit? At the moment it just carries on into the CHECK_DOS_MEMORY proc, so who
knows where it will end up?
Posted on 2007-05-09 01:40:36 by sinsi
but i did put the end start right at the end of the code...

jus below the LIBSEG ENDS...


Posted on 2007-05-09 01:47:27 by wogok
All "end start" does is tell the linker where the entry point is - you still need to exit to DOS

  ;blah blah blah
  mov ah,4ch
  int 21h
Posted on 2007-05-09 02:15:17 by sinsi
Dear Sinsi,

thanks 4 the reply!! :D

yaya..i had include it..and it realy works!!
now it has the time output display..

actually this is the first time im using MASM!!
it took me 1week to learn all d basic stuff!!

do u think this program can be use to measure RAM(memory) speed accurately?

Posted on 2007-05-09 02:34:01 by wogok
I think that the clock only goes 1.19MHz whereas memory is in the nanosecond range, so...nope
Maybe someone can refute this?
Posted on 2007-05-09 05:20:16 by sinsi
This would probably work.

;  INT 15h,  86h (134)      Wait                                XT-286, AT
;    Waits a specified number of microseconds before returning control to
;    the caller.
;      On entry:      AH        86h
;                      CX:DX      Number of microseconds to elapse
;      Returns:      Carry      Set if error or wait in progress, else
;                                cleared
;      Notes:        This service is not available for the PC, PCjr, and
;                      the XT.
;                      The real-time clock is used to count the number of
;                      microseconds.
;      The granularity of the time is 976 microseconds. (1/1000 second)
;                    1,000,000 microseconds = 1 second
Posted on 2007-05-09 20:50:45 by skywalker
Dear skywalker,

i dont really catch the meaning... :shock:
mayb can u xplain a little bit more...

anyway, thanks ya!!!  :D
Posted on 2007-05-09 21:03:00 by wogok