![]() |
In Asm-Prozedur eine Exception auslösen
Ich möchte in einer Assembler-Prozedur eine Exception auslösen.
Hierbei sollen keine außerhalb der Prozedur liegenden Prozeduren aufgerufen werden, ausgenommen natürlich System-Routinen. Konstruktionen, wie zum Beispiel
Delphi-Quellcode:
PROCEDURE RaiseException(const S:String);
begin raise Exception.Create(S); end;
Delphi-Quellcode:
Möchte ich nicht.
PROCEDURE Test;
const sErr:String='Meine Fehlermeldung'; asm mov eax,sErr call RaiseException; end; Ich hab mir mal ein "raise Exception" angeschaut und fand:
Delphi-Quellcode:
Fragen:
mov ecx,[ebp-$04] // Fehlermeldung
mov dl,$01 mov eax,[$00419bc8] // ??? call Exception.Create call @RaiseExcept Was wird da in EAX geladen, und wie kann ich das in eigenen Assembler-Routinen realisieren? |
AW: In Asm-Prozedur eine Exception auslösen
Der Zeiger auf die Typdefinition der Klasse, welche erstellt werden soll, würd' ich mal sagen. (alternativ zur VMT, falls der Constructor virtuell wäre)
Hier also die Klasse "Exception". (entspricht quasi sowas, wie dem versteckten Parameter "Self" einer nicht-static Class-Procedure) siehe
Delphi-Quellcode:
in der System.pas
function _ClassCreate(InstanceOrVMT: Pointer; Alloc: ShortInt): Pointer;
Vielleicht einfacher, wenn du stattdessen Error oder RunError der System-Unit nutzt. |
AW: In Asm-Prozedur eine Exception auslösen
Zitat:
Hab mir Error und _RunError angeschaut. Wenn ich das richtig verstehe, kann man bei beiden nur einen Fehlercode, nicht aber einen situationsbedingten Text übergeben. Auf _ClassCreate war ich auch schon gestoßen, mir ist aber nicht klar, wie ich diesen Pointer ins EAX-Register hinein bekomme. Sei doch so nett und schaue da noch mal rein. Danke im Voraus. |
AW: In Asm-Prozedur eine Exception auslösen
EAX wird meistens für den Rückgabewert verwendet.
Pseudo-Code: call ExitProcedure mov eax, 42 ret wird dann im ErrorLevel einer Batch-Datei mit 42 quittiert. |
AW: In Asm-Prozedur eine Exception auslösen
Zitat:
|
AW: In Asm-Prozedur eine Exception auslösen
man kann aber auch einen "indirekten Aufruf" (indirect call) so machen:
Pseudo-Code: mov eax, [Variable] call eax ... Variable: dd 0x1234 oder: mov eax, Offset (wobei Offset: 0x1234 sein kann) call eax |
AW: In Asm-Prozedur eine Exception auslösen
Zitat:
Wenn du nix zum wirklichen Thema beitragen kannst, dann sei bitte so nett und schweig einfach. |
AW: In Asm-Prozedur eine Exception auslösen
Zitat:
Anyway, i highly recommend to refrain form generating exception from assembly for the same reason above and the share amount of time you will spend on it to work and it most likely will bite you in the butt. Here a simple code that will work for 32bit
Code:
the result on my PC now
program AsmException;
{$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils; type TMyException = class(Exception) end; function GetException(Ex: ExceptClass; const Msg: string): Exception; begin Result := Ex.Create(Msg); end; procedure ExceptionPas1; begin raise GetException(Exception, 'Error Message from Exception'); end; procedure ExceptionPas2; begin raise GetException(TMyException, 'Error Message from MyExeption'); end; procedure ExceptionAsm32; const pMyExClass: ExceptClass = (TMyException); LocalExceptionMsg : string = 'Error from Assembly'; asm mov edx, LocalExceptionMsg mov eax, pMyExClass Call GetException Call system.@RaiseExcept end; { procedure ExceptionAsm64; // will not work, may be wrong, may be just need lot of hand tweaking const pMyExClass: ExceptClass = (TMyException); LocalExceptionMsg : string = 'Error from Assembly'; asm push rbp mov rbp, rsp mov rdx, LocalExceptionMsg mov rcx, pMyExClass Call GetException mov rcx, rax Call system.@RaiseExcept mov rsp, rbp pop rbp end; } begin try ExceptionPas1; except on E: Exception do Writeln(E.ClassName, ' class : ', E.Message); end; try ExceptionPas2; except on E: Exception do Writeln(E.ClassName, ' class : ', E.Message); end; try ExceptionAsm32; except on E: Exception do Writeln(E.ClassName, ' class : ', E.Message); end; Readln; end.
Code:
Yet there is som much to this than what meet the eyes, see, when an exception is raised then unwinding process will issued, for 32bit it is way easier because the system and its API where on the stack, on x64 the calling convention is like Delphi mostly with registers so framed stack will be used and these for optimization reason and unnecessity might be omited, here become problems with guessing where to go next, so you have to be sure for your assembly that framing is OK, in my example for 32 bit it is ok unless your assembly started to grow and the compiler added a frame stack to ruin things, same on x64, which is not working in my above code, i left it as example for who want to try to make it work, it is just waste of time.
Exception class : Error Message from Exception
TMyException class : Error Message from MyExeption TMyException class : Error from Assembly My suggestion is that for anything with exception use Pascal/Delphi code, only then the compiler might be helpful, put your exception creation and raising in procedure and call it from assembly, easier and might be safer too. |
AW: In Asm-Prozedur eine Exception auslösen
I just remembered, not long ago there was a thread about disappearing application when an exception raised, tweaking and playing (something like commenting the rbp instructions) with ExceptionAsm64 will produce similar behavior of disappearing application with messages, the OS will just kill it silently and will not look back.
|
AW: In Asm-Prozedur eine Exception auslösen
Zitat:
Delphi-Quellcode:
wäre eine Option eine Exception zu erzeugen ohne dass du dich selber ums erzeugen kümmern musst. Ist aber ein procedure call mit zwei Parametern.
Assert
Für eine richtige Exception wirst du nicht drum rum kommen dir eine Instanz einer Exception Klasse anzulegen und mit deren Methoden zu arbeiten. Aber, was ist dein Ziel? Eine Fehlermeldung anzuzeigen und dann dein Programm beenden? Oder wirklich eine Exception zu erzeugen? Wenn es ganz schnell gehen muss:
Delphi-Quellcode:
Das erzeugt eine von Windows generierte Meldung, allerdings ohne einen spezifischen Text. Führt aber ganz sicher und ohne jede Chance das Programm noch zu retten zu einem Ende ;-)
INT $29;
// void __fastfail(unsigned int code); |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:22 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz