Foros - Stratos

Stratos => General => Mensaje iniciado por: [EX3] en 06 de Octubre de 2004, 02:39:28 AM

Título: Trabajar Con Bytes
Publicado por: [EX3] en 06 de Octubre de 2004, 02:39:28 AM
 Wenas.

Resulta que estoy trabajando en un buffer de intercambio de datos para el TLSA Engine. El buffer es un array de tipo Byte en el que necesito guardar y leer valores de diferentes tipos: cadenas de texto (String), enteros largos (Long / DWORD) y coma flotante (Single / Float). De momento solo tengo implementada la lectura y escritura del mas sencillo de todos, las cadenas de texto y me quede bloqueado con el entero largo. Iluso de mi creia que sumando simplemente los 4 bytes que componen un Entero Largo obtendria el valor, pero ya averigue ke no es asi  (nooo)

Lo que busco en informacion de como leer y escribir Enteros Largos y decimales de Coma Flotante en array de Bytes. Gracias.

Salu2...
Título: Trabajar Con Bytes
Publicado por: averbell en 06 de Octubre de 2004, 09:06:33 AM
 no entiendo muy bien a lo que te refieres, pero si lo que te pasa es que en lugar de crearte el numero 5900 te suma las cifras?
Título: Trabajar Con Bytes
Publicado por: sés en 06 de Octubre de 2004, 10:08:50 AM
 No sé si te he entendido, pero si tienes los números 1, 2, 3 y 4 y quieres formar el 1234... con 1+2+3+4 como que no lo consigues O_O

Para una entero sería algo como:
byte b[] = {0x04, 0x03, 0x02, 0x01 }
int i = b[0] | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);

Después de esto:
i = 0x01020304;

En el caso de C, lo más sencillo sería algo del tipo:
int i = *((int *)&b[n])

Para un float ahora mismo no lo sé, además depende mucho de cómo estén esos números en el array de bytes. En el ejemplo anterior el mismo nº podría estar almacenado como { 0x01, 0x02, 0x03, 0x04 }, lo que cambiaría la forma de crear el entero.

De todas formas... no entiendo bien el problema. Si tú mismo lees y escribes en ese buffer, pues hazlo como mejor te venga, ¿no?
Título: Trabajar Con Bytes
Publicado por: [EX3] en 06 de Octubre de 2004, 03:33:54 PM
 A ver, me explico un poco mas:

Mediante la instruccion Put de VB guardo un valor de tipo Long (4 Bytes) en un archivo con acceso binario, por ejemplo.

Luego abro el archivo en modo binario y lo almaceno en un array de Bytes.

El valor de la variable que guarde era 40961024 que en hexadecimal seria: 0x00, 0x04, 0x71, 0x02, en binario seria: 0, 4, 113, 2.

La pregunta es, como hago yo para obtener el valor [40961024] de [0x00, 0x04, 0x71, 0x02] o [0, 4, 113, 2]?

Espero ke haya quedado algo mas claro  ;)

Salu2...
Título: Trabajar Con Bytes
Publicado por: sés en 06 de Octubre de 2004, 03:38:17 PM
Cita de: "[EX3"] Mediante la instruccion Put de VB guardo un valor de tipo Long (4 Bytes) en un archivo con acceso binario, por ejemplo.
Pues digo yo que habrá una función Get, ¿no?
Vamos, en los lenguajes que conozco, si tienes un putX(), en alguna parte existe un getX().

En el caso de que no existiera o de que no te sirviera por alguna extraña razón, pues implementa tú mismo los put y el get que necesites.
Título: Trabajar Con Bytes
Publicado por: [EX3] en 06 de Octubre de 2004, 05:28:58 PM
 
Cita de: "sés"Pues digo yo que habrá una función Get, ¿no?
Vamos, en los lenguajes que conozco, si tienes un putX(), en alguna parte existe un getX().

En el caso de que no existiera o de que no te sirviera por alguna extraña razón, pues implementa tú mismo los put y el get que necesites.
A ver, lo de escribir a un archivo con Put era un ejemplo. Yo lo ke busco es poder tener un array de bytes en el ke poder escribir y leer un Long y un Single(Float), osea, interpretar los 4 bytes y componer el valor y viceversa segun tipo de dato mediante unas funciones propias como por ejemplo:
Sub Write_Long(Var As Long, Pos As Long) 'Escribe un valor Long en el array de Bytes.
Sub Read_Long(Var As Long, Pos As Long) 'Lee un valor Long del array de Bytes.

Salu2...
Título: Trabajar Con Bytes
Publicado por: sés en 06 de Octubre de 2004, 05:33:00 PM
 Pues entonces usa el ejemplo que te puse al principio, que sería el get y haz el contrario para el put.
Título: Trabajar Con Bytes
Publicado por: averbell en 06 de Octubre de 2004, 07:11:33 PM
 yo en mis programas uso el array
dim sdatos() as byte

'cargo los datos en la variable sdatos() con redim....

'''''''''''''''
Creo el buffer en sdatos.
cargo los datos en la varaiable con get #1,,sdatos

Para convertirlo
uso la funcion chr(sdatos(posicionbyte))

es decir
sdato(100)
sdato(29)
sdato(22)
sdato(22)
en asc e valor es (EJEMPLO)
100=3
29=4
22=1

3411
une los datos en una cadena string mediande & i luego combiertelo a un valor integer
si eso te paso mi ejemplo de como la hago yo


----------------------------------------
Ma software
Portal de informática y programación
y Soporte técnico.
Last Program: Virus and trojan Remover
Contact:Beltran_a@terra.es
----------------------------------------

Título: Trabajar Con Bytes
Publicado por: Helius en 06 de Octubre de 2004, 07:37:25 PM
 No te he entendido muy bien, pero si lo que quieres es serializar datos de 32 bits en una array de bytes prueba esto.

Yo no tengo ni idea de VB pero hice estas funciones en ensamblador que funcionan bien para hacer precisamente eso (supongo que podrás hacer lo mismo en VB dando algun rodeo):


//-------------------------------------------------------------------------------
// Función: UTIL_32toChar
// Propósito: Pasa el dato a 4 bytes, necesita un buffer de almenos 4 bytes
//-------------------------------------------------------------------------------
inline void UTIL_32toChar(int iData, byte* buffer)
{
Assert(buffer, "Se ha pasado un puntero inválido: UTIL_32toChar");

byte temp[4]={0};
byte* dir=temp;

__asm{
 push esi
 push eax
 mov esi, dir
 mov eax, iData
 mov [esi],al
 shr eax,8
 mov [esi+1],al
 shr eax,8
 mov [esi+2],al
 shr eax,8
 mov [esi+3],al
 pop eax
 pop esi
};

memcpy(buffer, temp, 4);
}

//-------------------------------------------------------------------------------
// Función: UTIL_CharTo32
// Propósito: Devuelve un dato de 4 bytes almacenado en un buffer (de almenos 4 bytes)
//-------------------------------------------------------------------------------
inline int UTIL_CharTo32int(byte* buffer)
{
Assert(buffer, "Se ha pasado un puntero inválido: UTIL_CharTo32");

byte temp[4]={0};
memcpy(temp, buffer, 4);
byte* dir=temp;

int result=0;

__asm{
 push esi
 push eax
 mov esi, dir
 mov al,[esi+3]
 shl eax,8
 mov al,[esi+2]
 shl eax,8
 mov al,[esi+1]
 shl eax,8
 mov al,[esi]
 mov result,eax
 pop eax
 pop esi
};

return result;
}


No se si tendrán sentido para ti, pero para mi si. Esas funciones estan hechas para ints pero valen para cualquier dato de 4 bytes.

Suerte.
Título: Trabajar Con Bytes
Publicado por: [EX3] en 06 de Octubre de 2004, 07:48:44 PM
 averbell, si no he entendido mal:
A = Chr(Byte(0)) & Chr(Byte(1)) & Chr(Byte(2)) & Chr(3))
A = Chr(0) & Chr(4) & Chr(113) & Chr(2)
A = "041132"

Que todo esto seria lo mismo que:
A = Byte(0) & Byte(1) & Byte(2) & Byte(3)
A = 0 & 4 & 113 & 2
A = 41132

41132 <> 40961024

Asi tampoco funciona. No se trata de una simple concatenacion de valores, algo mas hay ke hacer pero no tengo ni pajolera idea y llevo asi una semana intentando buscar la solucion via Google y con ayuda de un amigo que esta en la carrera y nada aun  :(

sés, tampoco me funciona bien con tu ejemplo.

Helius, gracias por el codigo, voy a intentar traducirlo al VB a ver si tira  :)

Si no llego a encontrar la solucion estoy pensando en hacer dos cosas:
1.- Cerrar el buffer a uso exclusivo del script, vamos, sin acceso desde archivos, asi podria hacerme mi propio formato para almacenar los numeros mas o menos de la manera ke mas descrito antes, agrupar el valor en numeros de 3 digitos en cada byte: 40961024 = ["000"|"040"|"961"|"024"] mas o menos.

2.- Crear el buffer en un archivo y acceder a el mediante Put y Get de VB, aunque esta opcion no me agrada mucho.

Salu2...
Título: Trabajar Con Bytes
Publicado por: [EX3] en 06 de Octubre de 2004, 08:07:22 PM
 Por cierto, algun buen manual de ASM, por ke si no me va a ser imposible traducir tu codigo Helius  (yo de ASM 0 patartero (uoh) )
La verdad, con que me puedieras explicar ke hacen las funciones de tu codigo me bastaria supongo:
push esi
push eax
mov esi, <variable temporal>
mov eax, <variable integer>
mov [esi],al
shr eax,8
mov [esi+1],al
shr eax,8
mov [esi+2],al
shr eax,8
mov [esi+3],al
pop eax
pop esi

Salu2...
Título: Trabajar Con Bytes
Publicado por: Helius en 06 de Octubre de 2004, 08:34:52 PM
 Si, muy sencillo...

En esi tiene el puntero a la temporal.
En eax guarda el dato.

Mueve al primer byte de la temporal el byte mas bajo de eax.
Rota eax a la dercha 8 bits (con lo cual queda en la parte baja de eax el segundo byte de la temporal).

Mueve al segundo byte de la temporal (esi+1) el byte mas bajo de eax, que como lo habíamos rotado ahora será el segudo byte del dato.
Rota eax a la derecha 8 bits (con lo cual queda en la parte baja de eax el tercer byte de la temporal).

.
.
.

Así con los cuatro bytes que finalmente quedan en la temporal.

Luego copia esos cuatro bytes al búfer en donde los queríamos.
Título: Trabajar Con Bytes
Publicado por: Helius en 06 de Octubre de 2004, 09:01:37 PM
 Un ejemplo:

Si el número es 0x02578945 crearía en el array temporal de 4 bytes lo siguiente:

45 89 57 02

Logicamente para recuperar los cuatro bytes se hace lo contrario ;)

Espero que lo hallas entendido, en VB se podrá hacer de alguna manera, en vez de rotar divide, es lo mismo.
Título: Trabajar Con Bytes
Publicado por: averbell en 06 de Octubre de 2004, 09:48:59 PM
 Aquí te pongo ejemplo de un codigo echo:
tenenmos un fichero.dat que contiene la cadena 15.220
Dim memory() As Byte
Dim buffer As Integer
Dim variable As Single
Dim temporal As String
'///////////////////////////////////////
'/Cargar los datos en memoria/
'///////////////////////////////////////

Open "fichero.dat" For Binary As #1
buffer = LOF(1)
ReDim memory(0 To buffer) As Byte
Get #1, , memory
Close #1

'Crearemos una cadena con coma flotante que contiene 15,220
temporal = ""
For d = 0 To UBound(memory)
temporal = temporal & Chr(memory(d))
Next
variable = CSng(temporal)
msgbox  variable

'COMPROBADO variable sera igual a 15.220
Título: Trabajar Con Bytes
Publicado por: sés en 06 de Octubre de 2004, 09:56:23 PM
 Esto funciona perfectamente:
void putInt( int value, unsigned char buffer[], int pos )
{
  buffer[pos] = (unsigned char)(value & 0xff);
  buffer[pos+1] = (unsigned char)((value >> 8) & 0xff);
  buffer[pos+2] = (unsigned char)((value >> 16) & 0xff);
  buffer[pos+3] = (unsigned char)((value >> 24) & 0xff);
}


int getInt( unsigned char buffer[], int pos )
{
  int value;

  value = buffer[pos];
  value |= buffer[pos+1] << 8;
  value |= buffer[pos+2] << 16;
  value |= buffer[pos+3] << 24;

  return value;
}



NOTA: He puesto código de más para que se entienda mejor.
Título: Trabajar Con Bytes
Publicado por: Helius en 06 de Octubre de 2004, 10:06:40 PM
 Es lo mismo, pero yo soy más cafre, en su día se me ocurrió en ASM  :P  
Título: Trabajar Con Bytes
Publicado por: Trancos en 06 de Octubre de 2004, 10:20:00 PM
 La forma más facil es declarar un puntero al dato del tipo que quieras y hacer casting. Lo que pasa es que no se copmo hacerlo en VB, sólo lo se hacer en C.

Tienes el buffer de 1024 bytes:

byte *buffer = new byte[1024];

Digamos que la posición es al inicio del buffer para no liar la marrana. Para castear al tipo int haces:

int *puntero = (int *)byte;

Lo que pasa es que no se si VB te permite hacerlo. Creo que deberías trabajar en C/C++ si vas a estar trabajando directamente sobre la memoria.

Si no puedes hacer esto no te queda más remedio que recurrir al álgebra, leyendo los 4 bytes por separado y haciendo la siguiente operación:

numero = byte 1 + byte 2 * 256 + byte 3 * 65536 + byte 4 * 16777216
Título: Trabajar Con Bytes
Publicado por: Trancos en 06 de Octubre de 2004, 10:25:45 PM
 donde puse:

int *puntero = (int *)byte;

era:

int *puntero = (int *)buffer;

perdón  (nooo)
Título: Trabajar Con Bytes
Publicado por: [EX3] en 07 de Octubre de 2004, 01:25:37 AM
 
Cita de: "Huevox"numero = byte 1 + byte 2 * 256 + byte 3 * 65536 + byte 4 * 16777216
Yo alucino en colores, llevo dias intentando aplicar esta formula similar ke me paso mi colega y no me funcionaba, ahora me ha dado por probarla de coña y casi boto de la silla cuando he visto ke me ha devuelto el valor correcto!!  (uoh)

Ahora solo me falta averiguar como leer/escribir valores Single/Float ke me imagino ke sera mas o menos similar ya ke tb son 4 bytes.

Muchas Gracias a todos por la ayuda  (ole)

Salu2...

P.D.: Tambien me dado cuenta que he colgado el post en el general de Stratos en vez del foro de programacion, ha sido un lapsus  :P  
Título: Trabajar Con Bytes
Publicado por: herman en 07 de Octubre de 2004, 08:37:06 AM
 el formato de los numeros de coma flotante es bastante lioso:

S EEEEEEEE FFFFFFFFFFFFFFFFFFFFFFF

el bit S representa el signo, los 8 bits E representan el exponente y los restantes bits son la fraccion. Si quieres obtener el numero que representa debes hacer lo siguiente:

solamente si 0
si E es 0 o 255(11111111) esta formula no sirve, y tienes que seguir otros criterios, que no me acuerdo. Espero que te ayude.
Título: Trabajar Con Bytes
Publicado por: [EX3] en 11 de Octubre de 2004, 03:10:59 AM
 Vale, me acabo de dar cuenta hoy de que la formula que use para lectura de LONG falla al desbordarse la variable al leer un numero negativo y al realizar el paso contrario, osea, en vez de lectura escritura, al interpretar el 2º byte tb se desborda.

Demasiados lios, creo ke me decanto o por hacer mi propio formato y guardarlo asi en el array de bytes o seguir utilizando el array de Variants facilitando el trabajo entre VB y el motor script que usa VBS al no hacer conversiones pero haciendolo jodido si un dia me da la vena y quiero pasar el codigo a C++ por ejemplo, o crear el buffer en un archivo en disco y leer y escribir en el mediante las funciones Get y Put del propio lenguaje.

No pense que esto me fuera a traer tantas complicaciones  :(

Salu2...
Título: Trabajar Con Bytes
Publicado por: sés en 11 de Octubre de 2004, 08:33:06 AM
Cita de: "[EX3"] Vale, me acabo de dar cuenta hoy de que la formula que use para lectura de LONG falla al desbordarse la variable al leer un numero negativo y al realizar el paso contrario, osea, en vez de lectura escritura, al interpretar el 2º byte tb se desborda.
Esa una de las razones por las que se realiza con desplazamientos. Otra es la velocidad.
Título: Trabajar Con Bytes
Publicado por: fiero en 11 de Octubre de 2004, 01:37:55 PM
 EX3 ¿en VB hay desplazamientos? Es que yo me quedé en el qbasic y no me acuerdo. ES mejor que te acostumbres a desplazar, en vez de multiplicar por potencias de 2, como dice sés

un saludo
Título: Trabajar Con Bytes
Publicado por: Pogacha en 11 de Octubre de 2004, 01:53:50 PM
 Casi que te recomendaria que aprendas C.
Título: Trabajar Con Bytes
Publicado por: [EX3] en 12 de Octubre de 2004, 03:47:46 AM
 
Cita de: "fiero"EX3 ¿en VB hay desplazamientos?
Weno, yo eske aun hay cosas ke solo conozco de oidas y ke ni si kiera se ke son y si algunas vez las he tocado, esto me pasa por programar en lenguajes como BASIC o VB en mi caso  <_<  
Podriais explicarme lo ke seria un Desplazamiento?

Pogacha, aprender C es la mejor solucion ke me dan, pero kitando algunas historias ke tengo me sigue saliendo mas comodo programar en VB, al menos por el momento  :rolleyes:

Salu2...
Título: Trabajar Con Bytes
Publicado por: Sacrifai en 12 de Octubre de 2004, 09:23:27 AM
Cita de: "[EX3"] Podriais explicarme lo ke seria un Desplazamiento?
Pues yo no soy muy especialista en trabajar con bytes, pero creo que e refiere a mover un byte a otro.
Título: Trabajar Con Bytes
Publicado por: BeRSeRKeR en 12 de Octubre de 2004, 12:36:05 PM
 Parece que en Visual Basic no existe un operador de desplazamiento de bits. A ver si este artículo te ayuda en algo.

Saludos.
Título: Trabajar Con Bytes
Publicado por: Mars Attacks en 12 de Octubre de 2004, 01:17:37 PM
 00011001 << 2 = 01100100 (desplazamiento a izquierdas)

01011000 >> 2 = 00010110 (el desplazamiento a derechas tiene varios tipos, dependiendo de si arrastra bit de signo o no).
Título: Trabajar Con Bytes
Publicado por: [EX3] en 13 de Octubre de 2004, 02:58:44 AM
 Vale ya me he hecho una idea, por cierto, BeRSeRKeR, leyendo el articulo que me has recomendado he visto que las funciones descritas en codigo Basic, LShifWord() y RShiftWord(), las he visto en el codigo de un programa escrito en VB que baje hace algun tiempo, por eso comente que me sonaba de algo lo de Desplazamientos de Bytes pero no acertaba a saber si era en VB, gracias por el articulo  :)

De momento creo que lo del buffer de intercambio para el script lo seguire haciendo mediante un array de Variants, por que programar funciones para trabajar solo con enteros (WORD/DWORD) y caracteres (CHAR), pero no con decimales (FLOAT), a nivel de bytes no me valdria y seria dejar el proyecto cojo, aunque si algun dia logro hacerlo solo tendria que cambiar un modulo de codigo en el proyecto y listo, asi que tampoco hay mucho problema  :)

Gracias a todos por la ayuda.

Salu2...
Título: Trabajar Con Bytes
Publicado por: sés en 13 de Octubre de 2004, 09:09:22 AM
 No estoy seguro, pero... ¿VB no tiene operadores booleanos? Con eso creo que te serviría.
Título: Trabajar Con Bytes
Publicado por: [EX3] en 13 de Octubre de 2004, 05:54:17 PM
 
Cita de: "sés"No estoy seguro, pero... ¿VB no tiene operadores booleanos? Con eso creo que te serviría.
Estos son los operadores de Visual Basic 6:
Título: Trabajar Con Bytes
Publicado por: sés en 13 de Octubre de 2004, 06:50:12 PM
 Me refiero a: AND, OR, NOT y XOR
Creo recordar que funcionan como operadores booleanos si se utilizan con enteros.

Haz una prueba:
PRINT 1 OR 2
PRINT 6 AND 3
PRINT 7 XOR 2


Esto debería imprimir (si no me he confundido):
3
2
5
Título: Trabajar Con Bytes
Publicado por: [EX3] en 13 de Octubre de 2004, 07:59:13 PM
 PRINT 1 OR 2
PRINT 6 AND 3
PRINT 7 XOR 2

3
2
5

Correcto  :)

Entonces con estos operadores podria realizar desplazamientos de bits?

Salu2...
Título: Trabajar Con Bytes
Publicado por: sés en 13 de Octubre de 2004, 09:24:46 PM
 No, no puedes hacer desplazamientos, pero te pueden ayudar a resolver tu problema con los números negativos.

No recuerdo bien VB, pero creo que sería algo como:
Dim b(100) AS Byte ; el array de bytes
Dim res, b0, b1, b2 AS Long ; TODAS como Long

; meter cada byte en un long
b0 = b(1)
b1 = b(2)
b2 = b(3)
b3 = b(4)

; crear el long
res = b0 AND 255 ; b0 & 0xff
res = res OR ((b1 AND 255) * 256) ; res | ((b1 & 0xff) << 8)
res = res OR ((b2 AND 65535) * 65536)  ; res | ((b2 & 0xff) << 16)
res = res OR ((b3 AND 16777215) * 16777216)  ; res | ((b3 & 0xff) << 24)


Al hacer el AND, se eliminan los bits superiores que indican el signo, por lo que CREO que debería funcionar si no me he confundido al escribir ^_^
Título: Trabajar Con Bytes
Publicado por: [EX3] en 14 de Octubre de 2004, 01:14:43 AM
 El codigo funciona pero tambien falla con los negativos. Gracias por el intento ;)

Salu2...
Título: Trabajar Con Bytes
Publicado por: sés en 14 de Octubre de 2004, 08:58:50 AM
 Je,je... me confundí, los AND deberían ser todos con 255.

Te lo pongo de nuevo corregido y algo más clarito:

Dim b(100) AS Byte; el array de bytes
Dim res, b0, b1, b2 AS Long; TODAS como Long

; meter cada byte en un long
b0 = b(1) AND 255 ; b(1) & 0xff
b1 = b(2) AND 255 ; b(2) & 0xff
b2 = b(3) AND 255 ; b(3) & 0xff
b3 = b(4) AND 255 ; b(4) & 0xff

; crear el long, es el mismo código que ya te pusieron más arriba
; la diferencia es que b0, b1, b2 y b3 son positivos all hacerles AND con 255
res = b0 ; b0
res = res OR (b1 * 256); res | (b1 << 8)
res = res OR (b2 * 65536) ; res | (b2 << 16)
res = res OR (b3 * 16777216) ; res | (b3 << 24)
Título: Trabajar Con Bytes
Publicado por: [EX3] en 17 de Octubre de 2004, 06:45:40 AM
 Aun con la correccion el valor sigue siendo incorrecto. Mira a ver, ke a lo mejor he puesto algo mal en el codigo y no me he dado cuenta:
'Lee un entero largo del buffer de datos:
Public Sub Read_LONG(Var As Long, Pos As Long)
On Error Resume Next
Dim b(3) As Long

If Pos + 3 > UBound(Buffer) Then Exit Sub

b(0) = Buffer(Pos) And 255
b(1) = Buffer(Pos + 1) And 255
b(2) = Buffer(Pos + 2) And 255
b(3) = Buffer(Pos + 3) And 255

Var = b(0)
Var = Var Or (b(1) * 256)
Var = Var Or (b(2) * 65536)
Var = Var Or (b(3) * 16777216)
End Sub

Salu2...
Título: Trabajar Con Bytes
Publicado por: sés en 17 de Octubre de 2004, 10:23:34 AM
 No veo ningún error (de escritura ^_^).

Si tuviera VB podría probar y decirte cómo hacerlo... o por lo menos ver porqué falla. De todas formas, si me dices qué valores hay en el array y el resultado, puede que vea algo.
Título: Trabajar Con Bytes
Publicado por: [EX3] en 18 de Octubre de 2004, 03:03:47 AM
 Valor Original: -40961024
Bytes en Hexadecimal: 0x00, 0xFC, 0x8E, 0xFD
Bytes en Enteros: 0, 252, 142, 253
Valor devuelto por la funcion: 9370624

Para hacer pruebas en tiempo de ejecucion te podria pasar un pequeño programa que hice para realizar pruebas de codigo que lleva integrado el M$ Script Control con el VBScript y este aun no soportando tipos de datos (solo trabaja con Variants) tiene toda las instrucciones del VB para la tarea en cuestion y se puede trabajar datos especificos mediante conversiones CStr(), CByte(), CLng()... Si te interesa lo subo a mi ftp y te lo bajas, es ideal para realizar pruebas con codigos sin tener que tener instalado el VB  :)

Salu2...
Título: Trabajar Con Bytes
Publicado por: sés en 18 de Octubre de 2004, 09:33:48 AM
 No sé si te has fijado en lo que te sale:
9370624 = 8EFC00h
Curioso, ¿no? Es el valor que deberías tener en Val antes de hacer nada con el cuarto byte (FDh). Es como si te lo hubieras comido.

Comprueba que b(3) tenga el valor 253 (FDh).
b(3) * 16777216 tiene que valer -50331648 (FD000000h).

O sea:
Var = b(0)
b(0) = 0
Var = 0
Var = Var Or (b(1) * 256)
b(1) = 252 (000000FCh)
b(1) * 256 = 64512 (0000FC00h)
Var = 64512 (0000FC00h)
Var = Var Or (b(2) * 65536)
b(2) = 142 (0000008Eh)
b(2) * 65536 = 9306112 (008E0000h)
Var = 9370624 (008EFC00h) ¿TE SUENA?
Var = Var Or (b(3) * 16777216)
b(3) = 253 (000000FDh)
b(3) * 16777216 = -50331648 (FD000000h)
Var = -40961024 (FD8EFC00h)
Título: Trabajar Con Bytes
Publicado por: sés en 18 de Octubre de 2004, 01:31:55 PM
 Que cosas, si tengo el Access. He estado probando y ya sé lo que pasa; Hay un desbordamiento en el 4º byte.
Al hacer:
  b(3) * 16777216

estamos haciendo:
  253 * 16777216 = 4244635648 (FD000000)

Lo que nos provoca un desbordamiento porque en un Long no se puede representar ese número (el máximo es 2147483647 ó 0x7FFFFFFF).

La única solución es montar el último byte de otra forma, así:

Dim msk As Long
Dim bit As Long
bit = &H80000000
msk = &H80

While msk <> 0
   If (b(3) And msk) <> 0 Then
       Var = Var Or bit
   End If
   msk = msk \ 2 And &H7F
   bit = bit \ 2 And &H7F000000
Wend

Utilizando solo operaciones booleanas y divisiones (que no provocan desbordamiento ;))

Te pongo el código completo con el que he probado:
Dim Buffer(10) As Byte
Dim b(4) As Long
Dim pos As Integer
Dim Var As Long
   
Buffer(0) = &H0     ' 0
Buffer(1) = &HFC    ' 252
Buffer(2) = &H8E    ' 142
Buffer(3) = &HFD    ' 253
   
pos = 0
   
b(0) = Buffer(pos) And &HFF
b(1) = Buffer(pos + 1) And &HFF
b(2) = Buffer(pos + 2) And &HFF
b(3) = Buffer(pos + 3) And &HFF
   
Var = b(0)
Var = Var Or (b(1) * 256)
Var = Var Or (b(2) * 65536)
   
' caso especial
Dim msk As Long
Dim bit As Long
bit = &H80000000
msk = &H80
While msk <> 0
   If (b(3) And msk) <> 0 Then
       Var = Var Or bit
   End If
   msk = msk \ 2 And &H7F
   bit = bit \ 2 And &H7F000000
Wend


Esto lo he probado y me da el resultado correcto: -40961024
Título: Trabajar Con Bytes
Publicado por: [EX3] en 18 de Octubre de 2004, 05:00:23 PM
 Correcto, funciona  :) Se ve que al usar el On Error Resume Next no me percate, ni aun viendo la operacion, el error de desbordamiento. Pues muchas gracias por tu ayuda. Ahora solo me falta terminar lo de la lectura y escritura de coma flotante y ya podria trabajar con bytes en el motor.

Salu2...
Título: Trabajar Con Bytes
Publicado por: sés en 18 de Octubre de 2004, 05:12:12 PM
 *arf, arf...* Me alegro de que funcione de una vez.

De todas formas, si vas a realizar estas operaciones muchas veces, intenta optimizar. Eso no creo que sea precisamente rápido... además es VB :huh:

Seguramente puedas optimizar algunas cosas. Además, sabiendo cuál era el problema... y tú que sabes VB :P, a lo mejor se te ocurre otra solución; a mí solo se me ocurrió esa "ñapa".

Te digo una que se me acaba de ocurrir:
Utiliza un byte más (por ejemplo) para los números. Guarda los bytes de la misma forma, excepto el 4º, al que le quitas el bit de signo (así no habrá desbordamiento al multiplicar). En ese byte extra indica el bit de signo (0 ó 1).
Utilizas un byte más para los Long (para el resto no te hace falta, supongo), pero es más rápido.
Título: Trabajar Con Bytes
Publicado por: [EX3] en 18 de Octubre de 2004, 05:50:06 PM
 
Cita de: "sés"Seguramente puedas optimizar algunas cosas. Además, sabiendo cuál era el problema... y tú que sabes VB :P, a lo mejor se te ocurre otra solución; a mí solo se me ocurrió esa "ñapa".
Vale  :P , se programar en VB "mas o menos con soltura" pero no a un nivel tan avanzado como para tratar temas "tan complejos" para mi como esta siendo esto de trabajar con bytes. Yo de momento este codigo lo dejare como esta ya que al menos funciona y aparte de servir para el motor me sirve para otros programas que tengo por ahi y que esta funcion les vendra de perlas.

Si resultase muy lento el trabajar datos de esta manera, a nivel de bytes en VB, recurriria otra a vez a los "comodos" Variants aun ocupando estos mas espacio de lo debido. Sobre lo del byte de mas para almacenar el signo del numero me parece una buena idea  :) , ya de paso podria improvisar y hacerme tb un formato propio para almacenar los numero de coma flotante (mediante alguna ñapa, claro) y un problema menos. Cuando tenga un ratito trasteo un poco con la idea.

Salu2...
Título: Trabajar Con Bytes
Publicado por: sés en 22 de Octubre de 2004, 01:43:49 PM
 Aquí tienes una versión mejorada... y más lógica de los famosos bytes.

Te pongo la parte del último byte, que es la que cambia
' caso especial
Dim signo As Long
If (b(3) And &H80) <> 0 Then
   signo = &H80000000
Else
   signo = 0
End If
b(3) = b(3) And &H7F
Var = Var Or (b(3) * 16777216) Or signo


Como ves te puedes olvidar de eso de añadir un byte para el signo.

La verdad es que no sé en qué estaba pensando cuando hice lo otro... en fin, mis neuronas debían estar de vacaciones (genial)
Título: Trabajar Con Bytes
Publicado por: [EX3] en 22 de Octubre de 2004, 07:05:52 PM
 
Cita de: "sés"(...) en fin, mis neuronas debían estar de vacaciones (genial)
Pues si te cuento yo como tengo las mias ultimamente, estoy pa'l arrastre  (uoh)
Gracias por el codigo y por tu tiempo :)

Salu2...

P.D.: Si al final implmento el buffer mediante bytes en vez de variants que no te extrañe ver tu nick en los creditos del proyecto como agradecimiento ;)  
Título: Trabajar Con Bytes
Publicado por: sés en 23 de Octubre de 2004, 01:14:21 AM
 
Cita de: "[EX3"]Pues si te cuento yo como tengo las mias ultimamente, estoy pa'l arrastre  (uoh)
Las mías se están atrofiando de tanto Java :(

Cita de: "[EX3"]P.D.: Si al final implmento el buffer mediante bytes en vez de variants que no te extrañe ver tu nick en los creditos del proyecto como agradecimiento ;)
¿Mi nombre en algo relacionado con Visual Basic? Nunca lo imaginé... O_O
Título: Trabajar Con Bytes
Publicado por: [EX3] en 23 de Octubre de 2004, 02:54:54 AM
 
Cita de: "sés"Las mías se están atrofiando de tanto Java :(
Ja! las mias por culpa de la perreria y sencillez del BASIC, que no se que es peor  (uoh)

Salu2...
Título: Trabajar Con Bytes
Publicado por: sés en 23 de Octubre de 2004, 09:14:41 AM
Cita de: "[EX3"] Ja! las mias por culpa de la perreria y sencillez del BASIC, que no se que es peor  (uoh)
:ph34r: Pásate al lado oscuro... pásate a C