Go: package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

func getScanner(fp *os.File) *bufio.Scanner {
	scanner := bufio.NewScanner(fp)
	scanner.Split(bufio.ScanWords)
	scanner.Buffer(make([]byte, 1000005), 1000005)
	return scanner
}

func getNextString(scanner *bufio.Scanner) string {
	scanner.Scan()
	return scanner.Text()
}

func getNextInt(scanner *bufio.Scanner) int {
	i, _ := strconv.Atoi(getNextString(scanner))
	return i
}

func getNextInt64(scanner *bufio.Scanner) int64 {
	i, _ := strconv.ParseInt(getNextString(scanner), 10, 64)
	return i
}

func getNextUint64(scanner *bufio.Scanner) uint64 {
	i, _ := strconv.ParseUint(getNextString(scanner), 10, 64)
	return i
}

func getNextFloat64(scanner *bufio.Scanner) float64 {
	i, _ := strconv.ParseFloat(getNextString(scanner), 64)
	return i
}

func main() {
	fp := os.Stdin
	wfp := os.Stdout
	cnt := 0

	if os.Getenv("MASPY") == "ますピ" {
		fp, _ = os.Open(os.Getenv("BEET_THE_HARMONY_OF_PERFECT"))
		cnt = 0
	}
	if os.Getenv("MASPYPY") == "ますピッピ" {
		wfp, _ = os.Create(os.Getenv("NGTKANA_IS_GENIUS10"))
	}

	scanner := getScanner(fp)
	writer := bufio.NewWriter(wfp)
	for solve(scanner, writer) {

	}
	for i := 0; i < cnt; i++ {
		fmt.Fprintln(writer, "-----------------------------------")
		solve(scanner, writer)
	}
	writer.Flush()
}

func solve(scanner *bufio.Scanner, writer *bufio.Writer) bool {
	sol := solver{}
	sol.w = getNextInt(scanner)
	sol.h = getNextInt(scanner)
	if sol.w == 0 && sol.h == 0 {
		return false
	}
	sol.land = makeInts(sol.h, sol.w)
	for y := 0; y < sol.h; y++ {
		for x := 0; x < sol.w; x++ {
			sol.land[y][x] = getNextInt(scanner)
		}
	}
	ans := 0
	for y := 0; y < sol.h; y++ {
		for x := 0; x < sol.w; x++ {
			if sol.land[y][x] == 0 {
				continue
			}
			ans++
			sol.dfs(y, x)
		}
	}
	fmt.Fprintln(writer, ans)
	return true
}

type solver struct {
	w, h int
	land [][]int
}

func (sol *solver) dfs(y, x int) {
	if y < 0 {
		return
	}
	if y >= sol.h {
		return
	}
	if x < 0 {
		return
	}
	if x >= sol.w {
		return
	}
	if sol.land[y][x] == 0 {
		return
	}
	sol.land[y][x] = 0
	dy := [8]int{-1, -1, -1, 0, 0, 1, 1, 1}
	dx := [8]int{-1, 0, 1, -1, 1, -1, 0, 1}
	for i := 0; i < 8; i++ {
		sol.dfs(y+dy[i], x+dx[i])
	}
}
func makeInts(h, w int) [][]int {
	index := make([][]int, h, h)
	data := make([]int, h*w, h*w)
	for i := 0; i < h; i++ {
		index[i] = data[i*w : (i+1)*w]
	}
	return index
}

C++: #include <stdio.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <memory.h>
#include <functional>

using namespace std;

//FILE * in = freopen("B", "r", stdin);

typedef pair<int,int> P;

int n, m;
int cnt = 0;
int data[100][100];
int check[100][100];

int mvx[] = {-1, 0, 1, -1, 1, -1, 0, 1};
int mvy[] = {-1, -1, -1, 0, 0, 1, 1, 1};

void input() {
	for(int i = 0; i < m; i++){
		for(int j = 0; j < n; j++) {
			scanf("%d", &data[i][j]);
		}
	}
	cnt = 0;
	memset(check, 0, sizeof(check));
}

void bfs(int x, int y) {
	queue<P> que;
	que.push(P(x,y));
	check[x][y] = 1;
	while(!que.empty()){
		P cur = que.front(); que.pop();
		for(int i = 0; i < 8; i++) {
			if(cur.first + mvx[i] >= 0 && cur.first + mvx[i] < m && cur.second + mvy[i] >= 0 && cur.second + mvy[i] < n
				&& data[cur.first + mvx[i]][cur.second + mvy[i]] && !check[cur.first+mvx[i]][cur.second+mvy[i]]){
					check[cur.first +mvx[i]][cur.second+mvy[i]] = 1;
					que.push(P(cur.first+mvx[i], cur.second+mvy[i]));
			}
		}
	}
}

void process() {
	for(int i = 0; i < m; i++) {
		for(int j = 0; j < n; j++) {
			if(data[i][j] && !check[i][j]) {
				bfs(i,j);
				++cnt;
			}
		}
	}
	printf("%d\n", cnt);
}

int main() {
	while(true) {
		scanf("%d%d", &n, &m);
		if(n == 0) break;
		input();
		process();
	}
	return 0;
}

C++: //http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1160&lang=jp
//How Many Islands?
#include <bits/stdc++.h>
#if LOCAL
#include "dump.hpp"
#else
#define dump(...)
#endif
using namespace std;
using ll=long long;
#define FOR(i,a,b) for(ll i=(a);i<(b);++i)
#define REP(i,n) FOR(i,0,n)
template<class T>bool chmax(T &a, const T &b) {if (a<b) { a=b; return 1; } return 0;}
template<class T>bool chmin(T &a, const T &b) {if (b<a) { a=b; return 1; } return 0;}

//2重配列上でdfs
bool solve2(){
    ll w,h; cin>>w>>h;
    if(w==0&&h==0)return false;//終わり
    vector<vector<ll>> chw(h,vector<ll>(w));
    FOR(y,0,h){
        FOR(x,0,w){
            ll c; cin>>c;
            chw.at(y).at(x)=c;
        }
    }

    auto available_node = [&](ll x,ll y)->bool{
        if(x<0||x>=w)return false;
        if(y<0||y>=h)return false;
        return chw.at(y).at(x);
    };

    function<void(ll,ll)> dfs = [&](ll x,ll y){
        if(not available_node(x,y)) return;
        chw.at(y).at(x)=0;//訪問済、flag落す
        pair<ll,ll> ofstbl[] = {
            {0,1},{0,-1},{1,0},{-1,0},
            {1,1},{1,-1},{-1,1},{-1,-1},        
        };
        for(const auto&p:ofstbl){
            dfs(x+p.first,y+p.second);
        } 
    };
    ll ans=0;
    FOR(y,0,h){
        FOR(x,0,w){
            if(available_node(x,y)){
                ++ans;
                dfs(x,y);
            }
        }
    }
    cout<<ans<<endl;

    return true;
}
int main(){
    while(solve2()){
    }
    return 0;
}

//template graph使ってるけど冗長
template< typename T >
struct edge {
	int src, to;
	T cost;
	edge(int _to, T _cost) : src(-1), to(_to), cost(_cost) {}
	edge(int _src, int _to, T _cost) : src(_src), to(_to), cost(_cost) {}
	edge &operator=(const int &x) {
		to = x;
		return *this;
	}
	operator int() const { return to; }
};

template< typename T>
struct node {
	vector<edge<T>> edges;
    bool flag=false;;
};

template< typename T >
using Edges = vector< edge< T > >;
template< typename T >
using WeightedGraph = vector< node< T > >;
using UnWeightedGraph = vector< vector< int > >;
template< typename T >
using Matrix = vector< vector< T > >;

bool solve(){
    ll w,h; cin>>w>>h;
    if(w==0&&h==0)return false;//終わり
    vector<vector<ll>> chw(h,vector<ll>(w));
    ll node_num=0;
    FOR(y,0,h){
        FOR(x,0,w){
            ll c; cin>>c;
            if(c==1)++node_num;
            chw.at(y).at(x)=c;
        }
    }

    auto pos2id = [&](ll x,ll y)->ll{
        return y*w+x;
    };
    auto available_node = [&](ll x,ll y)->bool{
        if(x<0||x>=w)return false;
        if(y<0||y>=h)return false;
        return chw.at(y).at(x);
    };
    ll node_max=w*h;
    WeightedGraph<ll> graph(node_max);
    pair<ll,ll> ofstbl[] = {
        {0,1},{0,-1},{1,0},{-1,0},
        {1,1},{1,-1},{-1,1},{-1,-1},        
    };
    FOR(y,0,h){
        FOR(x,0,w){
            if (available_node(x,y)) {
                ll xy=pos2id(x,y);
                auto&& node=graph.at(xy);
                node.flag=true;
                for(const auto& o:ofstbl){
                    ll nx =x+o.first;
                    ll ny =y+o.second;
                    if(available_node(nx,ny)){
                        ll nxy=pos2id(nx,ny);
                        node.edges.emplace_back(nxy,1);
                    }
                }
            }
        }
    }

    function<void(ll)> dfs = [&](ll id){
        auto& node=graph.at(id);
        if (node.flag==false)return; //訪問済orない
        node.flag=false;
        for(const auto& e :graph.at(id).edges){
            dfs(e);
        }
    };

    ll ans=0;
    FOR(i,0,node_max){
        if(graph.at(i).flag){
            ++ans;
            dfs(i);
        }
    }
    cout<<ans<<endl;

    return true;
}

int main_() {
#if LOCAL&01
    //std::ifstream in("./test/sample-1.in");
    std::ifstream in("./input.txt");
    std::cin.rdbuf(in.rdbuf());
#else
    cin.tie(0);
    ios::sync_with_stdio(false);
#endif
    while(solve()){
    }
    return 0;
}