Newsgroup: it.comp.lang.c
Titolo: mistero della fede...

Sto svolgendo un lavoro di "benchmark" e mi sono imbattuto in un
interessante problema...
Ho due programmi, il primo su un file singolo, il secondo su due sorgenti.
I programmi sono praticamente analoghi, ma, pur non essendoci problemi
all'atto della compilazione, in run-time il primo restituisce valori
corretti, mentre il secondo svalvola del tutto...
(Il pezzo di codice in assembler va a pescare un registro a 64 bit del
processore (con architettura IA32 o successiva) che contiene una fotografia
temporale della macchina... niente di trascendentale insomma.)
Il primo è il seguente:
#include <stdio.h>
#include <sys/times.h>
static unsigned cyc_hi = 0;
static unsigned cyc_lo = 0;
void access_counter(unsigned *hi, unsigned *lo){
  asm("rdtsc; movl %%edx,%0; movl %%eax,%1"
      : "=r" (*hi), "=r" (*lo)
      : /* No input */
      : "%edx", "%eax");
}
void start_counter(){
  access_counter(&cyc_hi, &cyc_lo);
}
double get_counter(){
  unsigned ncyc_hi, ncyc_lo;
  unsigned hi, lo, borrow;
  double result;
  access_counter(&ncyc_hi, &ncyc_lo);
  lo = ncyc_lo - cyc_lo;
  borrow = lo > ncyc_lo;
  hi = ncyc_hi - cyc_hi - borrow;
  result = (double) hi * (1 << 30) * 4 + lo;
  if (result < 0) {
    fprintf(stderr, "Error: counter returns neg value: %.0f\n", result);
  }
  return result;
}
double mhz(int iSleepTime){
        double dRate;
 
        start_counter();
        sleep(iSleepTime);
        return (get_counter() / iSleepTime / 1e6);
 
}
int main()
{
        printf("CPU clock = %.1f\n",mhz(1));
}
---------------------------------------------------------------------------
mentre il secondo è il seguente:
#include <stdio.h>
#include <sys/times.h>
/*definite come sopra, ma in un file esterno*/
void access_counter(unsigned *hi, unsigned *lo);
void start_counter();
double get_counter();
/**/
double mhz(int verbose, int sleeptime){
 
  double rate;
 
  start_counter();
  sleep(sleeptime);
  rate = get_counter() / (1e6*sleeptime);
  if (verbose){
    printf("Processor clock rate ~= %.1f MHz\n", rate);
    printf("CPU cycles/sec ~= %.1f\n", rate * (1e6*sleeptime));
  }
  return rate;
}
int main(){
  double mhz(int, int);
  mhz(1,1);
}
-------------------------------------------------------------------------------
Il primo mi restituisce il valore esatto della velocità del processore (con
errore dell'1-2%), mentre il secondo da valori variabili, a volte anche
negativi), anche se come vedete, è identico (semanticamente, non
sintatticamente, al primo).
Visto che lo stesso problema non si presenta sul computer di un mio amico
con processore a 750 MHz (il mio è a 2400), vorrei sapere cosa ne pensate.
Grazie
        Fabbro

 con processore a 750 MHz (il mio è a 2400), vorrei sapere cosa ne pensate.
Da me non succede.
Direi che il compilatore ha problemi con l'asm inline. Alcuni bit 
restituiti da rdtsc verranno alterati in qualche modo.
Prova a iniettare il codice macchina direttamente.
Assembla qualcosa del genere:
; parametri:
; unsigned *hi
; unsigned *lo
;
; stack:
; ret
; lo  <-- ebp+8
; hi  <-- ebp+4
; ebp <-- ebp
push	ebp
mov	ebp, esp
push	eax
push	edx
push	ebx
xor	eax, eax
cpuid		; pipeline flush
rdtsc		; legge il TSC
mov	ebx, [ebp+4]
mov	[ebx], edx	; *hi = edx
mov	ebx, [ebp+8]
mov	[ebx], eax	; *lo = eax
pop	ebx
pop	edx
pop	eax
pop	ebp
ret
L'ho scritto di getto quindi controlla bene (ricorda che il C inserisce 
i parametri nello stack in ordine inverso).
A questo punto puoi scrivere il relativo codice macchina come:
unsigned char my_code[] = {0x33, 0xc0, .........};
Fai puntare un puntatore a funzione a my_code e sei a posto.
Kiuhnm

 i parametri nello stack in ordine inverso).
C'erano errori di distrazione.
Ecco il codice completo funzionante:
typedef unsigned (* func_ptr)(unsigned *hi, unsigned *lo);
int main()
{
	unsigned char my_code[] = {0x55, 0x8B, 0xEC, 0x50, 0x52, 0x53, 0x33,
							   0xC0, 0x0F, 0xA2, 0x0F, 0x31, 0x8B, 0x5D,
							   0x08, 0x89, 0x13, 0x8B, 0x5D, 0x0C, 0x89,
							   0x03, 0x5B, 0x5A, 0x58, 0x5D, 0xC3};
/*
	_asm
	{
		; parametri:
		; unsigned *hi
		; unsigned *lo
		;
		; stack:
		; lo  <-- ebp+0ch
		; hi  <-- ebp+8
		; ret <-- ebp+4
		; ebp <-- ebp
		push    ebp
		mov    ebp, esp
		push    eax
		push    edx
		push    ebx
		xor    eax, eax
		cpuid        ; pipeline flush
		rdtsc        ; legge il TSC
		mov    ebx, [ebp+8]
		mov    [ebx], edx    ; *hi = edx
		mov    ebx, [ebp+0xc]
		mov    [ebx], eax    ; *lo = eax
		pop    ebx
		pop    edx
		pop    eax
		pop    ebp
		ret
	}
*/
	func_ptr f = (func_ptr)(unsigned)my_code;
	unsigned hi, lo;
	f(&hi, &lo);
	return 0;
}
Kiuhnm

"Kiuhnm" <kiuh...@yahoo.it.invalid> ha scritto nel messaggio 
news:1p92e.709442$b5.32...@news3.tin.it...

Scusa se non ti ho risposto...
ti ringrazio del supporto, appena posso controllerò il funzionamento e ti 
farò sapere.
    Fabbro