Die Prinzipielle Idee würde ich gerne in meinen Pre-Compiler einbauen. Blöd ist, das ich keinerlei Assembler kann (also zumindest x86,x64). Ich hätte aber ein paar fragen zu den Output, die der PBCompiler so erzeugt (kommentierter ASM Output bei DLL erstellung).
Meine kleine PB-Datei:
Code: Alles auswählen
Procedure test()
b+10
EndProcedure
a=10
a=a+10
a+20
test()
procedure test2()
endprocedure
Der erste Block darf natürlich nicht verändert werden:
Code: Alles auswählen
;
; PureBasic 5.61 (Windows - x64) generated code
;
; (c) 2016 Fantaisie Software
;
; The header must remain intact for Re-Assembly
;
; :DLL
; :System
; kernel32.lib
; :Import
;
format MS64 COFF
;
;
extrn GetModuleHandleW
extrn HeapCreate
extrn HeapDestroy
extrn memset
public _PB_Instance
public PB_ExecutableType
public PB_OpenGLSubsystem
public _PB_MemoryBase
public PB_Instance
public PB_MemoryBase
public PB_EndFunctions
public _DLLEntryPoint@12
macro pb_public symbol
{
public _#symbol
public symbol
_#symbol:
symbol:
}
macro pb_align value { rb (value-1) - ($-_PB_DataSection + value-1) mod value }
macro pb_bssalign value { rb (value-1) - ($-_PB_BSSSection + value-1) mod value }
;
section '.code' code readable executable align 4096
;
;
Code: Alles auswählen
_DLLEntryPoint@12:
SUB rsp,40
CMP rdx,1
JNE .SkipProcessAttach
MOV [_PB_Instance],rcx
CALL PB_DllInit
JMP .End
.SkipProcessAttach:
CMP rdx,2
JNE .SkipThreadAttach
JMP .End
.SkipThreadAttach:
CMP rdx,0
JNE .SkipProcessDetach
CALL _PB_EOP
JMP .End
.SkipProcessDetach:
CMP rdx,3
JNE .SkipThreadDetach
.SkipThreadDetach:
.End:
MOV rax,1
ADD rsp,40
RET
Jetzt wirds interessant. PB_DLLInit ist wohl wichtig. Hier wurden alle Befehle gesammelt, die in Hauptquellcode vorkommen - den es in einer DLL nicht gibt. Man sieht auch das in den (von mir ausgeschnittenen Code) diese Function gestartet wird. Der Anfang scheint mir aber gefährlich.
Sub rsp,40
Scheint irgendwelche Stack-Aufräum-Aktion zu sein. Das muss bleiben
XOR r8,r8
MOV rdx,4096
XOR rcx,rcx
CALL HeapCreate
MOV [PB_MemoryBase],rax
scheint ein Funktionsaufruf zu sein, der in einer UserBibliothek garantiert nichts zu suchen hat. dementsprechend
Die zeilen drin
Code: Alles auswählen
PB_DllInit:
SUB rsp,40
Code: Alles auswählen
XOR r8,r8
MOV rdx,4096
XOR rcx,rcx
CALL HeapCreate
MOV [PB_MemoryBase],rax
Code: Alles auswählen
;; a=10
MOV qword [v_a],10
; a=a+10
ADD qword [v_a],10
; a+20
ADD qword [v_a],20
; test()
CALL _Procedure0
;
;
ADD rsp,40
RET
Also der Part weg:
Code: Alles auswählen
_PB_EOP:
SUB rsp,40
CALL PB_EndFunctions
MOV rcx,[PB_MemoryBase]
CALL HeapDestroy
ADD rsp,40
RET
PB_EndFunctions:
SUB rsp,40
ADD rsp,40
RET
Code: Alles auswählen
;
; Procedure test()
_Procedure0:
PUSH r15
PS0=64
XOR rax,rax
PUSH rax
SUB rsp,40
; b+10
MOV r15,qword [rsp+40]
ADD r15,10
MOV qword [rsp+40],r15
; EndProcedure
_EndProcedureZero1:
XOR rax,rax
_EndProcedure1:
ADD rsp,48
POP r15
RET
;
section '.data' data readable writeable
;
_PB_DataSection:
PB_OpenGLSubsystem: db 0
pb_public PB_DEBUGGER_LineNumber
dd -1
pb_public PB_DEBUGGER_IncludedFiles
dd 0
pb_public PB_DEBUGGER_FileName
db 0
pb_public PB_Compiler_Unicode
dd 1
pb_public PB_Compiler_Thread
dd 0
pb_public PB_Compiler_Purifier
dd 0
pb_public PB_Compiler_Debugger
dd 0
PB_ExecutableType: dd 0
pb_align 8
pb_align 8
pb_align 8
s_s:
dq 0
dq -1
pb_align 8
;
section '.bss' readable writeable
_PB_BSSSection:
pb_bssalign 8
;
I_BSSStart:
_PB_MemoryBase:
PB_MemoryBase: rq 1
_PB_Instance:
PB_Instance: rq 1
PB_ExitCode: rq 1
;
pb_bssalign 8
PB_DataPointer rq 1
v_a rq 1
pb_bssalign 8
pb_bssalign 8
pb_bssalign 8
pb_bssalign 8
I_BSSEnd:
section '.data' data readable writeable
SYS_EndDataSection:
Bonusfrage:
Oben ist ja x64, unter x86 siehts so aus:
Code: Alles auswählen
PB_DllInit:
PUSH dword 0
PUSH dword 4096
PUSH dword 0
CALL _HeapCreate@12
MOV [PB_MemoryBase],eax
;; a=10