2012-03-23 16 views
4

Linux Assembly Tutorial Zustände:Assembly: Warum verursacht das Springen zu einem Label, das über ret zurückkehrt, einen Segmentierungsfehler?

gibt es eine sehr wichtige Sache zu erinnern: Wenn Sie von einer Prozedur (mit dem RET-Befehl) zurückzukehren planen, nicht springen zu ihm! Wie in "nie!" Das wird einen Segmentierungsfehler auf Linux verursachen (was OK ist - alles, was Ihr Programm tut, wird beendet), aber in DOS kann es in verschiedenen Graden des Schreckens in Ihrem Gesicht explodieren.

Aber ich kann nicht verstehen, warum es einen Segmentierungsfehler nicht verursacht. Es klingt wie eine Rückkehr von einer Funktion.

Ich habe eine Situation, in der ich die Logik implementieren muss "Wenn X passiert, rufen Sie Prozedur A auf. Andernfalls rufen Sie Prozedur B." Gibt es einen anderen Weg als herumzuspringen wie ein Känguru-Spaghetti-Code?

+1

Nur eine Anmerkung: Es gibt nichts, was Sie daran hindert, dies zu tun, aber was es tut, ist für neue Assembler-Programmierer nicht immer offensichtlich. Der häufigste Fall wird als "Tail Call" bezeichnet und ist in funktionalen Sprachen üblich. Der Effekt besteht darin, zum Aufrufer der Funktion zurückzukehren, die den Sprung enthält (den Rest dieser Funktion zu umgehen), * wenn * Sie Ihren kleinen Teil des Stapels bereinigt haben. Wenn nicht, dann sehen Sie segfaults. – cHao

+1

Stellen Sie sicher, dass Sie den Unterschied von 'jmp' und' call' verstehen. – hirschhornsalz

Antwort

7

Weil CALL die aktuelle Befehlsadresse auf den Stack verschiebt, und RET zieht es ab, um zur Call-Site zurückzukehren. JMP (und zugehörige Anweisungen) schieben Sie nichts auf den Stapel.

-1

Ich denke, dass dieser Rat möglicherweise mit der Pipeline zu tun haben, aber ich bin mir nicht sicher.

Ich glaube, dass die Frage, die Sie fragen werden, ist:

... subroutine entrypoint ... 
... various instructions in a routine ... 
jmp label 
... move instructions in a routine... 
label: 
ret 

Was ist das Problem, wenn jeder, mit diesem? Erstens bin ich mir nicht sicher, ob das überhaupt ein Problem ist. Aber wenn es ist, ist es die Pipeline. Bei einigen Prozessoren wird eine oder mehrere Anweisungen nach der JMP ausgeführt werden, bevor die Steuerung auf das Etikett bewegt.

Meistens habe ich Angst, dass Sie das, was Sie gelesen haben, falsch verstanden haben, oder ich habe missverstanden, was Sie geschrieben haben. Es ist in Ordnung, von einem Punkt in der Subroutine bis zur Anweisung ret zu jmping zu gehen. Jump-ing anstelle von Ret ist, wie andere Leute darauf hingewiesen haben, eine dumme Idee.

+1

Ich denke, die Frage bezieht sich darauf, warum Sie nicht eine naive 'jmp' verwenden können, um eine Funktion aufzurufen, anstatt die' call' Anweisung zu verwenden. Natürlich kannst du das tun, wenn du den Stack selbst aufstellst, aber ansonsten ist das zum Scheitern verurteilt, weil 'ret' ins Nichts zurückkehrt. –

+1

Ich denke, die OP-Quote bedeutet "nicht zu einem Unterprogramm springen, immer anrufen", anstatt "nicht zum Befehl ret springen". –

+0

Ja, das sind was ich meinte. Entschuldigung, wenn ich unklar war :) – InvalidBrainException