using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static string InputPattern = "InputX";
static List<string> GetInputList()
{
var WillReturn = new List<string>();
if (InputPattern == "Input1") {
WillReturn.Add("5 4");
WillReturn.Add("6");
WillReturn.Add("1 3 2 4");
WillReturn.Add("1 5 1 1");
WillReturn.Add("5 5 1 4");
WillReturn.Add("4 4 2 2");
WillReturn.Add("5 5 4 4");
WillReturn.Add("1 5 1 4");
//28
//27
//36
//14
//0
//104
}
else if (InputPattern == "Input2") {
WillReturn.Add("1000000000 1000000000");
WillReturn.Add("3");
WillReturn.Add("1000000000 1000000000 1000000000 1000000000");
WillReturn.Add("165997482 306594988 719483261 992306147");
WillReturn.Add("1 1000000000 1 1000000000");
//716070898
//240994972
//536839100
}
else if (InputPattern == "Input3") {
WillReturn.Add("999999999 999999999");
WillReturn.Add("3");
WillReturn.Add("999999999 999999999 999999999 999999999");
WillReturn.Add("216499784 840031647 84657913 415448790");
WillReturn.Add("1 999999999 1 999999999");
//712559605
//648737448
//540261130
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
const long Hou = 998244353;
static long mHeight;
static long mWidth;
static void Main()
{
List<string> InputList = GetInputList();
long[] wkArr = { };
Action<string> SplitAct = pStr =>
wkArr = pStr.Split(' ').Select(pX => long.Parse(pX)).ToArray();
SplitAct(InputList[0]);
mHeight = wkArr[0];
mWidth = wkArr[1];
var sb = new System.Text.StringBuilder();
foreach (string EachStr in InputList.Skip(2)) {
SplitAct(EachStr);
long StaY = wkArr[0];
long EndY = wkArr[1];
long StaX = wkArr[2];
long EndX = wkArr[3];
long Sum1 = DeriveRectSum(EndX, EndY);
long Sum2 = DeriveRectSum(StaX - 1, EndY);
long Sum3 = DeriveRectSum(EndX, StaY - 1);
long Sum4 = DeriveRectSum(StaX - 1, StaY - 1);
long Answer = Sum1;
Answer -= Sum2;
Answer -= Sum3;
Answer += Sum4;
Answer %= Hou;
if (Answer < 0) Answer += Hou;
sb.Append(Answer);
sb.AppendLine();
}
Console.Write(sb.ToString());
}
// 右下の座標を引数として、矩形(1,1)から(pMaxX,pMaxY)の和を求める
static long DeriveRectSum(long pMaxX, long pMaxY)
{
if (pMaxX < 1 || pMaxY < 1) return 0;
// 左上の1から右方向への等差数列の項数
long KouCnt1 = (pMaxX + 1) / 2;
long SuuretuSum1 = DeriveTousaSuuretuSum(1, 2, KouCnt1, Hou);
// 奇数行の等差数列の和
long Syokou2 = SuuretuSum1;
long KouCnt2 = (pMaxY + 1) / 2;
long Kousa2 = 2 * KouCnt1 * mWidth;
long SuuretuSum2 = DeriveTousaSuuretuSum(Syokou2, Kousa2, KouCnt2, Hou);
// 2行目の、M+2から右方向への等差数列の項数
long KouCnt3 = pMaxX / 2;
long SuuretuSum3 = DeriveTousaSuuretuSum(mWidth + 2, 2, KouCnt3, Hou);
// 偶数行の等差数列の和
long Syokou4 = SuuretuSum3;
long KouCnt4 = pMaxY / 2;
long Kousa4 = 2 * KouCnt3 * mWidth;
long SuuretuSum4 = DeriveTousaSuuretuSum(Syokou4, Kousa4, KouCnt4, Hou);
return SuuretuSum2 + SuuretuSum4;
}
// 初項と公差と項数と法を引数として、等差数列の和を返す
static long DeriveTousaSuuretuSum(long pSyokou, long pKousa, long pKouCnt, long pHou)
{
pKouCnt %= pHou;
pKousa %= pHou;
long Makkou = pSyokou + pKousa * (pKouCnt - 1);
Makkou %= pHou;
long wkSum = (pSyokou + Makkou) % pHou;
wkSum %= pHou;
long Result = wkSum * pKouCnt;
Result %= pHou;
Result *= DeriveGyakugen(2);
Result %= pHou;
return Result;
}
// 引数の逆元を求める
static long DeriveGyakugen(long pLong)
{
return DeriveBekijyou(pLong, Hou - 2, Hou);
}
// 繰り返し2乗法で、(NのP乗) Mod Mを求める
static long DeriveBekijyou(long pN, long pP, long pM)
{
long CurrJyousuu = pN % pM;
long CurrShisuu = 1;
long WillReturn = 1;
while (true) {
// 対象ビットが立っている場合
if ((pP & CurrShisuu) > 0) {
WillReturn = (WillReturn * CurrJyousuu) % pM;
}
CurrShisuu *= 2;
if (CurrShisuu > pP) return WillReturn;
CurrJyousuu = (CurrJyousuu * CurrJyousuu) % pM;
}
}
}