Assembler section shows disassembler machine code near exception. This section can be disabled in options.
Note: assembler section is automatically disabled for reporting leaks.
Disassembler listing does not provide any new information as compared to other information in bug report - because it simply duplicate content of your executable, but presents it in human-readable form. But this section can still be useful, because it saves you time on disassembling your exe/DLL file.
; Base Address: $7F0000, Allocation Base: $400000, Region Size: 61440
; Allocation Protect: PAGE_EXECUTE_WRITECOPY, Protect: PAGE_EXECUTE_READ
; State: MEM_COMMIT, Type: MEM_IMAGE
; Unit9.TForm9.Button7Click (Line=747 - Offset=0)
00000000007F0D20 55 PUSH RBP
00000000007F0D21 4883EC20 SUB RSP, $20
00000000007F0D25 488BEC MOV RBP, RSP
00000000007F0D28 48894D30 MOV [RBP+$30], RCX
00000000007F0D2C 48895538 MOV [RBP+$38], RDX
; Line=748 - Offset=16
00000000007F0D30 488B0DA9ACC5FF MOV RCX, [REL -$003A5357] ; ($000000000044B9E0) Exception Data as ANSI: '¨ºD'; Data as UNICODE: '모D'
00000000007F0D37 B201 MOV DL, 1
00000000007F0D39 4C8D0520000000 LEA R8, [REL $00000020] ; ($00000000007F0D60) Unit9.TForm9.Button7Click (Line=749) UNICODE: 'Error Message'
00000000007F0D40 E84BEBC6FF CALL -$3914B5 ; ($000000000045F890) System.Exception.Create
00000000007F0D45 4889C1 MOV RCX, RAX
00000000007F0D48 E823C3C1FF CALL -$3E3CDD ; ($000000000040D070) System._RaiseExcept <-- EXCEPTION
; Line=749 - Offset=45
00000000007F0D4D 488D6520 LEA RSP, [RBP+$20]
00000000007F0D51 5D POP RBP
Example of disassembly output
Exception address will be listed in the middle of disassembly listing and marked with "<-- EXCEPTION" comment. Listing will go 15 CPU instructions in both directions (up/down) from exception address or until start/end of routine is found.
Assembler section uses asm syntax compatible with Delphi's asm-blocks with minor exceptions (see below):
CPU instructions are grouped in source lines. Each source line is marked with comment block above CPU instructions. Comment block indicate routine name, line number and byte offset. Each value is listed only if it was changed from previous line. For example, routine name is not shown if current line belongs to the same routine as previous line.
There is also a special comment block at the top of the section which shows general information about code page to which disassembled code belongs.
Note: disassembly listing uses ;-style comments instead of usual Delphi's //-style comments.
Absolute and relative addressing
EurekaLog's disassembler follows rules of Delphi's disassembler. For example, x86-32 assembler uses absolute addressing by default, but x86-64 assembler uses relative addressing by default. For example: "MOV EAX, [$10]". This instruction will be compiled into "MOV EAX, [ABS $10]" by 32-bit assembler. But the same instruction will be compiled into "MOV EAX, [REL $10]" (which means "MOV EAX, [RIP + $10]") by 64-bit assembler.
Delphi assembler supports ABS and REL modifier to alter addressing mode. It does not support [RIP + $10] or [$ + $10] syntax. ABS modifier is shown as + sign by Delphi's disassembler. For example, "MOV EAX, [ABS $10]" instruction will be disassembled by Delphi as "MOV EAX, [+$10]".
EurekaLog's disassembler always use REL and ABS modifiers to indicate addressing mode. REL/ABS modifiers are omitted for 32-bit code.
x86-64 is extension of x86-32. Thus, x86-64 tries to be compatible with x86-32 as much as possible. Still, there are differences - such as addressing mode. x86-32 prefers absolute addressing, while x86-64 prefers relative addressing to simplify writing PIC (Position Independent Code). This means that 64-bit code requires much less fix-ups when loading DLL to address which is different from preferred base address of this DLL. That's because 64-bit instructions works with relative addresses, so it doesn't use absolute addresses which needs to be fixed if code is loaded to another address.
MOV [sym], RAX ; absolute for 32-bit, relative for 64-bit
MOV [REL sym], RAX ; relative
MOV [RIP + sym], RAX ; relative, not supported by Delphi
MOV [$ + sym], RAX ; relative, not supported by Delphi
MOV [ABS sym], RAX ; absolute
MOV [+ sym], RAX ; absolute, Delphi disassembler only
Most 64-bit instructions works with 32-bit values. In 64-bit mode, immediates (that is, contants) and displacements (that is, offsets) are generally only 32 bits wide.
The above means that you can not JMP or CALL to 64-bit absolute location specified with constant. JMP and CALL can only jump to a relative location within +/- 2 Gb from current instruction. If you need to jump to arbitrary 64-bit location then you have to use at least two instructions or indirect addressing:
MOV RAX, $1234567890ABCDEF
JMP [REL 0]
DB $12, $34, $56, $78, $90, $AB, $CD, $EF