8 Stimmen

Wie funktionieren Prozeduraufrufe in Assembler?

Ich habe gerade angefangen, mich mit ASM zu beschäftigen und bin mir nicht sicher, ob mein Verständnis von Prozeduraufrufen richtig ist.

Angenommen, an einer bestimmten Stelle im Code gibt es einen Prozeduraufruf

call dword ptr[123]

und das Verfahren besteht aus nur einem Befehl, ret:

ret 0004

Was würde dieser Prozeduraufruf bewirken, und wo würde der Rückgabewert gespeichert werden? Ich habe irgendwo gelesen, dass ein Rückgabewert von 2 Bytes in AX gespeichert wird, aber wenn ich den Prozeduraufruf durch

mov AX, 0004

(zusammen mit den erforderlichen NOPs) stürzt das Programm ab.

12voto

Nathan Fellman Punkte 115324

In x86-Assembler der Parameter für die ret Anweisung bedeutet:

RET _immediate_

Rückkehr zur aufrufenden Prozedur und Pop sofort Bytes vom Stapel.

(zitiert aus Intel® 64- und IA-32-Architekturen Handbücher für Softwareentwickler Band 2B )

Wenn Sie also tippen:

ret 0004

Sie weisen die CPU an, zu der Anweisung zurückzukehren, die unmittelbar auf die call und 4 Bytes vom Stapel zu nehmen. Dies ist großartig, wenn Sie geschoben 4 Bytes auf dem Stack vor dem Aufruf.

push eax
call dword ptr[123]

Beachten Sie, dass dies nichts mit dem Rückgabewert zu tun hat. Tatsächlich hat eine Prozedur in Assembly keine Möglichkeit, anzugeben, dass ein Wert ein return Wert. Dies alles geschieht nach Konvention. Die meisten Compiler, die mir bekannt sind, verwenden EAX um den Rückgabewert zu halten, aber das ist nur wahr, weil die aufrufen Funktion wird das Ergebnis dort erwarten.

Ihre Vorwahl wäre also:

call dword ptr [123]
mov dword ptr [result], eax

und Ihre Funktion, die den Wert 4 zurückgibt, wäre:

mov eax, 4
ret

2voto

aib Punkte 42913

Es hängt alles von der Namenskonvention verwendet werden. Ich werde den Wikipedia-Artikel hier nicht wiederholen, lesen Sie einfach die Definition.

In der C-Aufruf-Konvention würde der Rückgabewert z. B. in EAX/AX/AL stehen. Ihre Single-Instruktion hat keinen solchen Wert: Es handelt sich um eine ungültige Funktion, die etwa 4 Bytes an Parametern benötigt (möglicherweise ein einzelner int) und nichts tut. Da es die Pflicht des Aufrufenden ist, den Stack in dieser Aufrufkonvention aufzuräumen, funktioniert es nicht, dies zu ignorieren und den Aufruf durch ein 'mov ax' zu ersetzen.

Außerdem vermute ich, dass Sie mit 32-Bit-Assembler arbeiten, während Sie ein 16-Bit-Dokument lesen. Das ist kein großes Problem, aber Sie sollten sich der Unterschiede bewusst sein.

1voto

Nick Dandoulakis Punkte 41402
// possibly there are arguments pushed here
...
call dword ptr[123] // push next OP code offset in the stack and jump to procedure

// procedure
...
ret 0004 // pop offset, set EIP to that offset and decrease ESP by 4

wir zusätzlich die ESP verringern, wenn wir vor dem Aufruf der Prozedur Argumente auf den Stack geschoben hätten.

Wenn es gepushte Argumente gibt, stürzt Ihr Programm ab, weil Sie sie nicht ausblenden. Der Rückgabeoffset für die aktuelle Prozedur wird falsch sein, da sie einen Wert von einem der gepushten Argumente als Offset erhält.

-1voto

A.Rashad Punkte 1004

Ich glaube nicht, dass der Rückgabewert im Register AX gespeichert wird.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X