#include <bits/stdc++.h>

// headers {{{
using namespace std;
// using namespace rel_ops;
 
const double pi=acos(-1.0);
const double eps=1e-11;
const int INF=0x7FFFFFFF;
template<class T> inline bool checkmin(T &a,T b){return b<a?a=b,1:0;}
template<class T> inline bool checkmax(T &a,T b){return b>a?a=b,1:0;}
template<class T> inline T sqr(T x){return x*x;}
template<class T> inline bool bit(T a, int b) {return (a>>b)&1;}
inline int popcount(int n) { return __builtin_popcount(n); }
inline int popcount(long long n) { return __builtin_popcountll(n); }
typedef long long int64;
typedef unsigned long long uint64;
typedef pair<int,int> PII;
typedef vector<int> VI;
typedef vector<PII> VII;
#define MP(A,B) make_pair(A,B)
#define PB(X) push_back(X)
#define eb(args...) emplace_back(args)
#define rep(i,n) for(int i=0; i<(int)n; i++)
#define ff first
#define ss second
#define sz(g) int(g.size())
template<typename A, typename B> ostream& operator<<(ostream &os, const pair<A, B> &p) { return os << '(' << p.first << ", " << p.second << ')'; }
template<typename T> ostream& operator<<(ostream &os, const vector<T> &v) { os << '{'; string sep; for (const auto &x : v) os << sep << x, sep = ", "; return os << '}'; }
#ifdef LOCAL
#define dout cerr 
void out() { dout << endl; }
template<typename A, typename... B> void out(A a, B... b) { dout << ' ' << a; out(b...); }
#define dbg(args...) dout << __LINE__ << ":(" << #args << ") -> ", out(args)
template<class T>void show(T a, int n){for(int i=0; i<n; ++i) cout<<a[i]<<' '; cout<<endl;}
template<class T>void show(T a, int r, int l){for(int i=0; i<r; ++i)show(a[i],l);cout<<endl;}
constexpr bool local = true;
#else
#define dbg(...)
#define dout if(true);else cerr
#define out(...)
#define show(...)
constexpr bool local = false;
#endif
// }}}

template <int m, typename intbase = int>
struct ModInt {
    intbase r;
    ModInt() : r(0) {}
    ModInt(int64_t rr) : r(rr) { if (abs(r) >= m) r %= m; if (r < 0) r += m; }
    ModInt(int rr) : r(rr) { if (abs(r) >= m) r %= m; if (r < 0) r += m; }
    ModInt inv() const { return this->pow(m - 2); }
    template<typename I> ModInt pow(I t) const {
        ModInt ret(1), base(*this);
        while (t) { if (t&1) ret *= base; base *= base; t >>= 1; }
        return ret;
    }
    ModInt operator*(const ModInt &t) const { return (int64_t(r) * t.r) % m; }
    ModInt operator/(const ModInt &t) const { return *this * t.inv(); }
    ModInt operator+=(const ModInt &t) { r += t.r; if (r >= m) r -= m; return *this; }
    ModInt operator-=(const ModInt &t) { r -= t.r; if (r < 0) r += m; return *this; }
    friend std::ostream& operator<<(std::ostream& os, ModInt x) { return os << x.r; }
    ModInt operator+(const ModInt &t) const { return ModInt(*this) += t; }
    ModInt operator-(const ModInt &t) const { return ModInt(*this) -= t; }
    ModInt operator-() const { return ModInt(m-r); }
    ModInt operator*=(const ModInt &t) { return *this = *this * t; }
    ModInt operator/=(const ModInt &t) { return *this = *this / t; }

    bool operator==(const ModInt &t) const { return r == t.r; }
    bool operator!=(const ModInt &t) const { return r != t.r; }

    operator int64_t() const { return r; }
};
using Int = ModInt<998244353>;
Int operator""_M(unsigned long long n) { return Int(int64_t(n)); }

template<typename T=Int>
struct NChooseR {
    vector<T> perm;
    NChooseR(int N=1e5) : perm(N+1) {
        perm[0] = 1;
        for (int i = 1; i <= N; i++) perm[i] = perm[i-1] * T(i);
    }
    T operator()(int n, int r) {
        return perm[n] / perm[r] / perm[n-r];
    }
};


Int dp[3001][3001];
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL); 
    int a, b, c, d;
    while (cin >> a >> b >> c >> d) {
        memset(dp, 0, sizeof(dp));
        dp[a][b] = 1;
        for (int i = a+1; i <= c; i++) dp[i][b] = dp[i-1][b] * Int(b);
		for (int i = b+1; i <= d; i++) dp[a][i] = dp[a][i-1] * Int(a);
		for (int i = a+1; i <= c; i++) {
			for (int j = b+1; j<=d; j++) {
				// dp[i][j] = dp[i-1][j-1] * Int(i-1)*Int(j) + dp[i-1][j] + dp[i][j-1];
				// dp[i][j] = dp[i-1][j] * Int(j) + dp[i][j-1] * Int(i) - (dp[i-1][j]+dp[i][j-1]) * inv2;
				dp[i][j] = dp[i-1][j] * Int(j) + dp[i][j-1] * Int(i) - dp[i-1][j-1] * Int(i-1) * Int(j-1);
			}
		}
        show(dp, c+1, d+1);
        cout << dp[c][d] << endl;
	}
	return 0;
}



Measured memory_bytes: 38796