import java.awt.*;
import java.io.*;
import java.math.*;
import java.util.*;



public class Main {

    public static void main(String[] args) {
        new Main().run();
    }

    int askab(int a, int b, int c, int d) {
        if((a^c) > (b^d)) return 1;
        if((a^c) < (b^d)) return -1;
        return 0;
    }
    boolean canGet(int A, int B, int bit, int c, int d, int g1, int g2) {
        if(bit == 0) {
            return askab(A, B, c^(1<<bit), d) == g1 && askab(A, B, c, d^(1<<bit)) == g2;
        }
        if(askab(A, B, c^(1<<bit), d) * g1<0) return false;
        if(askab(A, B, c, d^(1<<bit)) * g2>0) return false;
        int d1 = askab(A, B, c^(1<<bit), d);
        int d2 = askab(A, B, c, d^(1<<bit));
        return !(d1 == 0 && d2 == 0);
    }
    int ask(int a, int b) {
        out.println("? " + a + " " + b);
        out.flush();
        int d = in.nextInt();
        if (d==-1) {
            throw new IllegalArgumentException();
        }
        return d;
    }
    void solve() {
        /*
        for(int a = 0; a < 8; a++) {
            for (int b = 0; b < 8; b++) {
                int A = 0, B = 0;
                for(int bit = 2; bit >= 0; bit--) {
                    int g1 = askab(a, b, A^(1<<bit), B);
                    int g2 = askab(a, b, A, B^(1<<bit));
                    int cnt = 0;
                    if(g1 == 0 || g2 == 0) break;
                    for(int mask = 0; mask < 4; mask++) {
                        int AA = A;
                        int BB = B;
                        if((mask&1) > 0) AA ^= (1<<bit);
                        if((mask&2) > 0) BB ^= (1<<bit);
                        if(canGet(AA, BB, bit, A, B, g1, g2)) {
                            cnt++;
                        }
                    }
                    if(cnt>1) {
                        out.println(a + " " + b + " " + bit + " " + g1 + " " + g2 + " " + A + " " + B);
                        return;
                    }
                    if ((a&(1<<bit)) > 0) A ^= (1<<bit);
                    if ((b&(1<<bit)) > 0) B ^= (1<<bit);
                }
            }
        }
        */
        int bit = 29;
        int f = 0;
        int A = 0, B = 0, V = 0;
        while(bit>=0) {
            int g1 = ask(A^(1<<bit), B);
            int g2 = ask(A, B^(1<<bit));
            if(g1 == 0 || g2 == 0) {
                V = A^(1<<bit)^B;
                f = 1;
                break;
            }
            for(int mask = 0; mask < 4; mask++) {
                int AA = A;
                int BB = B;
                if((mask&1) > 0) AA ^= (1<<bit);
                if((mask&2) > 0) BB ^= (1<<bit);
                if(canGet(AA, BB, bit, A, B, g1, g2)) {
                    A = AA;
                    B = BB;
                    break;
                }
            }
            bit-=1;
        }

        if(f > 0) {
            while(bit>=0) {
                if((V&(1<<bit)) > 0) {
                    int g = ask(A, B);
                    if(g>0) A^=(1<<bit);
                    else B^=(1<<bit);
                }else {
                    int g = ask(A, B^(1<<bit));
                    if(g>0) {
                        A ^= (1 << bit);
                        B ^= (1 << bit);
                    }
                }
                bit-=1;
            }
        }
        out.println("! " + A + " "+B);
        out.flush();
    }


    FastScanner in;
    PrintWriter out;
    void run() {
        try{
            in = new FastScanner(System.in);
            out = new PrintWriter(System.out);
        }catch (Exception e) {
            // TODO: handle exception
        }
        int tests = 1;//in.nextInt();
        while(tests > 0){
            solve();
            tests--;
        }
        out.close();
    }

    class FastScanner {
        StringTokenizer st;
        BufferedReader bf;

        public FastScanner(InputStream is) {
            bf = new BufferedReader(new InputStreamReader(is));
        }

        public FastScanner(File f){
            try{
                bf = new BufferedReader(new FileReader(f));
            }
            catch(IOException ex){
                ex.printStackTrace();
            }
        }
        String next(){
            while(st == null || !st.hasMoreTokens()){
                try{
                    st = new StringTokenizer(bf.readLine());
                }
                catch(Exception ex){
                    ex.printStackTrace();
                }
            }
            return st.nextToken();
        }
        int nextInt(){
            return Integer.parseInt(next());
        }
        long nextLong(){
            return Long.parseLong(next());
        }
        double nextDouble(){
            return Double.parseDouble(next());
        }
        int[] readArray(int n){
            int[] a = new int[n];
            for(int i = 0; i < n; i++)
                a[i] = nextInt();
            return a;
        }
    }

}