Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   In Asm-Prozedur eine Exception auslösen (https://www.delphipraxis.net/213988-asm-prozedur-eine-exception-ausloesen.html)

Amateurprofi 2. Nov 2023 22:37

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:
PROCEDURE Test;
const sErr:String='Meine Fehlermeldung';
asm
   mov  eax,sErr
   call RaiseException;
end;
Möchte ich nicht.

Ich hab mir mal ein "raise Exception" angeschaut und fand:
Delphi-Quellcode:
   mov ecx,[ebp-$04] // Fehlermeldung
   mov dl,$01 
   mov eax,[$00419bc8] // ???
   call Exception.Create
   call @RaiseExcept
Fragen:
Was wird da in EAX geladen, und wie kann ich das in eigenen Assembler-Routinen realisieren?

himitsu 3. Nov 2023 01:42

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:
function _ClassCreate(InstanceOrVMT: Pointer; Alloc: ShortInt): Pointer;
in der System.pas


Vielleicht einfacher, wenn du stattdessen Error oder RunError der System-Unit nutzt.

Amateurprofi 3. Nov 2023 05:58

AW: In Asm-Prozedur eine Exception auslösen
 
Zitat:

Zitat von himitsu (Beitrag 1528929)
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:
function _ClassCreate(InstanceOrVMT: Pointer; Alloc: ShortInt): Pointer;
in der System.pas


Vielleicht einfacher, wenn du stattdessen Error oder RunError der System-Unit nutzt.

Danke, himitsu.
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.

paule32.jk 3. Nov 2023 07:07

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.

jaenicke 3. Nov 2023 07:29

AW: In Asm-Prozedur eine Exception auslösen
 
Zitat:

Zitat von paule32.jk (Beitrag 1528933)
EAX wird meistens für den Rückgabewert verwendet.

Das nennt sich Aufrufkonvention. In diesem Fall geht es um den ersten Parameter für die aufzurufende Methode.

paule32.jk 3. Nov 2023 09:26

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

Sinspin 3. Nov 2023 10:43

AW: In Asm-Prozedur eine Exception auslösen
 
Zitat:

Zitat von paule32.jk (Beitrag 1528941)
bla bla bla

Das geht total am Thema vorbei, könntest Du das lassen?
Wenn du nix zum wirklichen Thema beitragen kannst, dann sei bitte so nett und schweig einfach.

Kas Ob. 3. Nov 2023 11:08

AW: In Asm-Prozedur eine Exception auslösen
 
Zitat:

Zitat von Amateurprofi (Beitrag 1528925)
Delphi-Quellcode:
   mov eax,[$00419bc8] // ???
Fragen:
Was wird da in EAX geladen, und wie kann ich das in eigenen Assembler-Routinen realisieren?

In eax a pointer to a type class to create, and Delphi Assembler is very outdated and can't perform many things, in fact it is stuck in 90s, and till this day Embarcadero call it inline-assembler, while it is inline only for 32bit and not inline for 64.

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:
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.
the result on my PC now
Code:
Exception class : Error Message from Exception
TMyException class : Error Message from MyExeption
TMyException class : Error from Assembly
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.

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.

Kas Ob. 3. Nov 2023 11:12

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.

Sinspin 3. Nov 2023 11:56

AW: In Asm-Prozedur eine Exception auslösen
 
Zitat:

Zitat von Amateurprofi (Beitrag 1528925)
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.

Was wäre eine Systemroutine?
Delphi-Quellcode:
Assert
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.
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:
INT $29;
// void __fastfail(unsigned int code);
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 ;-)

Amateurprofi 3. Nov 2023 22:02

AW: In Asm-Prozedur eine Exception auslösen
 
Zitat:

Zitat von Sinspin (Beitrag 1528951)
Zitat:

Zitat von paule32.jk (Beitrag 1528941)
bla bla bla

Das geht total am Thema vorbei, könntest Du das lassen?
Wenn du nix zum wirklichen Thema beitragen kannst, dann sei bitte so nett und schweig einfach.

Danke.
Genau das, was ich mir dachte, aber da ich ja der Fragensteller bin ...

Amateurprofi 3. Nov 2023 22:28

AW: In Asm-Prozedur eine Exception auslösen
 
@Kas Ob.
Thanks for your detailed comments in #8.
Unfortunately not was I am looking for, because I dont want to call procedures outside of my Asm-Procedure (except system-routines).

What I am currently using is the following:

Delphi-Quellcode:
PROCEDURE RaiseException(const S:String);
begin
   raise Exception.Create(S);
end;
Delphi-Quellcode:
PROCEDURE Test;
const S:String='My Message';
asm
   {$IFDEF CPUX86}
   mov  eax,S
   {$ELSE}
   mov  rcx,S
   {$ENDIF}
   jmp  RaiseException
end;

Amateurprofi 3. Nov 2023 22:35

AW: In Asm-Prozedur eine Exception auslösen
 
Zitat:

Zitat von Sinspin (Beitrag 1528963)
Zitat:

Zitat von Amateurprofi (Beitrag 1528925)
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.

Was wäre eine Systemroutine?
Delphi-Quellcode:
Assert
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.
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:
INT $29;
// void __fastfail(unsigned int code);
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 ;-)

Zitat:

Was wäre eine Systemroutine?
Mit "Systemroutine" meine ich alles was systemmäßig ohne eigenen Code existiert.

paule32.jk 4. Nov 2023 00:41

AW: In Asm-Prozedur eine Exception auslösen
 
Hallo @AmateurProfi

1) zuerst ist mal zu klären, auf welcher Platform Du programmierst:
- Windows ?
- Linux ?

2) dann muss erstmal geklärt werden, welche ABI Architektur Du verwenden willst:
- 32-Bit
- 64-Bit

3) dann muss erstmal geklärt werden, welche Aufrufkonvention Du verwenden willst:
- Pascal (Delphi/FPC) => stdcall
- C/C++ => cdecl (C++ Builder => fastcall)

4) dann muss erstmal geklärt werden, welche Tools, und welche Programmiersprache Du verwenden willst:
- Delphi / FPC
- C++ Builder
- GNU C / C++
...

5) dann muss erstmal geklärt werden, was Du unter Systemroutinen verstehst.

Alles andere ist rumgestochere im kalten Kaffee-Satz.
----

zu 1:
- mein Tipp: Windows für professionelles Arbeiten
- Linux (bastel System)

zu 2:
- 32-Bit ist nicht 64-Bit kompatibel (in einen 32-Bit Process kann keine 64-Bit DLL geladen werden)
- 32-Bit eingeschränkte Datengröße an Speicher (max. 2 ^32 = 3 GiByte verwendbar)

- 64-Bit ist nicht 32-Bit (32-Bit DLL können geladen werden, sind aber wegen der Daten-Größen nicht kompatibel untereinander (8 ist mehr als 4 :))
- Speicher für Programme: 2 hoch 64 = 18 Millionen TerraByte

zu 3:
- jede Programmiersprache hat ihre Eigene Aufruf-Konvention (stdcall oder cdecl)
- DLL Funktionen, die importiert werden, müssen bei Pascal DLL mit stdcall deklariert werden
- DLL Funktionen, die importiert werden, müssen bei C /C++ DLL mit cdecl deklariert werden

zu 4:
- Delphi (kommerziell, kostenlos in der Community Edition, Einschränkungen)
- FPC (kommerziell einsetzbar, aber kostenlos, keine Einschränkungen, Vollversion, mehre Platformen)
- C++ Builder (siehe Delphi, nicht gleichzeitig einsetzbar neben Delphi oder umgekehrt)
- GNU C/C++ (kostenlos, viele Möglichkeiten, IDE fehlt - aber Leistungsstark)

zu 5:
Systemroutinen unter Linux werden mit einer Interrupt-Routine angesprochen. Im Assembler erfolgt dies mit der Anweisung: INT und mit einen zugehörigen nummerischen Wert. Dieser Wert kann zwischen 1 und 255 liegen. Linux verwendet für System-Routinen, die über INT angesprochen den Wert 80 (also INT 80) im 32-Bit Modus. Im 64-Bit Modus wird das Symbol syscall verwendet, um einen SysCall auszulösen.

Unter Windows kannst Du nicht so einfach das gleiche machen, da INT eher etwas von damals, als man noch BIOS unter MS-DOS 16-Bit eingesetzt hat.
Seit der Einführung von 32-Bit sowie 64-Bit, laufen Programme in einen "protected" Modus, in dem die Verwendung von INT nicht mehr ohne weiteres zur Verfügung. Man kann zwar mittels INT 3 einen Abbruch (Interrupt) auslösen - dieser wird aber meist nur zum Debuggen verwendet.
Findet zum Beispiel Windows den Op-Code für INT 3 im Programmcode, wird die entsprechende Windows-Debug-Methode aufgerufen, und das Programm wird an der Stelle an der der Interrupt (Abbruch) ausgelöst wurde, stehen.

Wenn Du neben der win32api, die eine Kapslung zu den internen System-Routinen darstellt, aufrufen willst, dann ist es notwendig, bestimmte .DLL zu laden und Funktionen aus diesen .DLL aufzurufen, da diese einen Schutz-Layer verpasst bekommen haben - den HAL (Hardware Abstract Layer).

- dieser HAL kümmert sich darum, welche Grafikkarten-Auflöse-Modi eingestellt werden soll
- wie ein Fenster in den Speicher gezeichnet wird,
- etc. pp...

Verwendest Du also Interrupts, großer, kleiner als 3, dann stürzt das Programm ab, und windows wird das Dir dann mit einer Meldung quittieren.

Unter Linux wird ein SysCall durch INT 80 ausgelöst.
- EAX ist dann im 32-Bit Modus der erste Parameter.
- dieser Parameter gibt zugleich die Systemroutine an, die aufgerufen wird.
- EAX kann aber auch als allzweck-Register verwendet werden, so dass es nicht selten für den Rückgabe-Wert von Funktionen unter AssemblerLevel eingesetzt wird.

- im 64-Bit Modus ist der erste Parameter: RAX
- hier eine Liste.

hier ein Beispiel für eine Exception:
Code:
%define PREFIX_OPERANDSIZE db 66h

IMAGE_RESOURCE_DATA_IS_DIRECTORY equ 80000000h
PAGE_READWRITE equ 4
ExceptionContinueExecution equ 0

DLL_PROCESS_ATTACH equ 1
DLL_PROCESS_DETACH equ 0

IMAGE_SCN_CNT_CODE              equ 000000020h
IMAGE_SCN_CNT_INITIALIZED_DATA  equ 000000040h
IMAGE_SCN_MEM_SHARED            equ 010000000h
IMAGE_SCN_MEM_EXECUTE           equ 020000000h
IMAGE_SCN_MEM_READ              equ 040000000h
IMAGE_SCN_MEM_WRITE             equ 080000000h

MEM_COMMIT equ 1000h

BREAKPOINT equ 080000003h
SINGLE_STEP equ 80000004h
ACCESS_VIOLATION equ 0c0000005h
INVALID_HANDLE equ 0C0000008h
INVALID_LOCK_SEQUENCE equ 0C000001eh
INTEGER_DIVIDE_BY_ZERO equ 0C0000094h
INTEGER_OVERFLOW equ 0C0000095h
PRIVILEGED_INSTRUCTION equ 0C0000096h

struc exceptionHandler
    .pException resd 1          ; EXCEPTION_RECORD
    .pRegistrationRecord resd 1 ; EXCEPTION_REGISTRATION_RECORD
    .pContext resd 1            ; CONTEXT
endstruc

SIZE_OF_80387_REGISTERS equ 80
MAXIMUM_SUPPORTED_EXTENSION equ 512

struc CONTEXT
    .ContextFlags resd 1
    ;CONTEXT_DEBUG_REGISTERS
    .iDr0          resd 1
    .iDr1          resd 1
    .iDr2          resd 1
    .iDr3          resd 1
    .iDr6          resd 1
    .iDr7          resd 1
    ;CONTEXT_FLOATING_POINT
    .ControlWord  resd 1
    .StatusWord   resd 1
    .TagWord      resd 1
    .ErrorOffset  resd 1
    .ErrorSelector resd 1
    .DataOffset   resd 1
    .DataSelector resd 1
    .RegisterArea resb SIZE_OF_80387_REGISTERS
    .Cr0NpxState  resd 1
    ;CONTEXT_SEGMENTS
    .regGs  resd 1
    .regFs  resd 1
    .regEs  resd 1
    .regDs  resd 1
    ;CONTEXT_INTEGER
    .regEdi resd 1
    .regEsi resd 1
    .regEbx resd 1
    .regEdx resd 1
    .regEcx resd 1
    .regEax resd 1
    ;CONTEXT_CONTROL
    .regEbp resd 1
    .regEip resd 1
    .regCs  resd 1
    .regFlag resd 1
    .regEsp resd 1
    .regSs  resd 1
    ;CONTEXT_EXTENDED_REGISTERS
    .ExtendedRegisters resb MAXIMUM_SUPPORTED_EXTENSION
endstruc

IMAGE_SIZEOF_SHORT_NAME equ 8

struc IMAGE_DOS_HEADER
  .e_magic     resw 1
  .e_cblp      resw 1
  .e_cp        resw 1
  .e_crlc      resw 1
  .e_cparhdr   resw 1
  .e_minalloc  resw 1
  .e_maxalloc  resw 1
  .e_ss        resw 1
  .e_sp        resw 1
  .e_csum      resw 1
  .e_ip        resw 1
  .e_cs        resw 1
  .e_lfarlc    resw 1
  .e_ovno      resw 1
  .e_res       resw 4
  .e_oemid     resw 1
  .e_oeminfo   resw 1
  .e_res2       resw 10
  .e_lfanew    resd 1
endstruc

struc IMAGE_NT_HEADERS
  .Signature        resd 1
; .FileHeader       resb IMAGE_FILE_HEADER_size
; .OptionalHeader   resb IMAGE_OPTIONAL_HEADER32_size
endstruc

struc IMAGE_FILE_HEADER
  .Machine             resw 1
  .NumberOfSections    resw 1
  .TimeDateStamp       resd 1
  .PointerToSymbolTable resd 1
  .NumberOfSymbols     resd 1
  .SizeOfOptionalHeader resw 1
  .Characteristics     resw 1
endstruc

IMAGE_FILE_MACHINE_I386         equ 014ch
IMAGE_FILE_DLL equ 02000h
IMAGE_NT_OPTIONAL_HDR32_MAGIC equ 010bh

struc IMAGE_OPTIONAL_HEADER32
  .Magic                       resw 1
  .MajorLinkerVersion          resb 1
  .MinorLinkerVersion          resb 1
  .SizeOfCode                  resd 1
  .SizeOfInitializedData       resd 1
  .SizeOfUninitializedData     resd 1
  .AddressOfEntryPoint         resd 1
  .BaseOfCode                  resd 1
  .BaseOfData                  resd 1
  .ImageBase                   resd 1
  .SectionAlignment            resd 1
  .FileAlignment               resd 1
  .MajorOperatingSystemVersion resw 1
  .MinorOperatingSystemVersion resw 1
  .MajorImageVersion           resw 1
  .MinorImageVersion           resw 1
  .MajorSubsystemVersion       resw 1
  .MinorSubsystemVersion       resw 1
  .Win32VersionValue           resd 1
  .SizeOfImage                 resd 1
  .SizeOfHeaders               resd 1
  .CheckSum                    resd 1
  .Subsystem                   resw 1
  .DllCharacteristics          resw 1
  .SizeOfStackReserve          resd 1
  .SizeOfStackCommit           resd 1
  .SizeOfHeapReserve           resd 1
  .SizeOfHeapCommit            resd 1
  .LoaderFlags                 resd 1
  .NumberOfRvaAndSizes         resd 1
  .DataDirectory               resb 0
endstruc

struc IMAGE_DATA_DIRECTORY
  VirtualAddress   resd 1
  isize            resd 1
endstruc

struc IMAGE_DATA_DIRECTORY_16
    .ExportsVA       resd 1
    .ExportsSize     resd 1
    .ImportsVA       resd 1
    .ImportsSize     resd 1
    .ResourceVA      resd 1
    .ResourceSize    resd 1
    .Exception       resd 2
    .Security        resd 2
    .FixupsVA        resd 1
    .FixupsSize      resd 1
    .DebugVA         resd 1
    .DebugSize       resd 1
    .Description     resd 2
    .MIPS            resd 2
    .TLSVA           resd 1
    .TLSSize         resd 1
    .Load            resd 2
    .BoundImportsVA  resd 1
    .BoundImportsSize resd 1
    .IATVA           resd 1
    .IATSize         resd 1
    .DelayImportsVA  resd 1
    .DelayImportsSize resd 1
    .COM             resd 2
    .reserved        resd 2
endstruc

struc IMAGE_SECTION_HEADER
    .Name                   resb IMAGE_SIZEOF_SHORT_NAME
    .VirtualSize            resd 1
    .VirtualAddress         resd 1
    .SizeOfRawData          resd 1
    .PointerToRawData       resd 1
    .PointerToRelocations   resd 1
    .PointerToLinenumbers   resd 1
    .NumberOfRelocations    resw 1
    .NumberOfLinenumbers    resw 1
    .Characteristics        resd 1
endstruc


IMAGE_SUBSYSTEM_WINDOWS_CUI   equ 3
IMAGE_SUBSYSTEM_WINDOWS_GUI   equ 2
IMAGE_FILE_RELOCS_STRIPPED        equ 00001h
IMAGE_FILE_EXECUTABLE_IMAGE       equ 00002h
IMAGE_FILE_LINE_NUMS_STRIPPED     equ 00004h
IMAGE_FILE_LOCAL_SYMS_STRIPPED    equ 00008h
IMAGE_FILE_32BIT_MACHINE          equ 00100h

%macro _ 0
    nop
%endmacro

%macro _c 0
    int3
    align 4, int3
%endmacro

%macro _d 0
    db 0
    align 16, db 0
%endmacro


%macro setSEH 1
    push %1
    push dword [fs:0]
    mov [fs:0], esp
%endmacro

%macro clearSEH 0
    pop dword [fs:0]
    add esp, 4
%endmacro

struc IMAGE_OPTIONAL_HEADER64
  .Magic                       resw 1
  .MajorLinkerVersion          resb 1
  .MinorLinkerVersion          resb 1
  .SizeOfCode                  resd 1
  .SizeOfInitializedData       resd 1
  .SizeOfUninitializedData     resd 1
  .AddressOfEntryPoint         resd 1
  .BaseOfCode                  resd 1
  .ImageBase                   resq 1
  .SectionAlignment            resd 1
  .FileAlignment               resd 1
  .MajorOperatingSystemVersion resw 1
  .MinorOperatingSystemVersion resw 1
  .MajorImageVersion           resw 1
  .MinorImageVersion           resw 1
  .MajorSubsystemVersion       resw 1
  .MinorSubsystemVersion       resw 1
  .Win32VersionValue           resd 1
  .SizeOfImage                 resd 1
  .SizeOfHeaders               resd 1
  .CheckSum                    resd 1
  .Subsystem                   resw 1
  .DllCharacteristics          resw 1
  .SizeOfStackReserve          resq 1
  .SizeOfStackCommit           resq 1
  .SizeOfHeapReserve           resq 1
  .SizeOfHeapCommit            resq 1
  .LoaderFlags                 resd 1
  .NumberOfRvaAndSizes         resd 1
  .DataDirectory               resb 0
endstruc

IMAGE_FILE_MACHINE_AMD64        equ 8664h
IMAGE_NT_OPTIONAL_HDR64_MAGIC  equ 020bh

IMAGE_REL_BASED_ABSOLUTE      equ 0 ; used for padding
IMAGE_REL_BASED_HIGH          equ 1
IMAGE_REL_BASED_LOW           equ 2 ; does nothing
IMAGE_REL_BASED_HIGHLOW       equ 3 ;
IMAGE_REL_BASED_HIGHADJ       equ 4 ; takes an argument but actually does nothing
IMAGE_REL_BASED_MIPS_JMPADDR  equ 5 ; until W7 only
IMAGE_REL_BASED_SECTION       equ 6 ; until W7 only ; does nothing anyway
IMAGE_REL_BASED_REL32          equ 7 ; until W7 only ; does nothing anyway
; 8 is always rejected, historically
IMAGE_REL_BASED_MIPS_JMPADDR16 equ 9
IMAGE_REL_BASED_IA64_IMM64     equ 9
IMAGE_REL_BASED_DIR64          equ 10
IMAGE_REL_BASED_HIGH3ADJ      equ 11 ; Win2k only

CR equ 0dh
EOF equ 1ah
LF equ 0ah

struc IMAGE_RESOURCE_DIRECTORY
 .Characteristics        resd 1
 .TimeDateStamp          resd 1
 .MajorVersion           resw 1
 .MinorVersion           resw 1
 .NumberOfNamedEntries   resw 1
 .NumberOfIdEntries      resw 1
endstruc

struc IMAGE_RESOURCE_DIRECTORY_ENTRY
    .NameID resd 1
    .OffsetToData resd 1
endstruc

struc IMAGE_RESOURCE_DATA_ENTRY
    .OffsetToData resd 1
    .Size1        resd 1
    .CodePage    resd 1
    .Reserved    resd 1
endstruc

struc _IMAGE_DELAY_IMPORT_DESCRIPTOR
    .grAttrs      resd 1  ; attributes
    .rvaDLLName   resd 1  ; RVA to dll name
    .rvaHmod      resd 1  ; RVA of module handle
    .rvaIAT       resd 1  ; RVA of the IAT
    .rvaINT       resd 1  ; RVA of the INT
    .rvaBoundIAT  resd 1  ; RVA of the optional bound IAT
    .rvaUnloadIAT resd 1  ; RVA of optional copy of original IAT
    .dwTimeStamp  resd 1  ; 0 if not bound
endstruc

struc TRUNC_OPTIONAL_HEADER32
  .Magic                       resw 1
  .MajorLinkerVersion          resb 1
  .MinorLinkerVersion          resb 1
  .SizeOfCode                  resd 1
  .SizeOfInitializedData       resd 1
  .SizeOfUninitializedData     resd 1
  .AddressOfEntryPoint         resd 1
  .BaseOfCode                  resd 1
  .BaseOfData                  resd 1
  .ImageBase                   resd 1
  .SectionAlignment            resd 1
  .FileAlignment               resd 1
  .MajorOperatingSystemVersion resw 1
  .MinorOperatingSystemVersion resw 1
  .MajorImageVersion           resw 1
  .MinorImageVersion           resw 1
  .MajorSubsystemVersion       resw 1
  .MinorSubsystemVersion       resw 1
  .Win32VersionValue           resd 1
  .SizeOfImage                 resd 1
  .SizeOfHeaders               resd 1
  .CheckSum                    resd 1
  .Subsystem                   resb 1  ; truncated as a byte
  ; no more data
endstruc

struc VS_FIXEDFILEINFO
  .dwSignature          resd 1
  .dwStrucVersion       resd 1
  .dwFileVersionMS      resd 1
  .dwFileVersionLS      resd 1
  .dwProductVersionMS   resd 1
  .dwProductVersionLS   resd 1
  .dwFileFlagsMask      resd 1
  .dwFileFlags          resd 1
  .dwFileOS             resd 1
  .dwFileType           resd 1
  .dwFileSubtype        resd 1
  .dwFileDateMS         resd 1
  .dwFileDateLS         resd 1
endstruc

CREATEPROCESS_MANIFEST_RESOURCE_ID EQU 1
ISOLATIONAWARE_MANIFEST_RESOURCE_ID EQU 2
ISOLATIONAWARE_NOSTATICIMPORT_MANIFEST_RESOURCE_ID EQU 3


struc ACTCTX                      ; typedef struct tagACTCTX {
.cbSize resd 1                     ;  ULONG  cbSize;
.dwFlags resd 1                    ;  DWORD  dwFlags;
.lpSource resd 1                   ;  LPCWSTR lpSource;
.wProcessorArchitecture resw 1     ;  USHORT wProcessorArchitecture;
.wLangId resw 1                    ;  LANGID wLangId;
.lpAssemblyDirectory resd 1        ;  LPCTSTR lpAssemblyDirectory;
.lpResourceName resd 1             ;  LPCTSTR lpResourceName;
.lpApplicationName resd 1          ;  LPCTSTR lpApplicationName;
.hModule resd 1                    ;  HMODULE hModule;
endstruc                          ; } ACTCTX, *PACTCTX;

ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID equ 1
ACTCTX_FLAG_LANGID_VALID equ 2
ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID equ 4
ACTCTX_FLAG_RESOURCE_NAME_VALID equ 8
ACTCTX_FLAG_SET_PROCESS_DEFAULT equ 16
ACTCTX_FLAG_APPLICATION_NAME_VALID equ 32
ACTCTX_FLAG_HMODULE_VALID equ 128

; widechar string macro
%macro WIDE 1
%assign %%__i 1
%strlen %%__len %1
%rep %%__len
   %substr %%__c %1 %%__i
      db %%__c
      db 0
   %assign %%__i %%__i + 1
%endrep
   db 0, 0
%endmacro

%macro _widestr_no0 1
%assign %%__i 1
%strlen %%__len %1
%rep %%__len
   %substr %%__c %1 %%__i
      db %%__c
      db 0
   %assign %%__i %%__i + 1
%endrep
%endmacro

%macro __string 2
%%string:
dw %%SLEN
dw %%VALLEN / 2 ; dammit !
dw 1 ; text type
WIDE %1
   align 4, db 0
%%val:
   WIDE %2
   %%VALLEN equ $ - %%val
   align 4, db 0
%%SLEN equ $ - %%string
%endmacro


struc RUNTIME_FUNCTION
    .FunctionStart resd 1
    .FunctionEnd  resd 1
    .UnwindInfo   resd 1
endstruc

struc UNWIND_INFO
    .Ver3_Flags    resb 1 ; versions and flags
    .PrologSize    resb 1
    .CntUnwindCodes resb 1
    .FrReg_FrRegOff resb 1 ; frame register and offsets
    ; dd ExceptionHandler or FunctionEntry
    ; ExceptionData
endstruc

struc UNWIND_CODE
    .PrologOff    resb 1
    .OpCode_OpInfo resb 1 ; operation code and info
endstruc

UNW_FLAG_EHANDLER equ 1

struc IMAGE_DEBUG_DIRECTORY
    .Characteristics resd 1
    .TimeDateStamp   resd 1
    .MajorVersion    resw 1
    .MinorVersion    resw 1
    .Type            resd 1
    .SizeOfData      resd 1
    .AddressOfRawData resd 1
    .PointerToRawData resd 1
endstruc

IMAGE_DEBUG_TYPE_COFF equ 1
IMAGE_DEBUG_TYPE_CODEVIEW equ 2
IMAGE_DEBUG_TYPE_MISC equ 4

SYMOPT_DEBUG equ 080000000h

struc IMAGE_EXPORT_DIRECTORY
    .Characteristics      resd 1
    .TimeDateStamp        resd 1
    .MajorVersion         resw 1
    .MinorVersion         resw 1
    .nName                resd 1
    .nBase                resd 1
    .NumberOfFunctions    resd 1
    .NumberOfNames        resd 1
    .AddressOfFunctions   resd 1
    .AddressOfNames       resd 1
    .AddressOfNameOrdinals resd 1
endstruc

struc IMAGE_IMPORT_DESCRIPTOR
    .OriginalFirstThunk resd 1 ; Characteristics
    .TimeDateStamp     resd 1
    .ForwarderChain    resd 1
    .Name1              resd 1
    .FirstThunk        resd 1
endstruc

%macro _import_descriptor 1
istruc IMAGE_IMPORT_DESCRIPTOR
    at IMAGE_IMPORT_DESCRIPTOR.OriginalFirstThunk, dd %1_hintnames - IMAGEBASE
    at IMAGE_IMPORT_DESCRIPTOR.Name1             , dd %1 - IMAGEBASE
    at IMAGE_IMPORT_DESCRIPTOR.FirstThunk       , dd %1_iat - IMAGEBASE
iend
%endmacro

struc IMAGE_LOAD_CONFIG_DIRECTORY32
    .Size                          resd 1
    .TimeDateStamp                 resd 1
    .MajorVersion                  resw 1
    .MinorVersion                  resw 1
    .GlobalFlagsClear              resd 1
    .GlobalFlagsSet                resd 1
    .CriticalSectionDefaultTimeout resd 1
    .DeCommitFreeBlockThreshold    resd 1
    .DeCommitTotalFreeThreshold    resd 1
    .LockPrefixTable               resd 1 ; VA
    .MaximumAllocationSize         resd 1
    .VirtualMemoryThreshold        resd 1
    .ProcessHeapFlags              resd 1
    .ProcessAffinityMask           resd 1
    .CSDVersion                    resw 1
    .Reserved1                      resw 1
    .EditList                      resd 1 ; VA
    .SecurityCookie                resd 1 ; VA
    .SEHandlerTable                resd 1 ; VA
    .SEHandlerCount                resd 1
    .GuardCFCheckFunctionPointer   resd 1 ; VA
    .Reserved2                      resd 1
    .GuardCFFunctionTable          resd 1 ; VA
    .GuardCFFunctionCount          resd 1
    .GuardFlags                    resd 1
endstruc

struc IMAGE_LOAD_CONFIG_DIRECTORY64
    .Size                          resd 1
    .TimeDateStamp                 resd 1
    .MajorVersion                  resw 1
    .MinorVersion                  resw 1
    .GlobalFlagsClear              resd 1
    .GlobalFlagsSet                resd 1
    .CriticalSectionDefaultTimeout resd 1
    .DeCommitFreeBlockThreshold    resq 1
    .DeCommitTotalFreeThreshold    resq 1
    .LockPrefixTable               resq 1 ; VA
    .MaximumAllocationSize         resq 1
    .VirtualMemoryThreshold        resq 1
    .ProcessAffinityMask           resq 1
    .ProcessHeapFlags              resd 1
    .CSDVersion                    resw 1
    .Reserved1                      resw 1
    .EditList                      resq 1 ; VA
    .SecurityCookie                resq 1 ; VA
    .SEHandlerTable                resq 1 ; VA
    .SEHandlerCount                resq 1
    .GuardCFCheckFunctionPointer   resq 1 ; VA
    .Reserved2                      resq 1
    .GuardCFFunctionTable          resq 1 ; VA
    .GuardCFFunctionCount          resq 1
    .GuardFlags                    resd 1
endstruc

RT_ICON      equ 3
RT_STRING    equ 6
RT_GROUP_ICON equ 14
RT_VERSION   equ 16
RT_MANIFEST  equ 24

struc GRPICONDIR
    .idReserved resw 1 ; always 0 - enforced
    .idType    resw 1 ; always 1 for icons
    .idCount   resw 1
endstruc

struc GRPICONDIRENTRY
    .bWidth      resb 1
    .bHeight     resb 1
    .bColorCount resb 1
    .bReserved   resb 1
    .wPlanes     resw 1
    .wBitCount   resw 1
    .dwBytesInRes resd 1
    .nId         resw 1
endstruc

%macro _resourceDirectoryEntry 2
istruc IMAGE_RESOURCE_DIRECTORY_ENTRY
    at IMAGE_RESOURCE_DIRECTORY_ENTRY.NameID, dd %1
    at IMAGE_RESOURCE_DIRECTORY_ENTRY.OffsetToData, dd IMAGE_RESOURCE_DATA_IS_DIRECTORY | (%2 - Directory_Entry_Resource)
iend
%endmacro

%macro _resource_tree 3 ; ID, Offset, Size
istruc IMAGE_RESOURCE_DIRECTORY
    at IMAGE_RESOURCE_DIRECTORY.NumberOfIdEntries, dw 1
iend
istruc IMAGE_RESOURCE_DIRECTORY_ENTRY
    at IMAGE_RESOURCE_DIRECTORY_ENTRY.NameID, dd %1
    at IMAGE_RESOURCE_DIRECTORY_ENTRY.OffsetToData, dd IMAGE_RESOURCE_DATA_IS_DIRECTORY | (%%language - Directory_Entry_Resource)
iend

%%language:
istruc IMAGE_RESOURCE_DIRECTORY
    at IMAGE_RESOURCE_DIRECTORY.NumberOfIdEntries, dw 1
iend
istruc IMAGE_RESOURCE_DIRECTORY_ENTRY
    ; language doesn't matter
    at IMAGE_RESOURCE_DIRECTORY_ENTRY.OffsetToData, dd %%entry - Directory_Entry_Resource
iend

%%entry:
istruc IMAGE_RESOURCE_DATA_ENTRY
    at IMAGE_RESOURCE_DATA_ENTRY.OffsetToData, dd %2 - IMAGEBASE
    at IMAGE_RESOURCE_DATA_ENTRY.Size1, dd %3
iend
%endmacro

RichKey EQU 092033d19h

struc IMAGE_TLS_DIRECTORY32
    .StartAddressOfRawData resd 1
    .EndAddressOfRawData  resd 1
    .AddressOfIndex       resd 1
    .AddressOfCallBacks   resd 1
    .SizeOfZeroFill       resd 1
    .Characteristics      resd 1
endstruc

struc IMAGE_TLS_DIRECTORY64
    .StartAddressOfRawData resq 1
    .EndAddressOfRawData  resq 1
    .AddressOfIndex       resq 1
    .AddressOfCallBacks   resq 1
    .SizeOfZeroFill       resd 1
    .Characteristics      resd 1
endstruc

struc IMAGE_BOUND_IMPORT_DESCRIPTOR
    .TimeDateStamp               resd 1
    .OffsetModuleName            resw 1
    .NumberOfModulesForwarderRefs resw 1
endstruc

struc WIN_CERTIFICATE
    .dwLength        resd 1
    .wRevision       resw 1
    .wCertificateType resw 1
    .bCertificate    resb 0
endstruc

struc IMAGE_BASE_RELOCATION
    .VirtualAddress resd 1
    .SizeOfBlock   resd 1
endstruc

; can't make a struct of that one with Yasm :(
%macro _IMAGE_IMPORT_BY_NAME 1
    .Hint  dw 0
    .Name  db %1, 0
%endmacro

IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE   equ 0040h
IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY equ 0080h
IMAGE_DLLCHARACTERISTICS_NX_COMPAT      equ 0100h
IMAGE_DLLCHARACTERISTICS_NO_SEH         equ 0400h
IMAGE_DLLCHARACTERISTICS_APPCONTAINER   equ 1000h ; W8
IMAGE_DLLCHARACTERISTICS_GUARD_CF       equ 4000h ; W8.1

FLG_SHOW_LDR_SNAPS equ 2

MB_OK          equ 00000000h
MB_ICONASTERISK equ 00000040h
MB_APPLMODAL   equ 00000000h

LOAD_LIBRARY_AS_DATAFILE equ 000000002h

IMAGE_GUARD_CF_INSTRUMENTED          equ 000000100h ;Module performs control flow integrity checks using system-supplied support
IMAGE_GUARD_CFW_INSTRUMENTED         equ 000000200h ;Module performs control flow and write integrity checks
IMAGE_GUARD_CF_FUNCTION_TABLE_PRESENT equ 000000400h ;Module contains valid control flow target metadata
IMAGE_GUARD_SECURITY_COOKIE_UNUSED   equ 000000800h ;Module does not make use of the /GS security cookie

COOKIE_DEFAULT equ 0bb40e64eh


IMAGEBASE equ 400000h
org IMAGEBASE
bits 32

SECTIONALIGN equ 1000h
FILEALIGN equ 200h

istruc IMAGE_DOS_HEADER
    at IMAGE_DOS_HEADER.e_magic, db 'MZ'
    at IMAGE_DOS_HEADER.e_lfanew, dd NT_Headers - IMAGEBASE
iend

NT_Headers:
istruc IMAGE_NT_HEADERS
    at IMAGE_NT_HEADERS.Signature, db 'PE', 0, 0
iend
istruc IMAGE_FILE_HEADER
    at IMAGE_FILE_HEADER.Machine,             dw IMAGE_FILE_MACHINE_I386
    at IMAGE_FILE_HEADER.NumberOfSections,    dw NUMBEROFSECTIONS
    at IMAGE_FILE_HEADER.SizeOfOptionalHeader, dw SIZEOFOPTIONALHEADER
    at IMAGE_FILE_HEADER.Characteristics,     dw IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_32BIT_MACHINE
iend

OptionalHeader:
istruc IMAGE_OPTIONAL_HEADER32
    at IMAGE_OPTIONAL_HEADER32.Magic,                dw IMAGE_NT_OPTIONAL_HDR32_MAGIC
    at IMAGE_OPTIONAL_HEADER32.AddressOfEntryPoint,  dd EntryPoint - IMAGEBASE
    at IMAGE_OPTIONAL_HEADER32.ImageBase,            dd IMAGEBASE
    at IMAGE_OPTIONAL_HEADER32.SectionAlignment,     dd SECTIONALIGN
    at IMAGE_OPTIONAL_HEADER32.FileAlignment,        dd FILEALIGN
    at IMAGE_OPTIONAL_HEADER32.MajorSubsystemVersion, dw 4
    at IMAGE_OPTIONAL_HEADER32.SizeOfImage,          dd 2 * SECTIONALIGN
    at IMAGE_OPTIONAL_HEADER32.SizeOfHeaders,        dd SIZEOFHEADERS
    at IMAGE_OPTIONAL_HEADER32.Subsystem,            dw IMAGE_SUBSYSTEM_WINDOWS_CUI
    at IMAGE_OPTIONAL_HEADER32.DllCharacteristics,   dw IMAGE_DLLCHARACTERISTICS_NO_SEH ; <===
    at IMAGE_OPTIONAL_HEADER32.NumberOfRvaAndSizes,  dd 16
iend

istruc IMAGE_DATA_DIRECTORY_16
    at IMAGE_DATA_DIRECTORY_16.ImportsVA, dd Import_Descriptor - IMAGEBASE
iend

SIZEOFOPTIONALHEADER equ $ - OptionalHeader
SectionHeader:
istruc IMAGE_SECTION_HEADER
    at IMAGE_SECTION_HEADER.VirtualSize,     dd 1 * SECTIONALIGN
    at IMAGE_SECTION_HEADER.VirtualAddress,  dd 1 * SECTIONALIGN
    at IMAGE_SECTION_HEADER.SizeOfRawData,   dd 1 * FILEALIGN
    at IMAGE_SECTION_HEADER.PointerToRawData, dd 1 * FILEALIGN
    at IMAGE_SECTION_HEADER.Characteristics, dd IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_WRITE
iend
NUMBEROFSECTIONS equ ($ - SectionHeader) / IMAGE_SECTION_HEADER_size
SIZEOFHEADERS equ $ - IMAGEBASE

section progbits vstart=IMAGEBASE + SECTIONALIGN align=FILEALIGN


EntryPoint:
    push Msg
    call [__imp__printf]
    add esp, 1 * 4

    push VEHHandler
    push -1
    call [__imp__AddVectoredExceptionHandler]

    push SEHHandler
    push dword [fs:0]
    mov [fs:0], esp

    int3
_c

SEHHandler:
    push SEHMsg
    call [__imp__printf]
    add esp, 1 * 4
_
    push 1
    call [__imp__ExitProcess]
_c

VEHHandler:
    push VEHMsg
    call [__imp__printf]
    add esp, 1 * 4
_
    push 2
    call [__imp__ExitProcess]
_c

SEHMsg db " # Structured Exception handler triggered", 0ah, 0
VEHMsg db " # Vectored Exception handler triggered", 0ah, 0
Msg db " * a PE with DllCharacteristics set to NO_SEH, but using a Vectored Exception Handler", 0ah, 0
_d

Import_Descriptor:
istruc IMAGE_IMPORT_DESCRIPTOR
    at IMAGE_IMPORT_DESCRIPTOR.OriginalFirstThunk, dd kernel32.dll_hintnames - IMAGEBASE
    at IMAGE_IMPORT_DESCRIPTOR.Name1,             dd kernel32.dll - IMAGEBASE
    at IMAGE_IMPORT_DESCRIPTOR.FirstThunk,        dd kernel32.dll_iat - IMAGEBASE
iend
istruc IMAGE_IMPORT_DESCRIPTOR
    at IMAGE_IMPORT_DESCRIPTOR.OriginalFirstThunk, dd msvcrt.dll_hintnames - IMAGEBASE
    at IMAGE_IMPORT_DESCRIPTOR.Name1,             dd msvcrt.dll - IMAGEBASE
    at IMAGE_IMPORT_DESCRIPTOR.FirstThunk,        dd msvcrt.dll_iat - IMAGEBASE
iend
istruc IMAGE_IMPORT_DESCRIPTOR
iend
_d

kernel32.dll_hintnames dd hnExitProcess - IMAGEBASE, hnAddVectoredExceptionHandler - IMAGEBASE, 0
msvcrt.dll_hintnames  dd hnprintf - IMAGEBASE, 0
_d

hnExitProcess                _IMAGE_IMPORT_BY_NAME 'ExitProcess'
hnAddVectoredExceptionHandler _IMAGE_IMPORT_BY_NAME 'AddVectoredExceptionHandler'
hnprintf                     _IMAGE_IMPORT_BY_NAME 'printf'
_d

kernel32.dll_iat:
__imp__ExitProcess                dd hnExitProcess - IMAGEBASE
__imp__AddVectoredExceptionHandler dd hnAddVectoredExceptionHandler - IMAGEBASE
    dd 0

msvcrt.dll_iat:
__imp__printf dd hnprintf - IMAGEBASE
    dd 0
_d

kernel32.dll db 'kernel32.dll', 0
msvcrt.dll db 'msvcrt.dll', 0
_d

align FILEALIGN, db 0
Hope this helps

jaenicke 4. Nov 2023 04:26

AW: In Asm-Prozedur eine Exception auslösen
 
Diese Fragen waren doch alle schon mit der Fragestellung klar.
1. Es handelt sich um Windows, denn gezeigt wurde 32-Bit Assembler Code. Den unterstützt Delphi nur unter Windows (macos geht nur mit 64-Bit, Assembler unter iOS und Android gar nicht).
2. 32-Bit, wie man am Code sehen kann.
3. Was spielt das hier für eine Rolle? Es geht ja gerade darum, keine eigene Funktion zu nutzen, sondern die Systemfunktionen.
4. Delphi... wie man am Quelltext sieht.
5. Alle Routinen, die Delphi selbst in der RTL bereit stellt. Eben hier vor allem die aus der Unit System.

Du hast dir sicher viel Mühe mit deinem Post gegeben, aber er geht leider komplett am Thema vorbei.

Amateurprofi 4. Nov 2023 04:52

AW: In Asm-Prozedur eine Exception auslösen
 
Zitat:

Zitat von jaenicke (Beitrag 1529023)
Diese Fragen waren doch alle schon mit der Fragestellung klar.
1. Es handelt sich um Windows, denn gezeigt wurde 32-Bit Assembler Code. Den unterstützt Delphi nur unter Windows (macos geht nur mit 64-Bit, Assembler unter iOS und Android gar nicht).
2. 32-Bit, wie man am Code sehen kann.
3. Was spielt das hier für eine Rolle? Es geht ja gerade darum, keine eigene Funktion zu nutzen, sondern die Systemfunktionen.
4. Delphi... wie man am Quelltext sieht.
5. Alle Routinen, die Delphi selbst in der RTL bereit stellt. Eben hier vor allem die aus der Unit System.

Du hast dir sicher viel Mühe mit deinem Post gegeben, aber er geht leider komplett am Thema vorbei.

Danke.

Amateurprofi 4. Nov 2023 05:08

AW: In Asm-Prozedur eine Exception auslösen
 
@paule32.jk
Danke für die Mühe, die Du Dir gegeben hast.
Aber: Alles was jaenicke in #15 schrieb.

Zitat:

Hope this helps
Nein.
Hilfreich wäre ein Einzeiler der meine Frage
Zitat:

wie kann ich das in eigenen Assembler-Routinen realisieren?
beantwortet, also:
Code:
  mov  eax,????

Kas Ob. 4. Nov 2023 08:29

AW: In Asm-Prozedur eine Exception auslösen
 
Zitat:

Zitat von Amateurprofi (Beitrag 1529016)
@Kas Ob.
Thanks for your detailed comments in #8.
Unfortunately not was I am looking for, because I dont want to call procedures outside of my Asm-Procedure (except system-routines).

What I am currently using is the following:

Delphi-Quellcode:
PROCEDURE RaiseException(const S:String);
begin
   raise Exception.Create(S);
end;
Delphi-Quellcode:
PROCEDURE Test;
const S:String='My Message';
asm
   {$IFDEF CPUX86}
   mov  eax,S
   {$ELSE}
   mov  rcx,S
   {$ENDIF}
   jmp  RaiseException
end;

Thank you for clarifying and sorry if i wasn't clear enough.
Delphi assembler has very limited capability, eg. that is why you have to declare constant strings to be used with the assembler with typed strings.

My function above "ExceptionAsm32" is the closest thing you can do with assembly to create and raise exception without writing very complex and unreliable assembly code for Delphi assembler, because it is inconsistent not allow you to get or access specific types, VMT, offsets..etc

Zitat:

Zitat von Amateurprofi (Beitrag 1529025)
beantwortet, also:
Code:
  mov  eax,????

That i had answered , if you don't need to declare your own (or will not multiple ) then replace TMyException with the default Exception.
Code:
const
  pMyExClass: ExceptClass = (TMyException);
  ..
asm
  ..
  mov   eax, pMyExClass; // <-----
That way you can use multiple exception from asm block, only i use create because there is no way or at least no way i know to access the default constructor with compiler help, your assembly can't have the default constructor index to call Create directly for specific class.

ps: about this
Zitat:

Zitat von Amateurprofi (Beitrag 1529016)
Delphi-Quellcode:
PROCEDURE Test;
const S:String='My Message';
asm
   {$IFDEF CPUX86}
   mov  eax,S
   {$ELSE}
   mov  rcx,S
   {$ENDIF}
   jmp  RaiseException
end;

I am against using jmp to raise exception, this will prevent one push on the stack which might leads to whole different story and confusion, just use call, the more code addresses on the stack the safer for OS to rewind correctly, see, when the system will unwind it might not see your that Test procedure at all and will report the caller to Test as the exception raiser.

paule32.jk 4. Nov 2023 08:48

AW: In Asm-Prozedur eine Exception auslösen
 
ich weiß gerade nicht, was IHR so an der Fragestellung versteht, was ich nicht verstehe...
Für mich (und was der Fragestellende gepostet hat, ist, das er mittels Einzeiler eine Exception bzw. eine System-Routine aufrufen will, OHNE viel Delphi zu verwenden.

Einfach einen Einzeiler Assembler mittels inline Code zu realisieren geht halt nicht, weil IHR schon geschrieben habt, das eine Instanz zu einer Exception Klasse vorliegen muss.
Klassen werden intern in einer virtuellen Tabelle aufgezeichnet, die dann auch Einsprung-Addressen für die Routinen speichert.

Man kann zwar einen einen Einzeiler Delphi Code schreiben - raise EException.Create('message');
und wie man hier schon erkennen kann, wird "Create" dafür benutzt, eine Instanz zu erstellen.

Aber in Assembler ist das recht aufwendiger und man kann nicht einfach Assembler-Code übernehmen, nur weil man denkt, das der finktionieren würde...
Mit Create werden auch andere Dinge "vorbereitet" Stack-Segment abgebaut, damit es keinen Überlauf-Fehler gibt und und und...

OOP Programmierung, wie man die unter Delphi betreibt, ist halt keine direkte funktionale Programmierung, so dass man nicht einfach wie bei RECORDS, einfach mal so in eine Klassen-Struktur irgendwelche Daten reinpumpen kann...

Aus den genannten und sicherlich aich bekannten Gründen, habe ich ein funktionales Beispiel in Assembler beigefügt, im meinen letzten Posting. Ich weiß jetzt nicht inwiefern IHR Euch das angeschaut habt: aber es soll zeigen, das mehr als nur ein Einzeiler nötig ist, um einen Exception-Handdler aufzurufen.

Wenn IHR das nicht verstehen könnt oder wollt, ist das nicht meine Schuld ...

Und unter uns:
man kann den Code, den ich Euch vorgelegt habe auch dazu nutzen, Einen Exception-Handler aufzurufen.
Dazu kann man ihn in inline Assembler einbetten und dann als Funktion einzeln aufrufen, oder als Objekt-Datei einbinden (dann sind aber wieder Aufrufkonventionen zu beachten, falls Parameter übergeben werden sollen)...

Ich habe jetzt keinen Delphi-Dissambler gefunden, aber hier mal an Hand von C++
C++ Exception per TRY CATCH

jaenicke 4. Nov 2023 09:41

AW: In Asm-Prozedur eine Exception auslösen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von Amateurprofi (Beitrag 1529016)
@Kas Ob.
Thanks for your detailed comments in #8.
Unfortunately not was I am looking for, because I dont want to call procedures outside of my Asm-Procedure (except system-routines).

Hattest du diesen Teil seines Codes übersehen?
Zitat:

Zitat von Kas Ob. (Beitrag 1528955)
Here a simple code that will work for 32bit
Code:
//[..]
procedure ExceptionAsm32;
const
  pMyExClass: ExceptClass = (TMyException);
  LocalExceptionMsg : string = 'Error from Assembly';
asm
  mov    edx, LocalExceptionMsg
  mov    eax, pMyExClass
  Call   GetException
  Call   system.@RaiseExcept
end;

Zitat:

Zitat von paule32.jk (Beitrag 1529028)
Einfach einen Einzeiler Assembler mittels inline Code zu realisieren geht halt nicht, weil IHR schon geschrieben habt, das eine Instanz zu einer Exception Klasse vorliegen muss.

Klaus hat doch schon in seinem Eingangspost den notwendigen Assemblercode gepostet. Die einzige Frage war, wie er nun EAX korrekt befüllen muss. Die Lösung hatte Kas Ob. ja auch schon gepostet.

Zitat:

Zitat von paule32.jk (Beitrag 1529028)
Ich habe jetzt keinen Delphi-Dissambler gefunden

Delphi?
Anhang 56396

Amateurprofi 5. Nov 2023 02:37

AW: In Asm-Prozedur eine Exception auslösen
 
@jaenicke
Zitat:

Hattest du diesen Teil seines Codes übersehen?
Nein, aber ich habe nicht gleich realisiert, dass das die Lösung sein könnte.
Danke für den Hinweis, werde mich im Laufe des Tages darum kümmern, jetzt erstmal 2-3 Stunden schlafen.

Amateurprofi 5. Nov 2023 07:52

AW: In Asm-Prozedur eine Exception auslösen
 
@Paule32.jk
Zitat:

ich weiß gerade nicht, was IHR so an der Fragestellung versteht, was ich nicht verstehe...
Für mich (und was der Fragestellende gepostet hat, ist, das er mittels Einzeiler eine Exception bzw. eine System-Routine aufrufen will, OHNE viel Delphi zu verwenden.
Wo habe ich denn geschrieben, dass ich "mittels Einzeiler eine Exception bzw. eine System-Routine aufrufen will" ?

Amateurprofi 5. Nov 2023 08:11

AW: In Asm-Prozedur eine Exception auslösen
 
Zitat:

Zitat von Amateurprofi (Beitrag 1529053)
@jaenicke
Zitat:

Hattest du diesen Teil seines Codes übersehen?
Nein, aber ich habe nicht gleich realisiert, dass das die Lösung sein könnte.
Danke für den Hinweis, werde mich im Laufe des Tages darum kümmern, jetzt erstmal 2-3 Stunden schlafen.

@jaenicke
So, bin wieder da.
Hab mir das angeschaut und mir ist auch wieder eingefallen, was mich gestört hatte, nämlich der Aufruf der Pascal-Routine "GetException", die außerhalb des Asm-Blocks liegt, was ich ja gerade vermeiden wollte.
Nach näherer Betrachtung ließ sich das aber leicht beheben.
Die nachstehende Prozedur funktioniert unter 32Bit, nicht aber unter 64Bit (Wie Kas Ob. auch schon deutlich machte).
Wäre schön, wenn da noch einmal jemand, der das durchschaut, reinschauen könnte.
Delphi-Quellcode:
PROCEDURE Test;
const
   pExClass:ExceptClass=(Exception);
   sErr:String='Meine Meldung';
asm
   {$IfDef CPUX86}
   mov  ecx,sErr
   mov  dl,1
   mov  eax,pExClass
   call Exception.Create
   call System.@RaiseExcept
   {$Else}
   mov  r8,sErr
   mov  dl,$01
   mov  rcx,pExClass
   call Exception.Create // Scheint zu funktionieren
   mov  rcx,rax
   call System.@RaiseExcept // Hier krachts. "ACCESS VIOLATION"
   {$EndIf}
end;

Kas Ob. 5. Nov 2023 10:22

AW: In Asm-Prozedur eine Exception auslösen
 
I am trying here to explain and language barrier is playing huge role.

This will work on x64 for this exact procedure
Code:
PROCEDURE test;
const
   pExClass:ExceptClass=( Exception );
   sErr:String=' My message ';
asm
    {$IfDef CPUX86}
   mov ecx,sErr
   mov dl ,1
   mov eax,pExClass
   call Exception .Create
   call System.@RaiseExcept
   {$Else}
   push rbp
   sub rsp,$20
   mov rbp,rsp
   mov r8,sErr
   mov dl ,$01
   mov rcx,pExClass
   call Exception .Create // Seems to work
   mov rcx,rax
   call System.@RaiseExcept // Here it crashes. " ACCESS VIOLATION"
   lea rsp,[rbp+$20]
   pop rbp
   pop rbp
   {$EndIf}
end ;
BUT will fail on many other places and different situations or for just little more complex assembly above that system.@RaiseExcept !!!

The reasoning : i put a frame stack for it and so it worked, now if your assembly is using variables or utilizing the stack or even the compiler went ahead and added a frame on its own to build right assembly, we will end up with double frame and whole different mess and that solution become broken again and you should remove that stack i introduced, this is one hand on other hand this can't be guaranteed to be working on future compiler, tested it on XE8 and your test procedure and it is raising stack overflow on my machine not an access violation!
That why i moved the raising call to its own pascal procedure, this guaranteed to have right frame stack and the compiler will handle it right, as i said that in my humble opinion and according to my experience this is the closest for assembly to raise an exception without braking things every time you modify your assembly and guaranteed to be working on different compilers including future ones, also will not send tools like EurekaLog after witch hunting!

I hope that is clear.

ps : this was a good question and might help many who interested.

Kas Ob. 5. Nov 2023 10:32

AW: In Asm-Prozedur eine Exception auslösen
 
OK, there much to say about this but really i don't like write essays :stupid:

You can force the compiler to not introduce a stack frame by using .noframe in the x64 assembly block.

so the code can be like this
Code:
PROCEDURE test;
const
   pExClass : ExceptClass = (Exception);
   sErr : String = ' My message ';
asm
    {$IfDef CPUX86}
   mov ecx,sErr
   mov dl ,1
   mov eax,pExClass
   call Exception .Create
   call System.@RaiseExcept
   {$Else}
   .noframe            //  crucial here
   push rbp
   sub rsp,$20
   mov rbp,rsp
   mov r8,sErr
   mov dl ,$01
   mov rcx,pExClass
   call Exception .Create
   mov rcx,rax
   call System.@RaiseExcept
   lea rsp,[rbp+$20]
   pop rbp
   {$EndIf}
end ;
Yet again, use that on your risk !

Edit: to fix an extra pop useless in that example but will cause problem in real life code.

Amateurprofi 6. Nov 2023 05:45

AW: In Asm-Prozedur eine Exception auslösen
 
Zitat:

Zitat von Kas Ob. (Beitrag 1529058)
I am trying here to explain and language barrier is playing huge role.

This will work on x64 for this exact procedure
Code:
PROCEDURE test;
const
   pExClass:ExceptClass=( Exception );
   sErr:String=' My message ';
asm
    {$IfDef CPUX86}
   mov ecx,sErr
   mov dl ,1
   mov eax,pExClass
   call Exception .Create
   call System.@RaiseExcept
   {$Else}
   push rbp
   sub rsp,$20
   mov rbp,rsp
   mov r8,sErr
   mov dl ,$01
   mov rcx,pExClass
   call Exception .Create // Seems to work
   mov rcx,rax
   call System.@RaiseExcept // Here it crashes. " ACCESS VIOLATION"
   lea rsp,[rbp+$20]
   pop rbp
   pop rbp
   {$EndIf}
end ;
BUT will fail on many other places and different situations or for just little more complex assembly above that system.@RaiseExcept !!!

The reasoning : i put a frame stack for it and so it worked, now if your assembly is using variables or utilizing the stack or even the compiler went ahead and added a frame on its own to build right assembly, we will end up with double frame and whole different mess and that solution become broken again and you should remove that stack i introduced, this is one hand on other hand this can't be guaranteed to be working on future compiler, tested it on XE8 and your test procedure and it is raising stack overflow on my machine not an access violation!
That why i moved the raising call to its own pascal procedure, this guaranteed to have right frame stack and the compiler will handle it right, as i said that in my humble opinion and according to my experience this is the closest for assembly to raise an exception without braking things every time you modify your assembly and guaranteed to be working on different compilers including future ones, also will not send tools like EurekaLog after witch hunting!

I hope that is clear.

ps : this was a good question and might help many who interested.

Thank you, Kas Ob.
Funny thing.
Just before entering the DP I looked, how

Delphi-Quellcode:
PROCEDURE TestRaise;
const sErr:String='Meine Meldung';
begin
   raise Exception.Create(sErr);
end;
is translated to asm, found the following

Code:
FS_Main.pas.5041: begin
00000000005D3070 55               push rbp
00000000005D3071 4883EC20         sub rsp,$20
00000000005D3075 488BEC          mov rbp,rsp
FS_Main.pas.5042: raise Exception.Create(sErr);
00000000005D3078 488B0D4901E5FF  mov rcx,[rel $ffe50149]
00000000005D307F B201             mov dl,$01
00000000005D3081 4C8B0500460300   mov r8,[rel $00034600]
00000000005D3088 E81307E6FF      call Exception.Create
00000000005D308D 4889C1           mov rcx,rax
00000000005D3090 E8EB73E3FF      call @RaiseExcept
FS_Main.pas.5043: end;
00000000005D3095 488D6520         lea rsp,[rbp+$20]
00000000005D3099 5D              pop rbp
00000000005D309A C3               ret
copied it into my test-procedure ... and it worked.
Then i wanted to post it and saw that did the same.
Again thank you

Kas Ob. 6. Nov 2023 08:47

AW: In Asm-Prozedur eine Exception auslösen
 
This is : to whom it concern !

Very simple assembler code, this example shows how assembler code generation is entangled with Pascal part and way outdated and not optimized, though i am using XE8, but i have highly confidence in Embarcadero that they did not touch that part for newer versions.

Code:
PROCEDURE test;
const
   pExClass : ExceptClass = (Exception);
   sErr : String = ' My message ';
asm
    {$IfDef CPUX86}
   mov ecx,sErr
   mov dl ,1
   mov eax,pExClass
   call Exception .Create
   call System.@RaiseExcept
   {$Else}
   .noframe            //  crucial here
   push rbp
   sub rsp,$20
   mov rbp,rsp
   mov r8,sErr
   mov dl ,$01
   mov rcx,pExClass
   call Exception .Create
   mov rcx,rax
   call System.@RaiseExcept
   lea rsp,[rbp+$20]
   pop rbp
   {$EndIf}
end ;


{$STACKFRAMES ON}
function Add1(A,B:NativeInt):NativeInt;
asm
  add A,B
  mov result ,A
end;

{$STACKFRAMES OFF}
function Add2(A,B:NativeInt):NativeInt;
asm
  add A,B
  mov result ,A
end;

{$STACKFRAMES ON}
function Add3(A,B:NativeInt):NativeInt;
asm
  .noframe
  add A,B
  mov result ,A
end;

{$STACKFRAMES OFF}
function Add4(A,B:NativeInt):NativeInt;
asm
  .noframe
  add A,B
  mov result ,A
end;

{$STACKFRAMES OFF}
function Add5(A,B:NativeInt):NativeInt;
asm
  .noframe
 { push rbp   //
  sub rsp,$20 //  Trying to put our own frame with $20 byte window
  mov rbp,rsp //  }

  add A,B
  mov result ,A

  call test   //  calling your working code from previous post and it is OK, try..except will catch and recover form this

 { lea rsp,[rbp+$20]
  pop rbp   }
end;

{$STACKFRAMES OFF}
function Add6(A,B:NativeInt):NativeInt;
asm
  .noframe
  push rbp   //
  sub rsp,$20 //  Trying to put our own frame with $20 byte window
  mov rbp,rsp //

  add A,B
  mov result ,A

  call test   //  calling your working code from previous post and things are broken, on my XE8 try..except doesn't help at all

  lea rsp,[rbp+$20]
  pop rbp
end;
Check the assembly part in CPU window, and will see this gem
Code:
x64
0000000000426310 55               push rbp             // why the stack is needed at all here if we used .noframe
0000000000426311 4883EC10         sub rsp,$10
0000000000426315 488BEC          mov rbp,rsp
AsmException.dpr.87: add A,B
0000000000426318 4801D1           add rcx,rdx
AsmException.dpr.88: mov result ,A
000000000042631B 48894D08         mov [rbp+$08],rcx    //   really !!
AsmException.dpr.89: end;
000000000042631F 488B4508         mov rax,[rbp+$08]    //   WTF
0000000000426323 488D6510         lea rsp,[rbp+$10]
0000000000426327 5D              pop rbp
0000000000426328 C3               ret


x32
AsmException.dpr.86: asm
0041A50C 55               push ebp
0041A50D 8BEC            mov ebp,esp
0041A50F 51               push ecx                  //   WTF, pushing ecx on the stack ??!!!!! why ecx even mentioned or used here at all
AsmException.dpr.87: add A,B
0041A510 01D0             add eax,edx               //   the result is in eax, good, so it is in Result , lets return/exit
AsmException.dpr.88: mov result ,A
0041A512 8945FC          mov [ebp-$04],eax         //   really !!
AsmException.dpr.89: end;
0041A515 8B45FC          mov eax,[ebp-$04]         //   WTF
0041A518 59               pop ecx
0041A519 5D              pop ebp
0041A51A C3               ret

and you will notice many defect and unneeded stack write as both parameters are in register also the result in register meaning there is a wasted 1 full cycle to write and the worse id reading it on the following instruction causing wait on CPU pipe, for what ?!!! for no freaking reason, but this is off topic a little.

Back to exception and stack frames, none of the above followed my request from the compiler to not add a frame ( from documentation https://docwiki.embarcadero.com/RADS..._and_Functions )
Zitat:

Forcibly disables the generation of a stack frame as long as there are no local variables declared and the parameter count <= 4. Use only for leaf functions.
So obviously (with sarcasm ) my parameters are 5 or i am using local variable, unless result is considered as local variable which is... well .....

Anyway back to the topic, in all in above function the assembler added a stack push outside (encapsulating) my frame and my code, in Add6 did broke the test procedure which was working fine !, and that is my point, Add5 is not adding frame and test is working, while Add6 did broke outsider procedure/function "test", see why i am very pessimistic for adding your own frame stack in this very special case where you want to raise an exception.
No raise exception, fine, no problem add as much as you want on the stack, while expecting the stack winder after raising an exception to work out of the box and also to understand your stack use and the conflict with the compiler stack use there is problem, aka there will be blood !

Your test procedure which in its simplistic form doesn't have parameters or result worked fine, using that part with more complex code or lets say useful procedure will behave just like Add6, erratic with unpredictable behavior.


Sorry for the long post and bad Engrish.

Amateurprofi 7. Nov 2023 01:58

AW: In Asm-Prozedur eine Exception auslösen
 
Hier, in #24 sind die Prozeduren für die ich das haben wollte.
Noch einmal vielen Dank für die Hilfestellungen.

https://www.delphipraxis.net/119187-...ml#post1529146

paule32.jk 10. Nov 2023 11:21

AW: In Asm-Prozedur eine Exception auslösen
 
@Kas Obi:

I think, the stack is need under modern Microsoft Windows.
Because the first two 8 Bit = 16 Bit = 10h is for 64-Bit self-references the Functions, and Procedures.
So the first Argument/Parameter for the Function's/Procedure's begin at Bit 16.
I say to me:
Code:
first := 0 <-- self
second := 1 <-- first Parameter
...

Kas Ob. 10. Nov 2023 12:40

AW: In Asm-Prozedur eine Exception auslösen
 
Zitat:

Zitat von paule32.jk (Beitrag 1529419)
@Kas Obi:

I think, the stack is need under modern Microsoft Windows.
Because the first two 8 Bit = 16 Bit = 10h is for 64-Bit self-references the Functions, and Procedures.
So the first Argument/Parameter for the Function's/Procedure's begin at Bit 16.
I say to me:
Code:
first := 0 <-- self
second := 1 <-- first Parameter
...

I am not sure i do understand that %100, but Self will be used and added ONLY in Objects and Classes when the code is used in OOP style, not in orphan procedures/functions like all the mentioned p/f in this thread.

Example
Code:
function MyFunc(A: Integer; B: string): Integer;
begin

end;
 // Internally the compiler will make generate the code exactly as the following

procedure MyFuncAsProc(A: Integer; B: string; out Result: Integer);
begin

end;

------------------------

function MyClass.MyFunc(A: Integer; B: string): Integer;
begin

end;
 // Internally the compiler will make generate the code exactly as the following

procedure MyClass.MyFuncAsProc(const Self: TMyClass; A: Integer; B: string; out Result: Integer);
begin

end;
So using the satck is not for only referencing Self, in fact Self will always be in a register.( in edx on x86/x32, and in rcx on x64)

and that if i understand your comment right and we are talking about Self like This in other languages.

himitsu 10. Nov 2023 12:46

AW: In Asm-Prozedur eine Exception auslösen
 
no, with is only for results greater a Register aka SizeOf(Pointer)
or for Results with managed types, such as string and interface.

paule32.jk 10. Nov 2023 19:41

AW: In Asm-Prozedur eine Exception auslösen
 
@kas ob:

ehmm... with self, I mean not the Delphi keyword in Context of Classes/Records.
with self, I mean the internal working Design of Microsoft Windows.
Like himitsu said - it could be for "self" managed Code (COM+).

And I can bet, that Microsoft have a secret Layer'ed File with Numbers (I pointed: 2 ^64 = 18 Trillion GiBytes dataflow. So, each managed Type becomes a (GUID) Number, and as such, all the Component(s) are different and can directly accessed. Instead to use String like in Delphi, and C++ Builder Debug Symbols.
In older Window's, the DLL Functions could be called by Value, and Name.

jaenicke 10. Nov 2023 22:01

AW: In Asm-Prozedur eine Exception auslösen
 
I don't understand what you mean, but the stack layout is documented here:
https://learn.microsoft.com/en-us/cpp/build/stack-usage

paule32.jk 10. Nov 2023 22:11

AW: In Asm-Prozedur eine Exception auslösen
 
hello @jaenicke:

I point to: PROLOG and EPILOG

You can not simply call Exception Functions or any Functions of any Classes without .Create a Instance.
This give MAVs.

Kas Ob. 11. Nov 2023 06:59

AW: In Asm-Prozedur eine Exception auslösen
 
Zitat:

Zitat von paule32.jk (Beitrag 1529452)
@kas ob:

ehmm... with self, I mean not the Delphi keyword in Context of Classes/Records.
with self, I mean the internal working Design of Microsoft Windows.
Like himitsu said - it could be for "self" managed Code (COM+).

I am lost here, i don't understand this point or how it is relevant to raising an exception.

Notice that, exception are raised by an interrupt instruction, meaning it have standard way to raise, this doesn't have anything to do the OS (Windows/Linux...) it is standard by hardware, were the OS Kernel should have installed its debugger to capture/receive these hardware generated interrupt.

That was one, and second is notice how Delphi raise the Exception, we create a class then we pass the class to specific procedure to raise it, we don't call any element of that class.
Code:
type
  TMyException = class(Exception)
  end;

var
  MyExcept: TMyException;
begin
  MyExcept.Create('Error Message');
  // we do
  raise MyExcept;
  // and there is no way to raise it from within like
  MyExcept.raise;
end.
If we could do MyExcept.Raise then we should pass the except as self here, but we do raise MyExcept, which take a parameter to the System._RaiseExcept which has hidden way (aka compiler magic) to fill the parameter with the exception class, meaning it is declared as such
Code:
procedure RaiseExcept(Obj: TObject);
The fact we pass the created exception as parameter is merely a coincidence.

Zitat:

Zitat von paule32.jk (Beitrag 1529452)
And I can bet, that Microsoft have a secret Layer'ed File with Numbers (I pointed: 2 ^64 = 18 Trillion GiBytes dataflow. So, each managed Type becomes a (GUID) Number, and as such, all the Component(s) are different and can directly accessed. Instead to use String like in Delphi, and C++ Builder Debug Symbols.
In older Window's, the DLL Functions could be called by Value, and Name.

Also don't understand this, GUID for COM literally stored in specific Windows format standardized with specific VMT, so we have what we can call a class but it is a bunch of linked look-up tables each have its own GUID stored in central table for that created class, so no secret DB for them, just a service belongs to the OS have the control over the registration for these COM/DCOM, and fill the data in the registry, in readable way.
Also these strings in Delphi are the same in other languages (eg. C#..), in all cases these GUID strings will be translated into bytes from their hex values, into the specific structure to be read then looked up.
So if you use a hex editor/viewer on an application, you will not find any string like these GUID in an interface, but you will find the HEX values for them.

paule32.jk 11. Nov 2023 07:57

AW: In Asm-Prozedur eine Exception auslösen
 
@kas ob

First, the only Standard Interrupt on Windows is INT 3. It will be handled as/for Debug reason. This Interrupt is addressed into the GDT, and IDT Table (that is an Operating System Issue). I don't want go into the depth with this, because it will cover more things, that you don't understand.

Again, you need to create a Instance of a Exception Class to "stack up" the Exception.
Each Exception (class) need then stack Prolog, and Epilog.
The Prolog is for clean "build stack", the Epilog is for clean "destroy stack". This is a very import memory thing, because each Exception "can" have Parameters like .Create(42); or .Create('foo'); or .Create('foo','fufu',42); or simply .Create;

Exception's will be "raise" with: raise EExceptionClass.Create; or EExceptionClass.Create(42); ...
Again, you can not do simply raise EExceptionClass.MyExcept; because raise point then into memory where "not" your code have access, and Windows will prompt you with MAV's.

Second, Microsoft Windows uses very often COM+ (Component Object Model) things.
That is based on the Terminal Server Services, and/or the Remote Access Services (RD Remote Desktop).
This services are for centralized the maintain flow of Enterprise/Corporation's firms Computerdesk.

To hold the traffic and latency of Applications for this Services on a low Level, Microsoft plays a little bit with it's own technologies.
As such, they transmit data in form of image data, and plain text (like numbers that describe, what Function is to call on the counter part of the connection. This is then from Server to Client, and Client to Server.

- You can take a look onto the RPC Protocol, and it's implementation (Tools).
- You will realize that many things are based on numbers

RPC is a very old Protocol from Unix Workstations, and Unix Servers back into the 1970th.

Kas Ob. 11. Nov 2023 08:57

AW: In Asm-Prozedur eine Exception auslösen
 
Zitat:

Zitat von paule32.jk (Beitrag 1529461)
@kas ob
First, the only Standard Interrupt on Windows is INT 3. It will be handled as/for Debug reason. This Interrupt is addressed into the GDT, and IDT Table (that is an Operating System Issue). I don't want go into the depth with this, because it will cover more things, that you don't understand.

There is more than one Interrupt https://www.felixcloutier.com/x86/intn:into:int3:int1
I do understand it all.

Zitat:

Zitat von paule32.jk (Beitrag 1529461)
Again, you need to create a Instance of a Exception Class to "stack up" the Exception.
Each Exception (class) need then stack Prolog, and Epilog.
The Prolog is for clean "build stack", the Epilog is for clean "destroy stack". This is a very import memory thing, because each Exception "can" have Parameters like .Create(42); or .Create('foo'); or .Create('foo','fufu',42); or simply .Create;

You are confusing the exception and its class with the SEH structure that will trap the exception, exception will not have Prolog or Epilog, these are and should be for each function/procedure for the unwinder to unwind till reaching the last exception trap, and they has nothing to do with the exception itself or its parameter, except where it did raised and where to start to unwind, if the parameters of the context is known for the OS then it will handle it, otherwise it will pass these SEH, also exception not only raised manually, eg. most of the assembly code that access memory can and might raise Page Faults which also are exception, and none the less will be passed to last SEH, only if the OS decide to, does these have prolog or epilog !!? no is the answer, and they don't have exception class at all, the OS will build parameters then do the unwind then pass these parameters to the last SEH found, if the applicaiton have one then it is OK, if not then most likely the OS will kill that process/application.

Zitat:

Zitat von paule32.jk (Beitrag 1529461)
Second, Microsoft Windows uses very often COM+ (Component Object Model) things.
That is based on the Terminal Server Services, and/or the Remote Access Services (RD Remote Desktop).
This services are for centralized the maintain flow of Enterprise/Corporation's firms Computerdesk.

Honestly, i have no idea what COM or COM+ or DCOM has to do here in this thread, but for the sake of clarification
https://stackoverflow.com/questions/...onent-services
https://www.geeksforgeeks.org/differ...com-and-dcom/#
So in very short sentences, COM is Windows way to overcome compatibility and portability for code over many or any programming language.
COM+ is advanced COM with extra layer of security and authentication.
DCOM is Distributed COM, provide the ability be for COM+ to be called and executed remotely, and by remotely not only over wire or Internet connection but also on different users accounts and different session, different domains also supported...etc.
That is it.

paule32.jk 11. Nov 2023 09:15

AW: In Asm-Prozedur eine Exception auslösen
 
Zitat:

Zitat von Kas Ob. (Beitrag 1529464)
Honestly, i have no idea what COM or COM+ or DCOM has to do here in this thread, but for the sake of clarification

This should be a Bonus Information, to keep in mind, that Microsoft Windows used "self references" its function references.
Don't make you hard on this. I don't can expect that you can understand all these things of Computers and the differences between the Calling Convention, ABI, and Operating interna of each one. Because all OS have it's own kernel behavior.

And yes, you can do INT'errupt on 32/64-Bit machines, but then, you have to switch from the 32/64-bit protected-mode into the 16-bit real-mode of the CPU. But doing this, you have to "store" all registers, before you switch, and after you switch back into 64-bit CPU mode, you have to "re-store" all registers to avoid crash or prompts of MAV's.

Kas Ob. 11. Nov 2023 09:49

AW: In Asm-Prozedur eine Exception auslösen
 
@paule32.jk :
I am sorry for wasting your time.


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:39 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-2025 by Thomas Breitkreuz