fn main() {
    let (n, m): (usize, usize) = readln();
    let a = min(n, m);
    let b = max(n, m);
    if a == 1 {
        if b == 1 {
            println!("{}", 1);
        } else {
            println!("{}", b - 2);
        }
    } else {
        let ans = n * m - (2 * n + 2 * m - 4);
        println!("{}", ans);
    }
}

#[allow(unused_imports)]
use std::cmp::{max, min};
#[allow(unused_imports)]
use std::collections::{HashMap, HashSet, VecDeque};

pub trait FromLn {
    fn fromln(s: &str) -> Self;
}
pub fn readln<T: FromLn>() -> T {
    let mut buf = String::new();
    let _ = ::std::io::stdin().read_line(&mut buf).unwrap();
    T::fromln(buf.trim())
}
pub fn readlns<T: FromLn>(n: usize) -> Vec<T> {
    let mut vs = vec![];
    for _ in 0..n {
        vs.push(readln());
    }
    vs
}
macro_rules! fromln_primitives {
    ($($t:ty),*) => { $(
        impl FromLn for $t {
            fn fromln(s: &str) -> $t {
                s.parse().unwrap()
            }
        }
    )* }
}
fromln_primitives!(
    String,
    bool,
    f32,
    f64,
    isize,
    i8,
    i16,
    i32,
    i64,
    usize,
    u8,
    u16,
    u32,
    u64
);
impl<T> FromLn for Vec<T>
where
    T: FromLn,
{
    fn fromln(s: &str) -> Vec<T> {
        s.split_whitespace().map(T::fromln).collect()
    }
}
impl FromLn for Vec<char> {
    fn fromln(s: &str) -> Vec<char> {
        s.chars().collect()
    }
}
macro_rules! fromln_tuple {
    ($($t:ident),*) => {
        impl<$($t),*> FromLn for ($($t),*) where $($t: FromLn),* {
            fn fromln(s: &str) -> ($($t),*) {
                let mut it = s.split_whitespace();
                let t = ($($t::fromln(it.next().unwrap())),*);
                assert_eq!(it.next(), None);
                t
            }
        }
    }
}
fromln_tuple!(A, B);
fromln_tuple!(A, B, C);
fromln_tuple!(A, B, C, D);
fromln_tuple!(A, B, C, D, E);
fromln_tuple!(A, B, C, D, E, F);
mod comp {
    pub mod math {
        pub mod comb {
            use super::mint::{Mint, MOD};
            pub struct Comb {
                fact: Vec<Mint>,
                factinv: Vec<Mint>,
            }
            impl Comb {}
            #[cfg(test)]
            mod tests {
                use super::*;
                #[test]
                fn test_simple() {
                    let c = Comb::new(100);
                    assert_eq!(Mint::from(336), c.perm(8, 3));
                    assert_eq!(Mint::from(56), c.comb(8, 3));
                    assert_eq!(Mint::from(10), c.multi_comb(3, 3));
                }
                #[test]
                fn test_fact() {
                    let c = Comb::new(100);
                    let p = 8721234;
                    let mut f = Mint::from(1);
                    for i in 1..(p + 1) {
                        f *= i;
                    }
                    assert_eq!(f, c.fact(p));
                }
            }
        }
        pub mod mint {
            use std;
            pub const MOD: u32 = 1000000007;
            #[derive(Debug, Copy, Clone, Eq)]
            pub struct Mint {
                val: u32,
            }
            impl<T: Into<Mint>> std::ops::Add<T> for Mint {
                type Output = Mint;
                fn add(self, other: T) -> Mint {
                    let nval = self.val + other.into().val;
                    Mint {
                        val: if nval >= MOD { nval - MOD } else { nval },
                    }
                }
            }
            impl<T: Into<Mint>> std::ops::Sub<T> for Mint {
                type Output = Mint;
                fn sub(self, other: T) -> Mint {
                    let nval = self.val + MOD - other.into().val;
                    Mint {
                        val: if nval >= MOD { nval - MOD } else { nval },
                    }
                }
            }
            impl<T: Into<Mint>> std::ops::Mul<T> for Mint {
                type Output = Mint;
                fn mul(self, other: T) -> Mint {
                    let nval = self.val as u64 * other.into().val as u64;
                    Mint {
                        val: (nval % (MOD as u64)) as u32,
                    }
                }
            }
            impl<T: Into<Mint>> std::ops::Div<T> for Mint {
                type Output = Mint;
                fn div(self, other: T) -> Mint {
                    self * other.into().inv()
                }
            }
            impl Mint {
                pub fn inv(self) -> Mint {
                    let mut a = self.val as i32;
                    let mut b = MOD as i32;
                    let mut u = 1 as i32;
                    let mut v = 0 as i32;
                    while b != 0 {
                        let t = a / b;
                        a -= t * b;
                        std::mem::swap(&mut a, &mut b);
                        u -= t * v;
                        std::mem::swap(&mut u, &mut v);
                    }
                    Mint {
                        val: if u < 0 { u + MOD as i32 } else { u } as u32,
                    }
                }
            }
            impl PartialEq for Mint {
                fn eq(&self, other: &Mint) -> bool {
                    self.val == other.val
                }
            }
            impl std::fmt::Display for Mint {
                fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                    self.val.fmt(f)
                }
            }
            macro_rules! impl_signed_mint(( $ ( $ t : ty ) * ) => (
                                      $ (
                                      impl From < $ t > for Mint {
                                      # [ inline ] fn from ( x : $ t ) -> Mint
                                      {
                                      let t = ( x as i64 ) % ( MOD as i64 ) ;
                                      if x >= 0 { Mint { val : t as u32 } }
                                      else {
                                      Mint { val : ( MOD as i64 + t ) as u32 }
                                      } } } ) * ));
            macro_rules! impl_unsigned_mint(( $ ( $ t : ty ) * ) => (
                                        $ (
                                        impl From < $ t > for Mint {
                                        # [ inline ] fn from ( x : $ t ) ->
                                        Mint {
                                        let t = x as u64 % MOD as u64 ; Mint {
                                        val : t as u32 } } } ) * ));
            impl_signed_mint! (i8 i16 i32 i64 isize);
            impl_unsigned_mint! (u8 u16 u32 u64 usize);
            impl<T: Into<Mint>> std::ops::AddAssign<T> for Mint {
                fn add_assign(&mut self, other: T) {
                    *self = *self + other.into();
                }
            }
            impl<T: Into<Mint>> std::ops::SubAssign<T> for Mint {
                fn sub_assign(&mut self, other: T) {
                    *self = *self - other.into();
                }
            }
            impl<T: Into<Mint>> std::ops::MulAssign<T> for Mint {
                fn mul_assign(&mut self, other: T) {
                    *self = *self * other.into();
                }
            }
            impl<T: Into<Mint>> std::ops::DivAssign<T> for Mint {
                fn div_assign(&mut self, other: T) {
                    *self = *self / other.into();
                }
            }
            #[cfg(test)]
            mod tests {
                use super::*;
                #[test]
                fn test_simple() {
                    let a: Mint = Mint::from(3);
                    let b: Mint = Mint::from(1000000000);
                    assert_eq!(Mint::from(3000000000u64 % MOD as u64), a * b);
                }
            }
        }
        pub mod prime {
            #[derive(Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Debug)]
            struct U128 {
                hi: u64,
                lo: u64,
            }
        }
    }
    pub mod data_structure {
        pub mod bit {
            pub struct BIT {
                tree: Vec<i64>,
            }
            pub struct BITRange {
                bit0: BIT,
                bit1: BIT,
            }
            impl BIT {}
            impl BITRange {}
            #[cfg(test)]
            mod tests {
                use super::*;
                #[test]
                fn test_simple() {
                    let mut bit = BIT::new(10);
                    bit.add(2, 1);
                    bit.add(3, 3);
                    bit.add(5, 10);
                    bit.add(0, -4);
                    bit.add(9, -5);
                    assert_eq!(5, bit.get(0, 10));
                    assert_eq!(4, bit.get(2, 4));
                    assert_eq!(1, bit.get(2, 3));
                    assert_eq!(0, bit.get(2, 2));
                    assert_eq!(0, bit.get(2, 0));
                    assert_eq!(-4, bit.get(0, 1));
                    assert_eq!(5, bit.get(5, 10));
                    let mut bit = BITRange::new(10);
                    bit.add(1, 3, 1);
                    bit.add(2, 5, 2);
                    assert_eq!(1, bit.get(1, 2));
                    assert_eq!(4, bit.get(1, 3));
                    assert_eq!(6, bit.get(1, 4));
                    assert_eq!(6, bit.get(0, 4));
                }
            }
        }
        pub mod union_find {
            pub struct UnionFind {
                data: Vec<i32>,
            }
            impl UnionFind {}
            #[cfg(test)]
            mod tests {
                use super::*;
                #[test]
                fn test_simple() {
                    let mut uf = UnionFind::new(3);
                    assert_eq!(1, uf.size(0));
                    assert_eq!(1, uf.size(1));
                    assert_eq!(1, uf.size(2));
                    assert_eq!(0, uf.root(0));
                    assert_eq!(1, uf.root(1));
                    assert_eq!(2, uf.root(2));
                    assert!(!uf.same(1, 2));
                    uf.unite(1, 2);
                    assert_ne!(uf.root(0), uf.root(2));
                    assert_eq!(uf.root(1), uf.root(2));
                    assert_eq!(1, uf.size(0));
                    assert_eq!(2, uf.size(1));
                    assert_eq!(2, uf.size(2));
                    assert!(uf.same(1, 2));
                    uf.unite(0, 1);
                    assert_eq!(uf.root(0), uf.root(2));
                    assert_eq!(uf.root(1), uf.root(2));
                    assert_eq!(3, uf.size(0));
                    assert_eq!(3, uf.size(1));
                    assert_eq!(3, uf.size(2));
                    assert!(uf.same(1, 2));
                    assert!(uf.same(0, 2));
                }
            }
        }
    }
    pub mod util {
        pub mod permutation {
            pub trait Permutation {
                fn next_permutation(&mut self) -> bool;
                fn prev_permutation(&mut self) -> bool;
            }
            impl<T> Permutation for [T]
            where
                T: Ord,
            {
                fn next_permutation(&mut self) -> bool {
                    if self.len() <= 1 {
                        return false;
                    }
                    let mut i = self.len() - 1;
                    while i > 0 && self[i - 1] >= self[i] {
                        i -= 1;
                    }
                    if i == 0 {
                        return false;
                    }
                    let mut j = self.len() - 1;
                    while self[j] <= self[i - 1] {
                        j -= 1;
                    }
                    self.swap(j, i - 1);
                    self[i..].reverse();
                    true
                }
                fn prev_permutation(&mut self) -> bool {
                    if self.len() <= 1 {
                        return false;
                    }
                    let mut i = self.len() - 1;
                    while i > 0 && self[i - 1] <= self[i] {
                        i -= 1;
                    }
                    if i == 0 {
                        return false;
                    }
                    self[i..].reverse();
                    let mut j = self.len() - 1;
                    while self[j - 1] < self[i - 1] {
                        j -= 1;
                    }
                    self.swap(i - 1, j);
                    true
                }
            }
            #[cfg(test)]
            mod tests {
                use super::*;
                #[test]
                fn test_simple() {
                    let mut data = [0, 0, 1, 1, 2];
                    data.next_permutation();
                    assert_eq!(&data, &[0, 0, 1, 2, 1]);
                    data.next_permutation();
                    assert_eq!(&data, &[0, 0, 2, 1, 1]);
                    data.next_permutation();
                    assert_eq!(&data, &[0, 1, 0, 1, 2]);
                    data.next_permutation();
                    assert_eq!(&data, &[0, 1, 0, 2, 1]);
                    data.next_permutation();
                    assert_eq!(&data, &[0, 1, 1, 0, 2]);
                    data.prev_permutation();
                    assert_eq!(&data, &[0, 1, 0, 2, 1]);
                    data.prev_permutation();
                    assert_eq!(&data, &[0, 1, 0, 1, 2]);
                    data.prev_permutation();
                    assert_eq!(&data, &[0, 0, 2, 1, 1]);
                    data.prev_permutation();
                    assert_eq!(&data, &[0, 0, 1, 2, 1]);
                    data.prev_permutation();
                    assert_eq!(&data, &[0, 0, 1, 1, 2]);
                    assert!(!data.prev_permutation());
                }
            }
        }
        pub mod rand {
            use std::{marker, mem};
            use std::io::{self, Read};
            use std::fs::File;
            use std::char;
            #[derive(Debug, Clone, Copy)]
            pub struct Xoroshiro128Rng {
                state: [u64; 2],
            }
            impl Xoroshiro128Rng {}
            impl Rng for Xoroshiro128Rng {
                fn next_u32(&mut self) -> u32 {
                    self.next_u64() as u32
                }
                fn next_u64(&mut self) -> u64 {
                    let s0: u64 = self.state[0];
                    let mut s1: u64 = self.state[1];
                    let result: u64 = s0.wrapping_add(s1);
                    s1 ^= s0;
                    self.state[0] = s0.rotate_left(55) ^ s1 ^ (s1 << 14);
                    self.state[1] = s1.rotate_left(36);
                    result
                }
            }
            pub trait Rand: Sized {
                fn rand<R: Rng>(rng: &mut R) -> Self;
            }
            pub trait Rng {
                fn next_u32(&mut self) -> u32;
                fn next_u64(&mut self) -> u64 {
                    let x = self.next_u32() as u64;
                    let y = self.next_u32() as u64;
                    (y << 32) | x
                }
                fn next_f32(&mut self) -> f32 {
                    const UPPER_MASK: u32 = 1065353216;
                    const LOWER_MASK: u32 = 8388607;
                    let tmp = UPPER_MASK | (self.next_u32() & LOWER_MASK);
                    let result: f32 = unsafe { mem::transmute(tmp) };
                    result - 1.0
                }
                fn next_f64(&mut self) -> f64 {
                    const UPPER_MASK: u64 = 4607182418800017408;
                    const LOWER_MASK: u64 = 4503599627370495;
                    let tmp = UPPER_MASK | (self.next_u64() & LOWER_MASK);
                    let result: f64 = unsafe { mem::transmute(tmp) };
                    result - 1.0
                }
                #[inline(always)]
                fn gen<T: Rand>(&mut self) -> T
                where
                    Self: Sized,
                {
                    Rand::rand(self)
                }
                fn gen_iter<'a, T: Rand>(&'a mut self) -> Generator<'a, T, Self>
                where
                    Self: Sized,
                {
                    Generator {
                        rng: self,
                        _marker: marker::PhantomData,
                    }
                }
                fn shuffle<T>(&mut self, values: &mut [T])
                where
                    Self: Sized,
                {
                    let mut i = values.len();
                    while i >= 2 {
                        i -= 1;
                        values.swap(i, (self.next_u64() as usize) % i);
                    }
                }
            }
            #[derive(Debug)]
            pub struct Generator<'a, T, R: 'a> {
                rng: &'a mut R,
                _marker: marker::PhantomData<fn() -> T>,
            }
            impl<'a, T: Rand, R: Rng> Iterator for Generator<'a, T, R> {
                type Item = T;
                fn next(&mut self) -> Option<T> {
                    Some(self.rng.gen())
                }
            }
            pub struct OsRng {
                reader: File,
            }
            impl OsRng {}
            impl Rng for OsRng {
                fn next_u32(&mut self) -> u32 {
                    let mut dest = [0u8; 4];
                    self.reader.read_exact(&mut dest).unwrap();
                    unsafe { mem::transmute::<[u8; 4], u32>(dest) }
                }
            }
            impl Rand for isize {
                #[inline]
                fn rand<R: Rng>(rng: &mut R) -> isize {
                    if mem::size_of::<isize>() == 4 {
                        rng.gen::<i32>() as isize
                    } else {
                        rng.gen::<i64>() as isize
                    }
                }
            }
            impl Rand for i8 {
                #[inline]
                fn rand<R: Rng>(rng: &mut R) -> i8 {
                    rng.next_u32() as i8
                }
            }
            impl Rand for i16 {
                #[inline]
                fn rand<R: Rng>(rng: &mut R) -> i16 {
                    rng.next_u32() as i16
                }
            }
            impl Rand for i32 {
                #[inline]
                fn rand<R: Rng>(rng: &mut R) -> i32 {
                    rng.next_u32() as i32
                }
            }
            impl Rand for i64 {
                #[inline]
                fn rand<R: Rng>(rng: &mut R) -> i64 {
                    rng.next_u64() as i64
                }
            }
            #[cfg(feature = "i128_support")]
            impl Rand for i128 {
                #[inline]
                fn rand<R: Rng>(rng: &mut R) -> i128 {
                    rng.gen::<u128>() as i128
                }
            }
            impl Rand for usize {
                #[inline]
                fn rand<R: Rng>(rng: &mut R) -> usize {
                    if mem::size_of::<usize>() == 4 {
                        rng.gen::<u32>() as usize
                    } else {
                        rng.gen::<u64>() as usize
                    }
                }
            }
            impl Rand for u8 {
                #[inline]
                fn rand<R: Rng>(rng: &mut R) -> u8 {
                    rng.next_u32() as u8
                }
            }
            impl Rand for u16 {
                #[inline]
                fn rand<R: Rng>(rng: &mut R) -> u16 {
                    rng.next_u32() as u16
                }
            }
            impl Rand for u32 {
                #[inline]
                fn rand<R: Rng>(rng: &mut R) -> u32 {
                    rng.next_u32()
                }
            }
            impl Rand for u64 {
                #[inline]
                fn rand<R: Rng>(rng: &mut R) -> u64 {
                    rng.next_u64()
                }
            }
            #[cfg(feature = "i128_support")]
            impl Rand for u128 {
                #[inline]
                fn rand<R: Rng>(rng: &mut R) -> u128 {
                    ((rng.next_u64() as u128) << 64) | (rng.next_u64() as u128)
                }
            }
            impl Rand for f64 {
                fn rand<R: Rng>(rng: &mut R) -> f64 {
                    rng.next_f64()
                }
            }
            impl Rand for f32 {
                fn rand<R: Rng>(rng: &mut R) -> f32 {
                    rng.next_f32()
                }
            }
            impl Rand for char {
                #[inline]
                fn rand<R: Rng>(rng: &mut R) -> char {
                    const CHAR_MASK: u32 = 2097151;
                    loop {
                        match char::from_u32(rng.next_u32() & CHAR_MASK) {
                            Some(c) => return c,
                            None => {}
                        }
                    }
                }
            }
            impl Rand for bool {
                #[inline]
                fn rand<R: Rng>(rng: &mut R) -> bool {
                    rng.gen::<u8>() & 1 == 1
                }
            }
            macro_rules! tuple_impl(( $ ( $ tyvar : ident ) , * ) => {
                                impl < $ ( $ tyvar : Rand ) , * > Rand for (
                                $ ( $ tyvar ) , * , ) {
                                # [ inline ] fn rand < R : Rng > (
                                _rng : & mut R ) -> ( $ ( $ tyvar ) , * , ) {
                                ( $ ( _rng . gen :: < $ tyvar > (  ) ) , * , )
                                } } });
            impl Rand for () {
                #[inline]
                fn rand<R: Rng>(_: &mut R) -> () {
                    ()
                }
            }
            tuple_impl!(A);
            tuple_impl!(A, B);
            tuple_impl!(A, B, C);
            tuple_impl!(A, B, C, D);
            tuple_impl!(A, B, C, D, E);
            tuple_impl!(A, B, C, D, E, F);
            tuple_impl!(A, B, C, D, E, F, G);
            tuple_impl!(A, B, C, D, E, F, G, H);
            tuple_impl!(A, B, C, D, E, F, G, H, I);
            tuple_impl!(A, B, C, D, E, F, G, H, I, J);
            tuple_impl!(A, B, C, D, E, F, G, H, I, J, K);
            tuple_impl!(A, B, C, D, E, F, G, H, I, J, K, L);
            macro_rules! array_impl({
                                $ n : expr , $ t : ident , $ ( $ ts : ident ,
                                ) * } => {
                                array_impl ! { ( $ n - 1 ) , $ ( $ ts , ) * }
                                impl < T > Rand for [ T ; $ n ] where T : Rand
                                {
                                # [ inline ] fn rand < R : Rng > (
                                _rng : & mut R ) -> [ T ; $ n ] {
                                [
                                _rng . gen :: < $ t > (  ) , $ (
                                _rng . gen :: < $ ts > (  ) ) , * ] } } } ; {
                                $ n : expr , } => {
                                impl < T > Rand for [ T ; $ n ] {
                                fn rand < R : Rng > ( _rng : & mut R ) -> [
                                T ; $ n ] { [  ] } } } ;);
            array_impl!(
                32,
                T,
                T,
                T,
                T,
                T,
                T,
                T,
                T,
                T,
                T,
                T,
                T,
                T,
                T,
                T,
                T,
                T,
                T,
                T,
                T,
                T,
                T,
                T,
                T,
                T,
                T,
                T,
                T,
                T,
                T,
                T,
                T,
            );
            impl<T: Rand> Rand for Option<T> {
                #[inline]
                fn rand<R: Rng>(rng: &mut R) -> Option<T> {
                    if rng.gen() {
                        Some(rng.gen())
                    } else {
                        None
                    }
                }
            }
        }
    }
}


Measured memory_bytes: 4352