Technology   • Technology •

< Technology

> Intro

> Polynomial

• Calculation

> Examples


— FCS (CRC): Calculation —

Calculation Loop

In the HDLC frame of the PPP, all data bytes are submitted to the FCS, except the frame start and end bytes (FE hex). The calculated FCS is inserted by the sender just prior the end of frame byte, low byte first, high byte last. The receiver includes the two FCS bytes in the HDLC frame received to the calculation. The final result must yield the «good value» of F0B8 (ef-zero-be-eight).

Initially, the table entry is undetermined. The calculation always starts with the «initial value» of FFFF. The sender submits the data bytes to the FCS prior to encapsulation. Consequently, the receiver must dump the escape byte (FD hex) and substract 20 hex from the encapsulated byte to regain the true data byte which is then submitted to the FCS calculation.

The calculation loop step by step

  1. Set «initial table value» to FFFF hex.
  2. Get a «data byte».
  3. Exclusive-OR «data byte» with low byte of «initial table value», this gives the «pointer» into the table.
  4. Read two-byte «table value» pointed to by «pointer» in step 3.
  5. Exclusive-OR low byte of «table value» with high byte of «initial table value».
  6. Store value formed by high byte of «table value» and low byte of result from the XOR in step 5 as new «initial table value».
  7. Go to step 2 and repeat for all data bytes.


  1. Form one's complement of final «initial table value».
  2. Store low byte of complemented «initial table value» at the end of all «data bytes», then store the high byte.


  1. Cycle twice longer through the loop to include both FCS bytes.
  2. Compare final result to the «good value» of F0B8.

The calculation loop in 80x86 assembler

Personally, I find a listing of an assembler fragment the most enlightning piece of documentation.

fcs:  mov  ds:si,DataBuf     ;start of data buffer
      mov  cx,BufLen         ;length of buffer
      mov  dx,0ffffh         ;initial table value
fcs1: xor  ax,ax             ;clear register
      mov  al,[si]           ;get data byte
      xor  al,dl             ;xor data byte with low byte of
                             ;initial table value
      shl  ax,1              ;pointer x 2 since table entries
                             ;are 2 bytes (16 bits)
      mov  bx,ax             ;save pointer into table
      mov  ax,[DataBuf + bx] ;read table value (word)
      xor  al,dh             ;xor low byte of table entry with
                             ;high byte of initial table value
      mov  dx,ax             ;store result as new initial table
      inc  si                ;point to next byte in DataBuf
      dec  cx                ;decrement length counter
      jnz  fcs1              ;repeat until all bytes done (cx=0)
xmtr: xor  dx,0ffffh         ;one's complement
      mov  [si],dl           ;store low byte of result after last
                             ;data byte
      inc  si                ;point to next byte in DataBuf
      mov [si],dh            ;store high byte of result
rcvr: mov  ax,0f0b8h         ;load good value into register
      cmp  ax,dx             ;compare against FCS
      jnz  error             ;if no match, error handling

The calculation loop graphically

Here is a uncommon representation of the FCS or any CRC calculation loop. The numbers do not follow those of «The calculation loop step by step» above. The eliptical boxes represent the processor registers of the 80x86, the rectangular box the table.

graphical representation

In the rather uncommon depiction of the process above, follow the numbers either for the transmit (Tx) or the receive side (Rx).

  © 2004 - 2018 by Horo Wernli.