It depends a lot on how you define "covered". My suggestions:
An exon is covered when all bases have at least 1 read mapped to it. Or in other words, uncovered exons are those were there are 1 or more bases that have no reads mapped to them. In this case, use bedtools coverageBed -abam file.bam -b exons.bed
An exon is covered when the bases have, on average, N reads (I use 5 or more reads) or more mapped to them, where you can choose the threshold N yourself (opposed to bedtools coverageBed ...). Use picard-tools CalculateHsMetrics for this approach (you have to change your bed file a bit, but I'm sure you will manage to do that.
There is also the GATK DepthOfCoverage tool, which is what I use to get coverage data for exons with Exome-Seq projects now. I prefer its output over Picards metrics. You can set what you want reported by the tool, from there you can parse the tab delimited output based on whatever thresholds for coverage you want. I tend to look at the percentage of bases covered at at least 5x and 10x to identify regions of low coverage where I may have missed calling variants for instance. And obviously the zero coverage exons are easy to identify in the output.