#include<bits/stdc++.h>
#define XX first
#define YY second
#define pb emplace_back
#define FOR(i,a,b) for(int (i)=(a);i<(b);++(i))
#define EFOR(i,a,b) for(int (i)=(a);i<=(b);++(i))
#define rep(X,Y) for (int (X) = 0;(X) < (Y);++(X))
#define REP rep
#define rrep(X,Y) for (int (X) = (Y)-1;(X) >=0;--(X))
#define all(X) (X).begin(),(X).end()
#define eb emplace_back

using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef ll LL;
typedef pii PII;
typedef pll PLL;
const ll MOD=1e9+7;

#define rall(X) (X).rbegin(),(X).rend()
#define UNIQUE(X) (X).erase(unique(all(X)),(X).end())
#define reps(X,S,Y) for (int (X) = S;(X) < (Y);++(X))
#define rreps(X,S,Y) for (int (X) = (Y)-1;(X) >= (S);--(X))
template<class T> inline bool MX(T &l,const T &r){return l<r?l=r,1:0;}
template<class T> inline bool MN(T &l,const T &r){return l>r?l=r,1:0;}

template<ll mod>
struct ModInt{
  using M=ModInt;
  ll a;
  M& put(ll v){
    a=(v<mod)?v:v-mod;
    return *this;
  }
  ModInt(ll v=0){put(v%mod+mod);}
  M operator+(M x){return M().put(a+x.a);}
  M operator-(M x){return M().put(a+mod-x.a);}
  M operator*(M x){return M().put(a*x.a%mod);}
  M operator/(M x){return x.inv()*a;}
  M& operator+=(M x){return *this=*this+x;};
  M& operator-=(M x){return *this=*this-x;};
  M& operator*=(M x){return *this=*this*x;};
  M& operator/=(M x){return *this=*this/x;};
  bool operator==(M x){return a==x.a;}
  M pow(ll m) {
    M x=*this,res=1;
    while(m){
      if(m&1)res*=x;
      x*=x;
      m>>=1;
    }
    return res;
  }
  M inv(){return pow(mod-2);}
};
using mint = ModInt<998244353>;

int A, B, C, D;
// 0, yo 1, ta [yo][ta]
mint dp[3145][3145][3][3];

mint Tate(int y, int x, int k) {
  mint ret = 0;
  rep(i, 3) {
    ret += dp[y][x][i][k];
  }
  return ret;
}
mint Yoko(int y, int x, int k) {
  mint ret = 0;
  rep(i, 3) {
    ret += dp[y][x][k][i];
  }
  return ret;
}

signed main(){
  ios_base::sync_with_stdio(false);
  cout<<fixed<<setprecision(0);

  cin >> A >> B >> C >> D;

  if (A == C && B == D) {
    cout << "1" << endl;
    return 0;
  }

  dp[A][B][1][0] = 1;
  reps(y, A+1, C+1) {
    dp[y][B][1][0] = dp[y-1][B][1][0] * B;
  }
  dp[A][B][0][1] = 1;
  reps(x, B+1, D+1) {
    dp[A][x][0][1] = dp[A][x-1][0][1] * A;
  }

  //if (A < C) dp[A+1][B][1][0] = B;
  //if (B < D) dp[A][B+1][0][1] = A;

  reps(y, A+1, C+1) {
    reps(x, B+1, D+1) {
      if (y-A + x-B <= 1) continue;

      if (y > A && x > B) {
        if (!(Yoko(y, x-1, 1) * (y-1) == Tate(y-1, x, 1) * (x-1))) {
          cout << y << ", " << x << endl;
          cout << Yoko(y, x-1, 1).a << endl;
          cout << Tate(y-1, x, 1).a << endl;
        }
        assert(Yoko(y, x-1, 1) * (y-1) == Tate(y-1, x, 1) * (x-1));
        dp[y][x][1][1] += Yoko(y, x-1, 1) * (y-1);
        //dp[y][x][1][1] += Tate(y-1, x, 1) * (x-1);
      }

      if (x > B) {
        dp[y][x][2][1] += Yoko(y, x-1, 2) * (y-1);
        dp[y][x][2][1] += Yoko(y, x-1, 1) + Yoko(y, x-1, 2);
      } 

      if (y > A) {
        dp[y][x][1][2] += Tate(y-1, x, 2) * (x-1);
        dp[y][x][1][2] += Tate(y-1, x, 1) + Tate(y-1, x, 2);
      }
    }
  }

  mint ans = 0;
  rep(i, 3) {
    rep(j, 3) {
      ans += dp[C][D][i][j];
    }
  }
  cout << ans.a << endl;
}


Measured memory_bytes: 699072