2008-08-29 6 views
5

un código que redondea la división de demostrar (C-sintaxis):¿Cómo dividir dos números de 64 bits en Kernel de Linux?

#define SINT64 long long int 
#define SINT32 long int 

SINT64 divRound(SINT64 dividend, SINT64 divisor) 
{ 
    SINT32 quotient1 = dividend/divisor; 

    SINT32 modResult = dividend % divisor; 
    SINT32 multResult = modResult * 2; 
    SINT32 quotient2 = multResult/divisor; 

    SINT64 result = quotient1 + quotient2; 

    return (result); 
} 

Ahora bien, si este fuera el usuario espacio que probablemente ni siquiera se dio cuenta de que nuestro compilador genere código para aquellos operadores (por ejemplo, divdi3() para la división). Es probable que estemos vinculados con 'libgcc' sin siquiera saberlo. El problema es que Kernel-space es diferente (por ejemplo, no libgcc). ¿Qué hacer?

arrastre de Google durante un tiempo, el aviso de que casi todo el mundo se dirige a la variante sin firmar:

#define UINT64 long long int 
#define UINT32 long int 

UINT64 divRound(UINT64 dividend, UINT64 divisor) 
{ 
    UINT32 quotient1 = dividend/divisor; 

    UINT32 modResult = dividend % divisor; 
    UINT32 multResult = modResult * 2; 
    UINT32 quotient2 = multResult/divisor; 

    UINT64 result = quotient1 + quotient2; 

    return (result); 
} 

sé cómo solucionar éste: Invalidar udivdi3() y umoddi3() con _do_div () _ de asm/div64.h. ¿Bien hecho? Incorrecto. Firmado no es lo mismo que unsigned, sdivdi3() _ no simplemente llama a udivdi3(), son funciones separadas por algún motivo.

¿Ha resuelto este problema? ¿Conoces una biblioteca que me ayude a hacer esto? Estoy realmente atascado así que todo lo que puedas ver aquí que yo no haga en este momento sería realmente útil.

Gracias, Chad

Respuesta

0

ldiv?

Editar: relee el título, por lo que es posible que desee ignorarlo. O no, dependiendo de si tiene una versión apropiada que no sea de biblioteca.

4

Aquí está mi solución realmente ingenua. Su experiencia puede ser diferente.

Mantenga un bit de signo, que es sign(dividend)^sign(divisor). (O *, o /, si está almacenando su signo como 1 y -1, a diferencia de falso y verdadero. Básicamente, negativo si cualquiera de ellos es negativo, positivo si ninguno o ambos son negativos.)

Entonces , llama a la función de división sin signo en los valores absolutos de ambos. Luego vire el letrero nuevamente en el resultado.

P.S. Así es como se implementa __divdi3 en libgcc2.c (de GCC 4.2.3, la versión que está instalada en mi sistema Ubuntu). Acabo de verificar. :-)

0

No creo que (al menos no puede encontrar una manera de hacer) Chris' answer trabajo en este caso porque do_div() realmente cambia el dividendo en el lugar. Obtener el valor absoluto implica una variable temporal cuyo valor cambiará en la forma en que lo necesito, pero que no puede pasarse de mi __divdi3() anulación.

no veo un camino alrededor de la firma parámetro por valor de __divdi3() en este punto excepto para imitar la técnica utilizada por do_div().

Podría parecer que estoy haciendo todo lo posible aquí y debería encontrar un algoritmo para hacer la división de 64 bits/32 bits que realmente necesito. La complicación añadida aquí es que tengo un montón de código numérico usando el operador '/' y necesitaría pasar por ese código y reemplazar cada '/' con mis llamadas a funciones.

Me estoy desesperando lo suficiente como para hacer eso.

Gracias por cualquier seguimiento, Chad

Cuestiones relacionadas