2014-02-09 19 views
7

Ich versuche, eine MIPS-Firmware umzukehren. Die Firmware ist Big-Endian-codiert für einen 32-Bit-r4kec-Prozessor.Zwei sequentielle Verzweigungsbefehle in MIPS-Assembly?

ich demontiert (mit objdump) die binäre, um zu sehen, was die Montage aussieht, und alles sieht aus wie gültiger Code, aber gleich am Anfang des Codes ich die folgenden zwei Befehle sehen:

bfc00220 152a0001 bne t1, t2, 0xbfc00228 
bfc00224 10000009 b 0xbfc0024c 

Der erste Befehl prüft die Werte der Register t1 und t2 und springt zu einer Adresse, wenn sie nicht gleich sind. Die zweite Anweisung scheint den Fall-Through-Fall zu behandeln, um direkt zu einer nachfolgenden Adresse zu springen. So weit, so gut oder nicht?

Meiner Kenntnis nach ist dies nicht legal. Alle verfügbaren MIPS-Dokumente, die ich gelesen habe, geben an, dass der Befehl, der direkt einem Verzweigungs-/Sprungbefehl folgt, als ein Sprungverzögerungsschlitz behandelt wird, dessen Befehl immer ausgeführt wird (ausgenommen die Zweigwahrscheinliche Klasse von Befehlen) durchgeführt.

Das Schlüsselproblem hier ist, dass ein anderer Zweig/Sprung nicht erlaubt in der Sprungverzögerung Slot ist, und dies wird den Prozessor in einem undefinierten Zustand verlassen.

Also was soll ich von diesem Code machen? Ich glaube nicht, dass dies eine Handarbeit ist (obwohl es nicht zu weit hergeholt wäre) für eine CPU, die diese Situation in einer bekannten deterministischen Art behandelt. Ich kann auch nicht glauben, dass ein Compiler wissentlich Code wie diesen erzeugt. Die andere Möglichkeit ist, dass ich den falschen Decompiler für die Binärdatei verwende, oder dass ich die Endiannität falsch habe, oder etwas anderes ...

Kann mir jemand erklären, was hier vor sich geht?

+1

Wie lautet die Adresse der ersten Anweisung, die von einem MIPS-Prozessor nach einem Reset oder Hochfahren ausgeführt wird? Gibt es eine Änderung, dass die ersten beiden Anweisungen eine Art Header sind und niemals als Code ausgeführt werden? – rcgldr

+0

'b' Anweisung ist * Zweig *, nicht" Pause ". –

+0

bearbeitet für s/break/branch/für zukünftige Suchende. – markgz

Antwort

0

Während dies ein nicht definiertes Verhalten ist, könnte eine bestimmte CPU-Implementierung für diese Befehlssequenz etwas Nützliches und Wiederholbares tun. Die einzige Möglichkeit, dies zu erkennen, besteht darin, den Code für diese tatsächliche Implementierung auszuführen. Verwenden Sie einen Debugger, um einen Haltepunkt auf das Ziel jeder Verzweigung zu setzen, und sehen Sie, welchen Sie erreichen.

Dies könnte sogar ein Fehler in der handgenerierten Assembly sein, die nie abgefangen wurde, weil das tatsächliche Verhalten des Codes nicht inkorrekt war.

+0

Ich denke, dass Sie Recht haben - das ist wahrscheinlich handgefertigte Montage, und die zwei Verzweigung Anweisungen wurden dort platziert und arbeitete wie erwartet "zufällig", für die spezifische CPU. Ich habe keine Jtag-Schnittstelle zu der Platine, auf der dieser Code ausgeführt werden soll, aber sobald ich ein bisschen weiter mit der Umkehrung fortgeschritten bin, sollte ich in der Lage sein, Code wie diesen auszuführen und über die serielle Ausgabe zu verfolgen. – user3290882

2

Das "undefined Verhalten" bedeutet nur, dass - es ist nicht angegeben, was passieren wird. Dies kann dazu führen, dass die CPU blockiert oder die Anweisung tatsächlich ausgeführt wird.

Sehen Sie diesen Beitrag über einige Tricks mit Delay-Slots, die in m88k verwendet wurden:

http://www.pagetable.com/?p=313

Oder die Antwort kann noch einfacher: Sie Daten können suchen, nicht-Code. Da eine rohe Binärdatei keine Informationen über Code-/Datengrenzen enthält, wird in objdump standardmäßig alles demontiert, ob dies sinnvoll ist oder nicht.