Título: enteros de 12 bits Publicado por: integeroverflow en 2 Marzo 2017, 08:05 am hola que tal. a ver si me pueden dar una mano con esto...
resulta que estoy programando una especie de driver para sistemas de archivos FAT12, basicamente es un programa en C al que le pasamos como parametro la imagen de un floppy y este se encarga de leer y escribir datos en el utilizando el formato FAT12. como sabran, este formato cuenta con 2 FATS (File Allocation Table) donde se guarda la informacion de todos los clusters presentes en el disco, vendria a ser un array de digitos de 12 bits que puede representar los siguientes valores: cluster sin uso - cluster da;ado - siguiente cluster del archivo - ultimo cluster del archivo. para leer la FAT lo que hago es calcular el inicio de esta y ir leyendo de a pedazos de 3 bytes (24 bits, 2 entradas de 12 bits). la idea ahroa es partir esos 3 bytes en 2 enteros de 12 bits que me van a dar la informacion de los 2 clusters que se guarda en esos 3 bytes. no hay ningun tipo de datos de 12 bit en C, asi que se me ocurrio usar dos enteros de 16 bits (uint16_t). lo que necesito hacer es: en el primer entero, copiar la segunda mitad del segundo byte + todo el contenido del primero. en el segundo entero, copiar todo el contenido del tercer byte + la segunda mitad del segundo. esto me daria como resultado las 2 entradas que necesito leer de la FAT. algo asi: // (pongo una letra al inicio cada 4 bits para poder apreciar bien lo que neceisto hacer a110 b011 // byte 0 c100 d100 // byte 1 e101 f101 // byte 2 esos 3 bytes son los que leo de la fat, ahora neceisto partirlos en 2 enteros de 16 bits, quedando: c100 a110 b011 0000 // primer entero d100 e101 f101 0000 // segundo entero la pregunta es, como puedo realizar esta operacion? es decir, que operaciones binarias debo realizar? Título: Re: enteros de 12 bits Publicado por: ivancea96 en 2 Marzo 2017, 08:51 am Los únicos operadores que necesitarás, en principio, son los de desplazamiento de bits (<<, >>) y and (&).
Suponiendo que tengas los 24 bits en un array de 3 chars: Código
Y el resto, más de lo mismo. Título: Re: enteros de 12 bits Publicado por: integeroverflow en 2 Marzo 2017, 12:43 pm Los únicos operadores que necesitarás, en principio, son los de desplazamiento de bits (<<, >>) y and (&). Suponiendo que tengas los 24 bits en un array de 3 chars: Código
Y el resto, más de lo mismo. que tal amigo, gracias por tu respuesta. a ver si me ayudas un poco a entender el codigo. suponiendo que: arr[0] = 0110 1010 arr[1] = 1100 0001 ((short)arr[0]) //casteando a short nos quedaria el byte dentro de 2 bytes, es asi? 0000 0000 0110 1010 // quedando este valor "<< 4" desplazaria los bits 4 veces hacia la izquierda, correcto? 0000 1010 0110 0000 // quedando este valor arr[1] >> 4 // desplazaria los bits 4 veces hacia la derecha, quedando este valor: 0000 1100 0000 0000 aplicando '|' entre los dos valores: 0000 0000 0110 1010 0000 1100 0000 0000 //resultado: 0000 1100 0110 1010 entendi bien? si no es asi, podrias explicarme paso a paso como funcionan estas operaciones? Título: Re: enteros de 12 bits Publicado por: ivancea96 en 2 Marzo 2017, 13:09 pm Am casi pero:
arr[1] >> 4 // desplazaria los bits 4 veces hacia la derecha, quedando este valor: 0000 1100 0000 0000 Eso no es así. 1100 0001, desplazando a la derecha, queda: 0000 1100 Con lo cual, 0000 1010 0110 0000 | 0000 1100 == 0000 1010 0110 1100 Título: Re: enteros de 12 bits Publicado por: integeroverflow en 2 Marzo 2017, 13:21 pm Am casi pero: arr[1] >> 4 // desplazaria los bits 4 veces hacia la derecha, quedando este valor: 0000 1100 0000 0000 Eso no es así. 1100 0001, desplazando a la derecha, queda: 0000 1100 Con lo cual, 0000 1010 0110 0000 | 0000 1100 == 0000 1010 0110 1100 ya veo, gracias. para tratar de entender un poco mejor esto, si quiero partir un short en 2 bytes, seria correcto hacer esto? short a = X; // digamos que vale: 1101 1110 0101 1010 char b[2]; b[0] = (a >> 8); // quedaria 0000 0000 1101 1110 b[1] = (a << 8) >> 8; // primero quedaria: 0101 1010 0000 0000 // y despues se convierte a: 0000 0000 0101 1010 es correcto? gracias por tu ayuda Título: Re: enteros de 12 bits Publicado por: ivancea96 en 2 Marzo 2017, 14:45 pm Correcto.
Como detalle extra, en vez de (x << 8) >> 8, puedes hacer x & 0xFFFF. Título: Re: enteros de 12 bits Publicado por: integeroverflow en 2 Marzo 2017, 15:07 pm Correcto. Como detalle extra, en vez de (x << 8) >> 8, puedes hacer x & 0xFFFF. mmm, eso no me quedo muy claro. digamos que el short vale 1101 1001 1100 1000. si desplazo 8 hacia la derecha, obtengo el primer byte: 0000 0000 1100 1000 para obtener el segundo, vos decis que haga and con 0xFFFF, que en binario sera 1111 1111 1111 1111, resultando: 1101 1001 1100 1000 1111 1111 1111 1111 =1101 1001 1100 1000 es decir, el mismo numero. no habras querido decir 0xFF? en ese caso, 0xFF valdria 0000 0000 1111 1111 y el resultado del and seria 1101 1001 1100 1000 0000 0000 1111 1111 = 0000 0000 1100 1000 dando el ultimo byte. o quizas me equivoco. gracias por tu ayuda, ya voy entendiendo como se opera con bits. Título: Re: enteros de 12 bits Publicado por: ivancea96 en 2 Marzo 2017, 15:49 pm Oh sí, me confundí. 0xFF.
Título: Re: enteros de 12 bits Publicado por: Borito30 en 3 Marzo 2017, 16:33 pm que tal amigo, gracias por tu respuesta. a ver si me ayudas un poco a entender el codigo. suponiendo que: arr[0] = 0110 1010 arr[1] = 1100 0001 ((short)arr[0]) //casteando a short nos quedaria el byte dentro de 2 bytes, es asi? 0000 0000 0110 1010 // quedando este valor "<< 4" desplazaria los bits 4 veces hacia la izquierda, correcto? 0000 1010 0110 0000 // quedando este valor arr[1] >> 4 // desplazaria los bits 4 veces hacia la derecha, quedando este valor: 0000 1100 0000 0000 aplicando '|' entre los dos valores: 0000 0000 0110 1010 0000 1100 0000 0000 //resultado: 0000 1100 0110 1010 entendi bien? si no es asi, podrias explicarme paso a paso como funcionan estas operaciones? Hola no entiendo esto. A ver tu tienes un array ejemplo: int arr [2]; Y le asignas dos valores: arr[0] = 0110 1010 arr[1] = 1100 0001 Código: ((short)arr[0]) //casteando a short nos quedaria el byte dentro de 2 bytes, es asi? Eso quiere decir que tu cadena se alarga en 16 bits. Pero porqué este valor? Código: 0000 0000 0110 1010 // quedando este valor Aqui dices esto: Código: "<< 4" desplazaria los bits 4 veces hacia la izquierda, correcto? Pero lo correcto seria¿Porque este número de donde lo sacaron?: Código: 0000 1100 0000 0000 Lo usastes en la posicion 1¿? Código: arr[1] >> 4 Y porque devuelve este valor?: Código: 0000 1100 0000 0000 Aplicando esto: Código: 0000 0000 0110 1010 | 0000 1100 0000 0000 Cuanto devolvería y porque? A vale es una division ok. En cuanto esto sería una simple suma es correcto? 1101 1001 1100 1000 0000 0000 1111 1111 = 0000 0000 1100 1000 Hace tiempo que no repasaba las operaciones en binario tendré que repasarlas si me podeis aclarar alguno de estos puntos me seria util gracias. Por otro lado porque 0xFF valdria 0000 0000 1111 1111 ? Título: Re: enteros de 12 bits Publicado por: ivancea96 en 3 Marzo 2017, 17:00 pm Oh, un detalle más. El array, en vez de char, debería ser de unsigned char (sinó, si el valor coincide negativo, la transformación a short será negativa y no serviría.
Bueno, estaba revisando el tema, y la colocación de los bits puede que la haya interpretado al revés. Puedes testear con: Código
Si arr[0] = AB y arr[1] = CD, la salida es ABC. No es lo que pusiste tú al principio, pero bueno, el cambio es mínimo. Perdona la confusión :p Citar Por otro lado porque Am no sé cómo responder a esto. Es así. Hexadecimal a binario.0xFF valdria 0000 0000 1111 1111 ? Título: Re: enteros de 12 bits Publicado por: integeroverflow en 4 Marzo 2017, 14:19 pm Hola no entiendo esto. en realidad no estamos hablando de una cadena, si no de numeros enteros. lo que sucede al castear es que el compilador va a tratar ese numero como si fuesen 2 bytes. no se alarga en 16 bits, si no que en 8.A ver tu tienes un array ejemplo: int arr [2]; Y le asignas dos valores: arr[0] = 0110 1010 arr[1] = 1100 0001 Código: ((short)arr[0]) //casteando a short nos quedaria el byte dentro de 2 bytes, es asi? Eso quiere decir que tu cadena se alarga en 16 bits. es como el siguiente ejemplo en decimal (es ilustrativo, nada que ver con programacion): 15 // el 15 expresado en un supuesto tipo de datos de 2 digitos 0015 // el 15 expresado en un supuesto tipo de datos de 4 digitos. mismo numero, mayor cantidad de digitos disponibles Citar Pero porqué este valor? queda ese valor porque los tipos de datos que yo manejo al principio son CHAR, o sea, 1 byte (8 bits). al castearlo a short (2 bytes, 16 bits), me queda un numero de 16 digitos, como el valor es el mismo que antes los 8 nuevos digitos quedan en 0Código: 0000 0000 0110 1010 // quedando este valor Citar Aqui dices esto: si tengo este numero: 0000 0000 1010 0110, y muevo 4 posiciones a la izq, queda 0000 1010 0110 0000, el numero que pusiste ahi le estan faltando 4 bits, 0110Código: "<< 4" desplazaria los bits 4 veces hacia la izquierda, correcto? Pero lo correcto seria¿Porque este número de donde lo sacaron?: Código: 0000 1100 0000 0000 Citar Lo usastes en la posicion 1¿? esto no es una division, es el operador OR. lo que hace, si miramos la tabla:Código: arr[1] >> 4 Y porque devuelve este valor?: Código: 0000 1100 0000 0000 Aplicando esto: Código: 0000 0000 0110 1010 | 0000 1100 0000 0000 INPUT OUTPUT A B A OR B 0 0 0 0 1 1 1 0 1 1 1 1 devuelve 1 si alguno de los 2 digitos es 1, caso contrario devuelve 0. entonces se puede usar para copiar un conjunto de bits. ejemplo: 1101 0001 =1101 (uno y cero da 1, 0 y 0 da 0, 1 y 1 da 1) Citar Cuanto devolvería y porque? A vale es una division ok. En cuanto esto sería una simple suma es correcto? 1101 1001 1100 1000 0000 0000 1111 1111 = 0000 0000 1100 1000 Hace tiempo que no repasaba las operaciones en binario tendré que repasarlas si me podeis aclarar alguno de estos puntos me seria util gracias. Por otro lado porque 0xFF valdria 0000 0000 1111 1111 ? 0xFF tiene ese valor porque la F en hexadecimal vale 15. si hacemos la cuenta: Código: 0 = 0 entonces teniendo 0xFF nos quedaria el siguiente valor 1111 1111 el grupo del ceros al principio es porque estamos hablando de un short, o sea 2 bytes o 16 bits. quedando: 0000 0000 1111 1111. espero se haya entendido. Título: Re: enteros de 12 bits Publicado por: integeroverflow en 4 Marzo 2017, 14:30 pm Código
dejo mi codigo a ver si me podes ayudar. si te fijas arriba del todo, hay una lista de enteros de 12 bits. abajo su valor en decimal. luego tenemos un array de bytes que contiene estos enteros de 12 bits en enteros de 8 bits. es decir, cada elemento par del array contiene 2 tercios del entero que representa, y cada elemento impar contiene 1 tercio del entero representado por el elemento anterior y 1 tercio del entero que representa el elemento siguiente. para verlo con mas claridad: Citar unsigned char a[9] = { 0b00011100, 0b10010001, 0b11001010, 0b00011100, 0b10110001, 0b11001100, 0b00011100, 0b11010001, 0b11001110 }; en el codigo lo que hago es ir elemento por elemento y chequear si es par o impar. si es par, shifteo a la izquierda 4 bits y tomo los primeros 4 bits del elemento siguiente. si es impar, elimino los primeros 4 bits, shifteo a la izquierda 8 bits, y copio el contenido del elemento siguiente. ese codigo funciona bien, lo pruebo y me devuelve el valor decimal que tiene que devolver. sin embargo, falla en algunos elementos. que puede estar causando el problema? output: Código: 457 Título: Re: enteros de 12 bits Publicado por: ivancea96 en 4 Marzo 2017, 21:45 pm No depende de si el byte es par o impar. Depende del resto de dividir entre 3:
Código
Título: Re: enteros de 12 bits Publicado por: integeroverflow en 4 Marzo 2017, 22:59 pm No depende de si el byte es par o impar. Depende del resto de dividir entre 3: Código
ahora si, funciona perfecto. pero no me quedo claro, que tiene que ver el resto de la division con 3? me podrias explicar asi logro entenderlo? te agradezco Título: Re: enteros de 12 bits Publicado por: ivancea96 en 5 Marzo 2017, 00:13 am Citar unsigned char a[9] = { 0b00011100, // 0 (entero 1) 0b10010001, // 1 (entero 2) 0b11001010, // 2 (nada) 0b00011100, // 0 (entero 1) 0b10110001, // 1 (entero 2) 0b11001100, // 2 (nada) 0b00011100, // 0 (entero 1) 0b11010001, // 1 (entero 2) 0b11001110 // 2 (nada) }; Tienes 2 enteros cada 3 bytes. En el primer bytes, obtienes el primer entero (accediendo, además, al siguiente byte) En el segundo byte, obtienes el segundo entero (accediendo también al siguiente byte) El tercer byte es, en su totalidad, parte del anterior entero. Aquí no hay anda que hacer Y repites. 3 bytes, 2 acciones. Título: Re: enteros de 12 bits Publicado por: integeroverflow en 5 Marzo 2017, 09:40 am Tienes 2 enteros cada 3 bytes. En el primer bytes, obtienes el primer entero (accediendo, además, al siguiente byte) En el segundo byte, obtienes el segundo entero (accediendo también al siguiente byte) El tercer byte es, en su totalidad, parte del anterior entero. Aquí no hay anda que hacer Y repites. 3 bytes, 2 acciones. ahora si, lo entiendo perfectamente. esto sucedia si chequeaba par o impar: 1111 1111 // byte 0 = 1111 1111 1001 1001 0110 // byte 1 = 0110 1011 1011 1011 1011 // byte 2 = 1100 0011 ahora cada 3 bytes el byte es salteado. muchas gracias por tu ayuda amigo !!! Título: Re: enteros de 12 bits Publicado por: MAFUS en 5 Marzo 2017, 12:41 pm A ver, he encontrado esto: http://www.disc.ua.es/~gil/FAT12Description.pdf
Según el paper los 12 bits se consiguen de esta forma: Suponiendo que 3 bytes consecutivos tienen la siguiente información (supongamos también que cada bit del byte puede alojar un número decimal):
Bien, pues el primer número de 12 bits sería el 109876543210 y el segundo número de 12 bits sería el 321098765432 Esto es así porque la FAT se hizo para máquinas IBM, y esas son little-endian, lo que quiere decir que el LSB se encuentra en la parte baja de la memoria. Traducido: Para formar la representación de los 12 bits del primer número debes tomar · Del 2º byte los 4 bits menos significativos : 1098 · Del 1er byte todos los bits : 76543210 Para formar la representación de los 12 bits del segundo número debes tomar · Del 3er byte todos los bits : 321098765432 · Del 2º byte los 4 bits más significativos Título: Re: enteros de 12 bits Publicado por: integeroverflow en 5 Marzo 2017, 20:12 pm A ver, he encontrado esto: http://www.disc.ua.es/~gil/FAT12Description.pdf Según el paper los 12 bits se consiguen de esta forma: Suponiendo que 3 bytes consecutivos tienen la siguiente información (supongamos también que cada bit del byte puede alojar un número decimal):
Bien, pues el primer número de 12 bits sería el 109876543210 y el segundo número de 12 bits sería el 321098765432 Esto es así porque la FAT se hizo para máquinas IBM, y esas son little-endian, lo que quiere decir que el LSB se encuentra en la parte baja de la memoria. Traducido: Para formar la representación de los 12 bits del primer número debes tomar · Del 2º byte los 4 bits menos significativos : 1098 · Del 1er byte todos los bits : 76543210 Para formar la representación de los 12 bits del segundo número debes tomar · Del 3er byte todos los bits : 321098765432 · Del 2º byte los 4 bits más significativos que tal hermano gracias por tu respuesta. ya habia visto ese PDF, la informacion sobre el formato FAT12 ya la tenia, mi duda era sobre las operaciones binarias en c lo cual ya lo solucione. claro que la operacion que yo hago en el codigo que publique recientemente parte el segundo byte al reves, es decir: XXXX XXXX XXXX XXXX XXXX XXXX pero ahora que tengo en claro como hacer operaciones con bits, solo queda modificar el codigo para leerlo de la manera correcta y arreglar mi funcion que lee la FAT. o sea XXXX XXXX |