admin管理员组

文章数量:1184837

I have the following code that is written in pure Delphi.

procedure Test;
var
  i2: Integer;
begin
  i2 := 0;
  i2 := 0 div i2;
end;
try
  Test1;
except
  WriteLn('runtime error');
end;

Then I copied all the assembly code that generated by Delphi compiler in the CPU view under debugger.

procedure Test;
asm
  push rbp
  sub rsp,$10
  mov rbp,rsp
  mov [rbp+$0c],$0000007b
  mov [rbp+$08],$00000000
  mov eax,[rbp+$0c]
  cdq
  idiv dword ptr [rbp+$08]
  mov [rbp+$08],eax
  lea rsp,[rbp+$10]
  pop rbp
end;

try
  Test1;
except
  WriteLn('runtime error');
end;

But the program crashed due to unable unwind exception. But the pure Pascal version works correctly to catch the exception. Why it happens since they are the same assembly code?

Is there any documentation to explain this different behavior? I have found a documentation explaining MacOS inline assembly (PC-Mapped Exceptions - RAD Studio). But I suppose that does not fit Win64.

Is there any special rule to write assembly code in Win64 and properly let Delphi handing runtime error?

I have the following code that is written in pure Delphi.

procedure Test;
var
  i2: Integer;
begin
  i2 := 0;
  i2 := 0 div i2;
end;
try
  Test1;
except
  WriteLn('runtime error');
end;

Then I copied all the assembly code that generated by Delphi compiler in the CPU view under debugger.

procedure Test;
asm
  push rbp
  sub rsp,$10
  mov rbp,rsp
  mov [rbp+$0c],$0000007b
  mov [rbp+$08],$00000000
  mov eax,[rbp+$0c]
  cdq
  idiv dword ptr [rbp+$08]
  mov [rbp+$08],eax
  lea rsp,[rbp+$10]
  pop rbp
end;

try
  Test1;
except
  WriteLn('runtime error');
end;

But the program crashed due to unable unwind exception. But the pure Pascal version works correctly to catch the exception. Why it happens since they are the same assembly code?

Is there any documentation to explain this different behavior? I have found a documentation explaining MacOS inline assembly (PC-Mapped Exceptions - RAD Studio). But I suppose that does not fit Win64.

Is there any special rule to write assembly code in Win64 and properly let Delphi handing runtime error?

Share Improve this question edited yesterday Kai Burghardt 1,5541 gold badge12 silver badges28 bronze badges asked Jan 26 at 3:04 qgiqgi 655 bronze badges 5
  • 2 I don't know about Delphi runtime but Windows's x64 ABI uses table based exceptions and that requires extra data to be generated and pointed to by the PE sections list (and also constraint the prolog/epilog code). If there's no special code for the Delphi runtime (as it seems) in the function itself, then Delphi is probably relying on the Win64 exception system. – Margaret Bloom Commented Jan 26 at 13:02
  • 1 Exactly this, you didn't create the meta data for the exception table – David Heffernan Commented Jan 26 at 14:38
  • I have no idea how Delphi handles this, but there's some discussion of how MASM and GAS does it here. – David Wohlferd Commented Jan 26 at 19:07
  • Afaik Borland held the patent for table based exceptions for years, and licensed it to Microsoft. – Marco van de Voort Commented 2 days ago
  • But how should I write assembly code in Win64, so the runtime error is handled correctly in Delphi? Is there any doc or reading material that I could read? There is really little on this, on Delphi migration 64bit doc, it just said you should write ASM code carefully or the exception won't be handled correctly. – qgi Commented 2 days ago
Add a comment  | 

1 Answer 1

Reset to default 2

The term is SEH, Structured Exception Handling. The compiler generates a table on a fixed offset of the procedure entry point, and the unwinder can find it using the exception address (and possibly also using the parent frame).

In short: the assembler you have for the procedure, is not all that is generated.

To get a feeling for what is involved, compile the short example with Free Pascal with the -al parameter. That shows all generated data as assembler source, and you can also see section information and other tables.

本文标签: Exception Handling in 64bit(Windows) Delphi assemblyStack Overflow