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
include mac.inc
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 )
start:
call calibrate_timer
call start_timer
call CHECK_DOS_MEMORY ; program to be evaluated time
call read_timer
call convert_timer
call display_timer
public CHECK_DOS_MEMORY
CHECK_DOS_MEMORY proc far
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
retf
CHECK_DOS_MEMORY endp
public start_timer
start_timer proc far
apush ax,dx,ds
pushf
cli
;
; 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
;
sti
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
popf
apop ds,dx,ax
retf
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
pushf
cli
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
popf
exit: apop es,ds
retf
read_timer endp
public CONVERT_TIMER
CONVERT_TIMER proc far
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
round_up:
add ax,1
adc dx,0 ;round up 1
compute_seconds:
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
retf
CONVERT_TIMER endp
public display_timer
DISPLAY_TIMER proc far
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
retf
DISPLAY_TIMER endp
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
retf
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
LIBSEG ENDS
end start
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
include mac.inc
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 )
start:
call calibrate_timer
call start_timer
call CHECK_DOS_MEMORY ; program to be evaluated time
call read_timer
call convert_timer
call display_timer
public CHECK_DOS_MEMORY
CHECK_DOS_MEMORY proc far
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
retf
CHECK_DOS_MEMORY endp
public start_timer
start_timer proc far
apush ax,dx,ds
pushf
cli
;
; 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
;
sti
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
popf
apop ds,dx,ax
retf
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
pushf
cli
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
popf
exit: apop es,ds
retf
read_timer endp
public CONVERT_TIMER
CONVERT_TIMER proc far
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
round_up:
add ax,1
adc dx,0 ;round up 1
compute_seconds:
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
retf
CONVERT_TIMER endp
public display_timer
DISPLAY_TIMER proc far
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
retf
DISPLAY_TIMER endp
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
retf
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
LIBSEG ENDS
end start
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?
knows where it will end up?
but i did put the end start right at the end of the code...
jus below the LIBSEG ENDS...
so...
jus below the LIBSEG ENDS...
so...
All "end start" does is tell the linker where the entry point is - you still need to exit to DOS
start:
;blah blah blah
mov ah,4ch
int 21h
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?
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?
I think that the clock only goes 1.19MHz whereas memory is in the nanosecond range, so...nope
Maybe someone can refute this?
Maybe someone can refute this?
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
; 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
Dear skywalker,
i dont really catch the meaning... :shock:
mayb can u xplain a little bit more...
anyway, thanks ya!!! :D
i dont really catch the meaning... :shock:
mayb can u xplain a little bit more...
anyway, thanks ya!!! :D