# Endianness e IEEE 754: il bug che ti fa rileggere il datasheet

> Leggi un registro float a 32 bit su Modbus e ottieni numeri assurdi: endianness big vs little, word swap, IEEE 754 e complemento a due. Decodificare i byte.

Pubblicato: 2026-06-24
Categoria: software
Tag: endianness, ieee-754, floating-point, two-complement, modbus, byte-order, debugging

Pagina: <https://www.stline.it/blog/endianness-ieee754-byte/>

---

Quando si integra strumentazione di terzi, una delle cause di errore più insidiose sta nell’ordine dei byte, non nell’algoritmo che li elabora. Lo strumento dichiara di esporre una grandezza fisica come float a 32 bit su un registro; noi la leggiamo e otteniamo `1.7e+38`, oppure `-0.0000000000000000003`, oppure un `NaN` pulito. Il valore vero era `23,7`. Nessuno dei due lati ha torto sul protocollo: ci siamo solo capiti male su *come* quei byte vanno rimontati.

## Il caso

Catena tipica: un misuratore espone una lettura su Modbus, due registri a 16 bit consecutivi che insieme formano un float a 32 bit. Il nostro lato legge i registri, li concatena, li interpreta come `float` e stampa un numero che non ha senso fisico. Prima reazione, sbagliata, è dubitare del proprio codice di parsing dell'algoritmo. La reazione giusta è scendere al livello del singolo byte e chiedersi due cose distinte: **in che ordine arrivano i byte**, e **come quei byte codificano un numero**. Sono due problemi indipendenti, e quando i valori letti sono implausibili conviene escludere l’ordine dei byte prima di mettere in dubbio la codifica.

## Endianness: lo stesso numero, byte in ordine diverso

Un intero o un float a 32 bit sono quattro byte. L'**endianness** è la convenzione su quale byte viene per primo in memoria o sul filo. **Big-endian** mette per primo il byte più significativo (MSB), nell'ordine in cui scriveremmo il numero a mano; **little-endian** mette per primo quello meno significativo (LSB). I quattro byte `41 BD 70 A4` interpretati big-endian valgono `23,68`; gli stessi byte letti little-endian, cioè `A4 70 BD 41`, sono un float completamente diverso e privo di senso.

Modbus complica le cose perché lavora a registri di 16 bit big-endian, ma non specifica l'ordine *fra* i due registri di un float a 32 bit. Così nascono in pratica fino a quattro varianti — `ABCD`, `CDAB`, `BADC`, `DCBA` — a seconda che il costruttore inverta i byte, le word, entrambi o nessuno dei due (il famigerato *word swap*). Il datasheet, se è fatto bene, dice quale; se è fatto male, lo scopri a mano. Per questo, davanti a numeri assurdi, la prima mossa è provare sistematicamente i quattro byte-order: se una delle permutazioni restituisce il valore atteso, il problema era l'endianness e non la decodifica.

## IEEE 754: come i byte diventano un numero

Una volta messi i byte nell'ordine giusto, resta il secondo problema: cosa significano. Un float a 32 bit segue lo standard **IEEE 754** a singola precisione, che divide i 32 bit in tre campi: **1 bit di segno**, **8 bit di esponente** (con bias 127), **23 bit di mantissa** (con un bit implicito a 1 davanti). Il valore è circa `(-1)^segno · 1,mantissa · 2^(esponente−127)`. Capire questa decomposizione è ciò che permette di distinguere un errore di endianness da un valore legittimamente piccolo o grande: se il campo esponente è tutto a 1 il valore è un infinito o un `NaN`. Su un dato che dovrebbe essere una grandezza fisica misurata è un segnale: le cause possibili sono l’ordine dei byte, un disallineamento del frame o un campo non valido dichiarato dallo strumento, e vanno escluse in quest’ordine perché la prima costa meno da verificare.

Sugli **interi** lo stesso genere di errore si presenta col segno. I valori negativi si codificano in **complemento a due**: si invertono tutti i bit e si somma 1. Leggere un registro a 16 bit come unsigned quando lo strumento lo intende signed fa apparire un `-3` come `65533` — di nuovo un numero "assurdo" che in realtà è solo interpretato con la convenzione sbagliata. E come per i float, su un valore multi-registro l'ordine dei byte va risolto *prima* di applicare il complemento a due.

## Il metodo, non l'aneddoto

La lezione che ci portiamo dietro non è "attenzione a Modbus". È un metodo: quando un valore numerico letto da un protocollo o da un registro è assurdo, si scende al byte grezzo e si separano i due livelli. Primo, l'ordine dei byte — big o little, con eventuale word swap. Secondo, la codifica — IEEE 754 per i float, complemento a due per gli interi con segno. Risolti nell'ordine giusto, il numero torna; e la risposta sta di regola nel datasheet, in una riga sull’ordine dei byte o sul formato del campo.

Per ispezionare a mano quattro byte qualsiasi nei diversi ordini e codifiche abbiamo messo online un [Data Format Inspector](/tools/data-format-inspector/); il dettaglio su endianness, IEEE 754 e complemento a due è nella [wiki dedicata](/wiki/data-format-inspector/).

Stai integrando strumentazione su Modbus, seriale o un protocollo binario custom e i numeri non tornano? [Parliamone](/contatti/).
