From: Mint on
I am having some problems with this code.
Can someone help?

Thanks.

Turbo Assembler Version 4.1 Copyright (c) 1988, 1996 Borland
International

Assembling file: timeit.asm
**Error** c:\16_bit\monitor.asm(69) Code or data emission to
undeclared segment
**Error** c:\16_bit\monitor.asm(85) Name must come first
**Error** c:\16_bit\monitor.asm(89) Illegal instruction
**Error** c:\16_bit\monitor.asm(90) Operand types do not match
**Error** c:\16_bit\monitor.asm(91) Operand types do not match
**Error** c:\16_bit\monitor.asm(92) Can't use this outside macro
**Error** c:\16_bit\monitor.asm(109) Name must come first
**Error** c:\16_bit\monitor.asm(113) Illegal instruction
**Error** c:\16_bit\monitor.asm(114) Operand types do not match
**Error** c:\16_bit\monitor.asm(115) Operand types do not match
**Error** c:\16_bit\monitor.asm(122) Can't use this outside macro
**Error** timeit.asm(21) Undefined symbol: MONITOR_INIT
**Error** timeit.asm(22) Illegal instruction
**Error** timeit.asm(24) Illegal instruction

..model small
..586
..stack 200h

include c:\16_bit\monitor.asm

..data

time_cycles dq ?
cycle dd ?
cpuid_cycle dd ?
mycountlow dd ?
mycounthigh dd ?

..code

start:
mov ax,@data
mov ds,ax
call monitor_init
time_start
xor ax,ax
time_stop
mov [mycountlow],eax
mov [mycounthigh],edx

exit:
mov ax,4c00h
int 21h

end start

------------------------------------------

; monitor.asm
; Performance monitoring package
;
; define PProPII if your CPU is a Pentium Pro or a Pentium II
;
; implements:
;
; monitor_init
; initializes the package
;
; time_start
; start cycle count here
;
; time_stop
; stop counting here
;
; note:
; the package can not do nested measurements, since the macro
; returns all cycles in the same variable
;

;
; define cpuid and rdtsc instructions via macros
; this is not necessary is your assembler supports them
;
; MACRO cpuid
; db 0fh,0a2h
; ENDM
;
; MACRO rdtsc
; db 0fh,031h
; ENDM


;
; monitor_init:
;
; input:
; nothing
;
; output:
; cpuid_cycle = initialized to exection time of cpuid
;
; destroys:
; nothing
;

monitor_init:

IFDEF PProPII
pushfd
pushad

mov ecx,3
getcpuidtime:
cpuid
rdtsc
mov [cycle],eax
cpuid
rdtsc
sub eax,[cycle]
mov [cpuid_cycle],eax
dec ecx
jnz getcpuidtime

popad
popf
ENDIF
ret

;
; time_start - start timing point here
;
; input:
; none
;
; output:
; time_cycles initialized
;
; destroys:
; eax, ebx, ecx, edx
; eflags
;

MACRO time_start
IFDEF PProPII
cpuid
ENDIF
rdtsc
mov [time_cycles],eax
mov [time_cycles+4],edx
ENDM

;
; time_stop - stop timing point here
;
; input:
; none
;
; output:
; eax = low cycle count
; edx = high cycle count
;
; destroys:
; eax, ebx, ecx, edx
; eflags
;

MACRO time_stop
IFDEF PProPII
cpuid
ENDIF
rdtsc
sub eax,[time_cycles]
sbb edx,[time_cycles+4]

IFDEF ProPII
sub eax,[cpuid_cycle]
sbb edx,0
ENDIF

ENDM

From: io_x on

"Mint" <chocolatemint77581(a)yahoo.com> ha scritto nel messaggio
news:e3de4069-c526-4c78-9fc5-599185d4f71b(a)s41g2000vba.googlegroups.com...
>I am having some problems with this code.
> Can someone help?
>
> Thanks.
>
> Turbo Assembler Version 4.1 Copyright (c) 1988, 1996 Borland
> International
>
> Assembling file: timeit.asm
> **Error** c:\16_bit\monitor.asm(69) Code or data emission to
> undeclared segment
> **Error** c:\16_bit\monitor.asm(85) Name must come first
> **Error** c:\16_bit\monitor.asm(89) Illegal instruction
> IFDEF PProPII
> pushfd
> pushad
>
> mov ecx,3
> getcpuidtime:
> cpuid
> rdtsc
> mov [cycle],eax
> cpuid
> rdtsc
> sub eax,[cycle]
> mov [cpuid_cycle],eax
> dec ecx
> jnz getcpuidtime
>
> popad
> popf

i think above should be popfd
but i not understand much so could be not true
(if popfd==popf==32bit instruction pop all the 32bit falg register)
but the flag register is 32Bits for one 386 cpu?

> ENDIF
> ret
>



From: Frank Kotler on
Mint wrote:
> I am having some problems with this code.
> Can someone help?
>
> Thanks.
>
> Turbo Assembler Version 4.1 Copyright (c) 1988, 1996 Borland
> International

FFS, Andy, get yourself an assembler!

....
> time_cycles dq ?

.....
> mov [time_cycles],eax
> mov [time_cycles+4],edx

dword ptr

> sub eax,[time_cycles]
> sbb edx,[time_cycles+4]

dword ptr

http://www.japheth.de/JWasm.html

Are you *new* at this???

Best,
Frank
From: Mint on
On May 26, 3:24 pm, Frank Kotler <fbkot...(a)myfairpoint.net> wrote:
> Mint wrote:
> > I am having some problems with this code.
> > Can someone help?
>
> > Thanks.
>
> > Turbo Assembler  Version 4.1  Copyright (c) 1988, 1996 Borland
> > International
>
> FFS, Andy, get yourself an assembler!

> Are you *new* at this???
>
> Best,
> Frank

Be nice. :-)
Nothing wrong with Tasm.

; ?? Showing 340 cycles for any block of code
; timeit.asm TASM code
; Help from Shoorick,
; time = cycles/frequency
..model small
..486
..stack 200h

..data

time_cycles dd ?
cycle dd ?
cpuid_cycle dd ?
mycountlow dd ?
mycounthigh dd ?

..code

include monitor.asm

start:

mov ax,@data
mov ds,ax

call monitor_init
time_start

mov ax,45000 ; ax:dx contains 90,000,000
; ax = 4a80h
; dx = 55dh
; so, 55d4a80h = 90,000,000
mov bx,2000
mul bx


time_stop
mov [mycountlow],eax
mov [mycounthigh],edx

;mov eax,123456789
; print low cycle count
call PrtDec
xor eax,eax ; clear eax

; print high cycle count
mov eax,edx
call PrtDec

mov ax,4c00h
int 21h
; Print any number in eax
PrtDec proc
push eax
push ecx
push edx
mov ecx,0ffffffffh
push ecx
mov ecx,10
pd1:
mov edx,0
div ecx
add dl,30h
push edx
cmp eax,0
jne pd1
pd2:
pop edx
cmp edx,0ffffffffh
je pd3
mov ah,2
int 21h
jmp pd2
pd3:
pop edx
pop ecx
pop eax
ret
PrtDec endp

;exit:
;mov ax,4c00h
;int 21h

end start
From: Frank Kotler on
Mint wrote:
> On May 26, 3:24 pm, Frank Kotler <fbkot...(a)myfairpoint.net> wrote:
>> Mint wrote:
>>> I am having some problems with this code.
>>> Can someone help?
>>> Thanks.
>>> Turbo Assembler Version 4.1 Copyright (c) 1988, 1996 Borland
>>> International
>> FFS, Andy, get yourself an assembler!
>
>> Are you *new* at this???
>>
>> Best,
>> Frank
>
> Be nice. :-)
> Nothing wrong with Tasm.

You're right. I'm sorry.

> ; ?? Showing 340 cycles for any block of code

Thought you said there was nothing wrong with it. :)

> ; timeit.asm TASM code
> ; Help from Shoorick,
> ; time = cycles/frequency
> .model small
> .486
> .stack 200h
>
> .data
>
> time_cycles dd ?

Unless you've changed the hidden-away part, you're still treating this
as a qword. This is "wrong", but you're just overwriting "cycle" with
the high dword, and I don't think you use "cycle" after "monitor_init"
(if then)... so I don't think it matters...

> cycle dd ?
> cpuid_cycle dd ?
> mycountlow dd ?
> mycounthigh dd ?
>
> .code
>
> include monitor.asm
>
> start:
>
> mov ax,@data
> mov ds,ax
>
> call monitor_init

What does this do? As I read it, if you haven't got "PProPII" defined,
it doesn't do squat. In fact, you don't appear to do "cpuid" at all, if
this isn't defined. You probably do want "cpuid", if your machine
supports it - using Tasm, ya never know. :)

I sympathize with your problems. My attempts to time anything have been
"inconclusive". If you get this thing working, time "das" for me! I've
got some code... very similar to what you've got here... which "works",
I guess, but gives some weird results. "das" is all over the place.
"push eax"/"pop eax" executes faster if you do it twice than if you do
it once. Things like that make me wonder if there's a bug in the code
that I haven't found, or if my PIV is just weird. I'd post it, but it is
specific to Linux... Hell, I'll post it anyway. I'll try to work up a
more "portable" version, don't waste too much "time" on this...

Best,
Frank


; uses Herbert's "direct to elf executable" code
; nasm -f bin myprog.asm > myprog.map
; chmod +x myprog

; "tune" this so an empty loop gives zero, most often,
; on your machine.
THIS_EMPTY_LOOP equ 384

; define this on the command line to Nasm,
; or uncomment it here, if you prefer...
; REPT_COUNT equ 1 ; 10000

;[map all]
;===========================================================================
bits 32
ORIGIN equ 8048000h
org ORIGIN
section .text
code_offset equ 0
code_addr:
;--------------------------- ELF header -----------------------------------
dd $464c457f,$00010101,0,0,$00030002,1,main,$34,0,0,$00200034,2,0
dd 1,code_offset,code_addr,code_addr,code_filez,code_memsz,5,4096
dd 1,data_offset,data_addr,data_addr,data_filez,data_memsz,6,4096
main:
;--------- your code goes here ------------------------------------------

xor eax, eax
cpuid
rdtsc
push edx
push eax

;------------------
; code to time

;times REPT_COUNT mov eax, 0
;times REPT_COUNT xor eax, eax

;times REPT_COUNT dec eax
; times REPT_COUNT sub eax, byte 1


%rep REPT_COUNT
;push eax
;pop eax

;mov eax, [esp]
;mov [esp], eax

; das

%endrep

;-------------------

xor eax, eax
cpuid
rdtsc

pop ebx
sub eax, ebx
pop ecx
sbb edx, ecx
sub eax, THIS_EMPTY_LOOP
sbb edx, 0

mov edi, ascbuf
call u64toda

; will need a suitable "printstring" and "exit" for 'doze

mov al, 10 ; terminate buffer with LF
stosb
mov ecx, ascbuf
mov edx, edi
sub edx, ecx
mov ebx, 1
mov eax, 4
int 80h


exit:
mov eax, 1
int 80h
;----------------

;--------------------------------------------------------------
; u64toda - converts (64 bit) integer in edx:eax
; to (comma delimited) decimal representation in
; string in buffer pointed to by edi
; returns edi -> next position in buffer
;-----------------------------------------------------------------
u64toda:
push eax
push ebx
push ecx
push edx
push esi

mov ebx, edx ; stash high dword
mov esi, 0Ah ; prepare to divide by 10
xor ecx, ecx ; zero the digit count
jmp highleft ; check is high word 0 ?
highword:
xchg eax, ebx ; swap high & low words
xor edx, edx ; zero edx for the divide!
div esi ; divide high word by 10
xchg eax, ebx ; swap 'em back
div esi ; divide low word including remainder
push edx ; remainder is our digit - save it
inc ecx ; count digits
highleft:
test ebx, ebx
jnz highword
lowleft:
xor edx, edx ; zero high word
div esi ; divide low word by 10
push edx ; our digit
inc ecx ; count it
or eax, eax ; 0 yet ?
jne lowleft
cmp ecx, 4 ; commas needed ?
jl write2buf ; nope
xor edx, edx ; zero high word for divide
mov eax, ecx ; number of digits
mov ebx, 3
div ebx
mov esi, edx ; remainder = number digits before comma
test edx, edx
jnz write2buf ; no remainder?
mov esi, 3 ; we can write 3 digits, then.
write2buf:
pop eax ; get digit back - in right order
add al, '0' ; convert to ascii character
stosb ; write it to our buffer
dec esi ; digits before comma needed
jnz moredigits ; no comma needed yet
cmp ecx, 2 ; we at the end?
jl moredigits ; don't need comma
mov al, ',' ; write a comma
stosb
mov esi, 3 ; we're good for another 3 digits
moredigits:
loop write2buf ; write more digits - cx of 'em

pop esi
pop edx
pop ecx
pop ebx
pop eax
ret
;-------------------------------------------------------------



;------------ constant data ---------------------------------
; (note that we're in .text, not .rdata)
align 4

; we have none

;---------------------------------------------------------------------------
align 4
code_memsz equ $ - $$
code_filez equ code_memsz
data_addr equ (ORIGIN+code_memsz+4095)/4096*4096 + (code_filez
% 4096)
data_offset equ code_filez
section .data vstart=data_addr
;------------ initialized data ------------------------------

; we have none

;---------------------------------------------------------------------------
idat_memsz equ $ - $$
bss_addr equ data_addr + ($ - $$)
section .bss vstart=bss_addr
;--------------------------- uninitialized data ----------------------------

ascbuf resb 20h

;---------------------------------------------------------------------------
udat_memsz equ $ - $$
data_memsz equ idat_memsz + udat_memsz
data_filez equ idat_memsz
;===========================================================================