docs: def differing_constants(block_a, block_b):
      """
      Compares two basic blocks and finds all the constants that differ from the first block to the second.
  
      :param block_a: The first block to compare.
      :param block_b: The second block to compare.
      :returns:       Returns a list of differing constants in the form of ConstantChange, which has the offset in the
                      block and the respective constants.
      """
      statements_a = [s for s in block_a.vex.statements if s.tag != "Ist_IMark"] + [block_a.vex.next]
      statements_b = [s for s in block_b.vex.statements if s.tag != "Ist_IMark"] + [block_b.vex.next]
      if len(statements_a) != len(statements_b):
          raise UnmatchedStatementsException("Blocks have different numbers of statements")
  
      start_1 = min(block_a.instruction_addrs)
      start_2 = min(block_b.instruction_addrs)
  
      changes = []
  
      # check statements
      current_offset = None
      for statement, statement_2 in zip(statements_a, statements_b):
          # sanity check
          if statement.tag != statement_2.tag:
              raise UnmatchedStatementsException("Statement tag has changed")
  
          if statement.tag == "Ist_IMark":
              if statement.addr - start_1 != statement_2.addr - start_2:
                  raise UnmatchedStatementsException("Instruction length has changed")
              current_offset = statement.addr - start_1
              continue
  
          differences = compare_statement_dict(statement, statement_2)
          for d in differences:
              if d.type != DIFF_VALUE:
                  raise UnmatchedStatementsException("Instruction has changed")
              else:
                  changes.append(ConstantChange(current_offset, d.value_a, d.value_b))
  
      return changes