import std.stdio, std.array, std.string, std.conv, std.algorithm;
import std.typecons, std.range, std.random, std.math, std.container;
import std.numeric, std.bigint, core.bitop, core.stdc.string;

immutable int M = 30;
long x, y;
int cnt = 0;

int ask(long c, long d) {
    debug {
        cnt += 1;
        if ((x^c) > (y^d)) return 1;
        else if ((x^c) == (y^d)) return 0;
        else return -1;
    }

    writeln("? ", c, " ", d);
    stdout.flush;
    return readln.chomp.to!int;
}

void answer(long a, long b) {
    writeln("! ", a, " ", b);
    stdout.flush;
}

void main() {
    debug {
        auto s = readln.split.map!(to!long);
        x = s[0];
        y = s[1];
    }

    int f = ask(0, 0);
    int ff = f;

    if (f == 0) {
        long a = 0;
        foreach_reverse (i; 0..M) {
            long c = (1L << (i + 1)) - 1;
            long d = (1L << i) - 1;
            c += a;
            d += a;
            f = ask(c, d);
            if (f == -1) {
                a += 1L << i;
            }
        }
        answer(a, a);
        return;
    }

    bool a_large = f == 1;
    long a = 0;
    long b = 0;
    auto same = new bool[](M);

    foreach_reverse (i; 0..M) {
        long c = 1L << i;
        f = ask(a+c, b+c);
        if (a_large && f == -1) {
            a += c;
            f = ask(a, b);
            a_large = f == 1;
        } else if (!a_large && f == 1) {
            b += c;
            f = ask(a, b);
            a_large = f == 1;
        } else {
            same[i] = true;
        }
    }

    foreach (i; 0..M) {
        if (!same[i]) {
            continue;
        }
        long c = 1L << i;
        f = ask(a+c, b);
        if (f == -1) {
            a += c;
            b += c;
        }
    }

    answer(a, b);
    debug{cnt.writeln;}
}
