Simpler 32/64-Bit-Dis-Assembler in PB

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
Helle
Beiträge: 566
Registriert: 11.11.2004 16:13
Wohnort: Magdeburg

Simpler 32/64-Bit-Dis-Assembler in PB

Beitrag von Helle »

Da mich der jetzt in PB 4.30 enthaltene Dis-Assembler Udis86 noch nie so richtig vom Hocker gerissen hat (öfters Invalid-Meldungen), habe ich (endlich) mal angefangen, selbst einen Dis-Assembler zu schreiben. Das Ganze sollte halbwegs übersichtlich und relativ leicht erweiterbar sein und Ausführungs-Geschwindigkeit keine Rolle spielen. Das Ergebnis ist ein komplett in PB geschriebener simpler Dis-Assembler, der bisher nur "normale" x86-Befehle (incl. FPU) auswertet, aber weiter in Entwicklung ist. Hier der bisherige Code:
http://www.mdcc-fun.de/k.helbing/Dis-Assembler/
Fehler-Meldungen erwünscht!

Ich wünsche Euch einen guten Rutsch und ein erfolgreiches, möglichst fehlerfreies Programmier-Jahr 2009 :mrgreen: !

Gruß
Helle
Zuletzt geändert von Helle am 02.05.2009 19:01, insgesamt 1-mal geändert.
Benutzeravatar
Josef Sniatecki
Beiträge: 657
Registriert: 02.06.2008 21:29
Kontaktdaten:

Beitrag von Josef Sniatecki »

Echt gut. Habe es getestet.
Der Quellcode ist ja beinahe länger als der von meinem Interpreter :shock:.
PB 4.61 | Windows Vista - 32Bit
Homepage

"Wahrlich es ist nicht das Wissen, sondern das Lernen, nicht das Besitzen sondern das Erwerben, nicht das Dasein, sondern das Hinkommen, was den grössten Genuss gewährt." - Carl Friedrich Gauß
sechsrad
Rüpel
Beiträge: 112
Registriert: 01.02.2008 13:31

Beitrag von sechsrad »

Hallo, gut gelungen.

mfg
Benutzeravatar
Rings
Beiträge: 977
Registriert: 29.08.2004 08:48

Beitrag von Rings »

wie immer, alle Achtung !!!
Einen Disassembler zu schreiben beinhaltet nicht geraden
geringe kenntnis der Materie.Sind die Opcodes der
x86 Schiene doch gerade nicht
logisch angeordnet(im vergleich zum 680xxx zbsp) .
Was auffällt, eine Disassm-Session einer 2mb großen Exe
dauert manchmal sehr lange.
Deswegen ein paar Vorschläge:
zum Speed:
-Die Listview erst enablen wenn der vorgang fertig ist.
-PeekL benötigt immer mehr Zyklen als wenn man per Pointer
auf nen Speicherbereich direkt zurückgreift.

Zur Übersicht:
-die ganzen Peek's mit absoluten Adressen in der Section machen
das ganze natürlich total unübersichtlich.
besser die Strukturen und damit Pointer des PE-Formates verwenden.

Code: Alles auswählen

IMAGE_DOS_HEADER
IMAGE_DATA_DIRECTORY
IMAGE_OPTIONAL_HEADER
IMAGE_FILE_HEADER
IMAGE_SECTION_HEADER etc.
solche Sachen sind in PB deklariert und auch für X64 verwendbar !

-Die Variablen haben meist zu kleine Namen(3 Zeichen) , etwas länger
wäre besser lesbar(intellisense macht weniger tipparbeit).

wie gesagt, nur Vorschläge.
Was mir persönlich fehlen würde (und das eigentlich nur für
die ExceptionHandler/Trampolin Geschichte),
wäre die Länge eines Opcodes (inkl. Parametern) zu ermitteln.

sowas hier ZumBsp:

Code: Alles auswählen

Procedure getOpCodelength(adress)
*OP.Byte = adress
*OP2.Byte = adress+1
op2=(*OP2\b & $FF )
*OP3.Byte = adress+2
op3=(*OP3\b & $FF )
 
 ;Debug Hex(*op\b)
 
 Select ( *OP\b  & $FF) 
      ;----------------------
      Case $00                              ;Eb, Gb
      ProcedureReturn  1
 ;       MN$ = "ADD "
      
      Case $83                              ;Immediate Gruppe 1 mit 1-Byte-Konstante
;Debug OP2
RM = (OP2 & %00111000) >> 3
;Debug RM
      ProcedureReturn  3

;         OP = PeekB(Buffer + BZ) & $FF     
;         OP$ + RSet(Hex(OP), 2, "0") + " " 
;         BZ + 1
;         RM = (OP & %00111000) >> 3          ;reg/opcode für Befehl        
;         Select RM
;           Case 0
;             MN$ = "ADD "
;           Case 1
;             MN$ = "OR "
;           Case 2
;             MN$ = "ADC "
;           Case 3
;             MN$ = "SBB "
;           Case 4
;             MN$ = "AND "
;           Case 5
;             MN$ = "SUB "
;           Case 6
;             MN$ = "XOR "
;           Case 7
;             MN$ = "CMP "
;         EndSelect
;         Komma = 1
;         MSBytes(OP, 2)                      ;VAR2=2=DWord        
;         OP = PeekB(Buffer + BZ) & $FF     
;         OP$ + RSet(Hex(OP), 2, "0") + " " 
;         H = PeekB(Buffer + BZ) & $FF
;         If H < $80                          ;Feinheit!
;           H$ = "00 00 00 "
;          Else
;           H$ = "FF FF FF "
;         EndIf  
;         MN$ + H$ + RSet(Hex(H), 2, "0")     ;plus der 1-Byte-Wert      
;         BZ + 1
    Case $90
     ;NOP
      ProcedureReturn 1
    Case $CC
     ;INT 3
      ProcedureReturn 1 
    Case x
     ProcedureReturn y
     
 EndSelect
 
EndProcedure


Adresse=?ExampleCode
AdresseEnd=?ExampleCodeEnd

Debug Adresse


For I=Adresse To AdresseEnd -1
 Debug Hex(I) + "  : " + Hex(PeekL(I) & $FF)
Next I

Debug getOpCodelength(Adresse)
Debug getOpCodelength(Adresse+1)
Debug getOpCodelength(Adresse+2)

 If ExamineAssembly(Adresse,  AdresseEnd)
    While NextInstruction()
      ;Text$ + RSet(Hex(InstructionAddress()), SizeOf(Integer)*2, "0")
      Debug  RSet(Hex(InstructionAddress()), SizeOf(Integer)*2, "0") + "  "+ InstructionString() 
    Wend
  EndIf

End

ExampleCode:
!NOP
!INT3
!ADD EAX,1
ExampleCodeEnd:
Rings hat geschrieben:ziert sich nich beim zitieren
Benutzeravatar
Helle
Beiträge: 566
Registriert: 11.11.2004 16:13
Wohnort: Magdeburg

Beitrag von Helle »

Erstmal Danke! Habe die neueste Version soeben hochgeladen; noch ohne die von Rings angeregte Structure-Verwendung, aber das schaue ich mir noch an. Geschwindigkeits-Steigerung steht auch noch aus.
Die Ermittlung der Opcode-Länge war von Anfang an mit im Hinterkopf :mrgreen: ! Ich hatte mich ja hier schon in einen Thread betr. Exception-Handler eingeklingt. Der dortige Einsatz des Udis86-Disassemblers machte das Programm (als Exe) um satte 100kB grösser, ausserdem hat er einige Macken (teste mal INC/DEC mit einer DWord-oder Word-Variable oder das eigentlich harmlose FABS). Lizenz und momentane Einschränkungen (kein SSSE3 und höher) kommen noch hinzu. Also musste für die Code-Längen-Ermittlung etwas Eigenes her, möglichst mit nur 1/10 der Größe von Udis. Der Dis-Assembler wurde als Grundlage dafür benötigt. Hier ist das Ergebnis:

Code: Alles auswählen

;- Ermittlung der nächsten Opcode-Adresse (z.B. für Exception-Handler)
;- "Helle" Klaus Helbing, 10.01.2009
;- Getestet mit PB 4.30, WinXP Prof. SP3
;- Kann z.B. als Include-Datei definiert werden
;- Es muss nur die Code-Adresse als globale Variable definiert werden; hier BZ genannt 
;- Nicht berücksichtigt werden (z.Z.) Address-Override und 3DNow!, werden in einem "normalen"
;-  PB-Programm nicht vorkommen (hoffe ich)
;- Ist noch in der Test-Phase, mögliche Fehler nicht ausgeschlossen! 
;- Der Code kann zeilenmässig noch gestrafft werden

Global BZ.i                                 ;Code-Adresse

Procedure MSBytes(VAR1)
  MOD = VAR1 >> 6
  RM = VAR1 & %00000111
  Select MOD
    Case %00
      Select RM
        Case %100                           ;SIB-Byte folgt
          SIB = PeekB(BZ) & $FF             ;also einlesen 
          BZ + 1
          I = (SIB & %00111000) >> 3
          B = SIB & %00000111
          Select B
            Case %101
              Select I
                Case %100                   ;wäre Register ESP
                  ;wäre Fehler: kein Index, kein Base
                Default
                  BZ + 4
              EndSelect
          EndSelect
        Case %101                           ;direkte 32-Bit-Adresse
          BZ + 4
        Default                             ;kein SIB-Byte
       EndSelect
          
    Case %01                                ;mit 8-Bit-Adress-Versatz, 1 weiteres Byte einlesen
      Select RM
        Case %100                           ;SIB-Byte folgt       
          SIB = PeekB(BZ) & $FF             ;also einlesen 
          BZ + 1
          S = SIB >> 6
          I = (SIB & %00111000) >> 3
          Select I
            Case %100
              Select S
                Case %00                    ;EA=Address+[B]
                  BZ + 1                
                Default 
                  ;Fehler, wäre falsche Compilierung 
              EndSelect 
            Default                         ;EA=Address+[B+S*I]
              BZ + 1                
          EndSelect
        Default                             ;kein SIB-Byte, EA=Address+[R/M] 
          BZ + 1                     
      EndSelect 
  
    Case %10                                ;Adresse 32-bittig 
      Select RM
        Case %100                           ;SIB-Byte folgt       
          SIB = PeekB(BZ) & $FF             ;also einlesen 
          BZ + 1
          S = SIB >> 6
          I = (SIB & %00111000) >> 3
          Select I
            Case %100
              Select S
                Case %00                    ;EA=Address+[B]
                  BZ + 4
                Default 
                  ;Fehler, wäre falsche Compilierung 
              EndSelect 
            Default                         ;EA=Address+[B+S*I]
              BZ + 4
          EndSelect
        Default                             ;kein SIB-Byte, EA=Address+[R/M] 
          BZ + 4
      EndSelect 

  EndSelect       
EndProcedure

Procedure M()
  OP = PeekB(BZ) & $FF     
  BZ + 1
  MSBytes(OP)
EndProcedure

Procedure FPU()                             ;FPU-Instruktionen
  OPF = PeekB(BZ- 1) & $FF
  MODRM = PeekB(BZ) & $FF
  MOD = MODRM >> 6
  SPEC = (MODRM >> 3) & %00000111
  RM = MODRM & %00000111
  BZ + 1
  Select OPF                                ;$D8 bis $DF, kommt von Procedure_Codes()  
    Case $D8 To $DC
      Select MOD
        Case 0 To 2 
          MSBytes(MODRM)
      EndSelect
    Case $DD
      Select MOD
        Case 0 To 2
          Select SPEC
            Case 0 To 3                     ;nicht zusammenfassen!
              MSBytes(MODRM)
            Case 7
              MSBytes(MODRM)
          EndSelect
      EndSelect 
    Case $DE To $DF
      Select MOD
        Case 0 To 2
          MSBytes(MODRM)
      EndSelect
  EndSelect
EndProcedure

Procedure OP3B38()                          ;die ersten 2 Bytes sind $0F $38
  OP = PeekB(BZ) & $FF
  BZ + 1  
  Select OP 
    ;----------------------
    Case $00 To $0B
      M()  
    ;----------------------
    Case $10
      M()
    ;----------------------
    Case $14 To $15
      M()
    ;----------------------
    Case $17
      M()
    ;----------------------
    Case $1C To $1E
      M()  
    ;----------------------
    Case $28 To $2B
      M()
    ;----------------------
    Case $37 To $41
      M()
  EndSelect
EndProcedure

Procedure OP3B3A()                          ;die ersten 2 Bytes sind $0F $3A
  OP = PeekB(BZ) & $FF
  BZ + 1  
  Select OP 
    ;----------------------
    Case $08 To $0F
      M() : BZ + 1
    ;------------------------  
    Case $40 To $42
      M() : BZ + 1
    ;------------------------  
    Case $60 To $63
      M() : BZ + 1
  EndSelect
EndProcedure

Procedure Codes_Shift()                     ;1.Byte ist $0F
  OP = PeekB(BZ) & $FF
  BZ + 1  
  Select OP 
    ;------------------------    
    Case $00                                ;Gruppe 6
      OP = PeekB(BZ) & $FF     
      BZ + 1
      If OP < $C0                           ;also nicht %11xxxxxx = Register-Register   
        BZ + 4
      EndIf
    ;------------------------    
    Case $01                                ;Gruppe 7
      OP = PeekB(BZ) & $FF     
      BZ + 1
      If OP < $C0                           ;also nicht %11xxxxxx
         BZ + 4
      EndIf
    ;------------------------ 
    Case $02 To $03
      M()
    ;------------------------    
    Case $05 To $0B
    ;------------------------    
    Case $10 To $17
      M() 
    ;------------------------    
    Case $18                                ;PREFETCH, Gruppe 16 
      BZ + 5
    ;------------------------    
    Case $1F                                ;Ev
      M()
    ;------------------------    
    Case $20 To 23
      BZ + 1
    ;------------------------
    Case $28 To $2F
      M()
    ;------------------------    
    Case $30 To $35
    ;------------------------    
    Case $37
    ;------------------------    
    Case $38                                ;3-Byte-Opcodes
      OP3B38()
    ;------------------------    
    Case $3A                                ;3-Byte-Opcodes
      OP3B3A()
    ;----------------------
    Case $40 To $4F
      M()
    ;----------------------
    Case $50 To $6F
      M()
    ;------------------------  
    Case $70
      M() : BZ + 1
    ;----------------------
    Case $71 To $73
      BZ + 2
    ;----------------------
    Case $74 To $76
      M()
    ;----------------------
    Case $77
    ;----------------------
    Case $78 To $79
      M()
    ;----------------------
    Case $7C To $7F
      M()
   ;------------------------
    Case $80 To $8F
      BZ + 4
    ;------------------------ 
    Case $90 To $9F
      M()
    ;------------------------ 
    Case $A0 To $A2
    ;------------------------ 
    Case $A3                                ;Ev, Gv
      M()
    ;------------------------ 
    Case $A4                                ;Ev, Gv, Ib
      OP = PeekB(BZ) & $FF     
      BZ + 1      
      If (OP >> 6) <> 3                     ;also nicht Register-Register
        MSBytes(OP)
      EndIf
      BZ + 1
    ;------------------------ 
    Case $A5                                ;Ev, Gv, CL
      OP = PeekB(BZ) & $FF     
      BZ + 1      
      If (OP >> 6) <> 3                     ;also nicht Register-Register
        MSBytes(OP)
      EndIf
    ;------------------------ 
    Case $A8 To $AA
    ;------------------------
    Case $AB                                ;Ev, Gv
      M()
    ;------------------------ 
    Case $AC                                ;Ev, Gv, Ib
      OP = PeekB(BZ) & $FF     
      BZ + 1      
      If (OP >> 6) <> 3                     ;also nicht Register-Register
        MSBytes(OP)
      EndIf
      BZ + 1
     ;------------------------ 
    Case $AD                                ;Ev, Gv, CL
      OP = PeekB(BZ) & $FF     
      BZ + 1      
      If (OP >> 6) <> 3                     ;also nicht Register-Register
        MSBytes(OP)
      EndIf
    ;------------------------ 
    Case $AE                                ;Gruppe 15
      OP = PeekB(BZ) & $FF     
      BZ + 1
      RM = (OP & %00111000) >> 3            ;reg/opcode für Befehl
      Select RM
        Case 0 To 1
          If OP < $C0                       ;also nicht %11xxxxxx
            MSBytes(OP)
          EndIf
        Case 2 To 3
          If OP < $C0                       ;also nicht %11xxxxxx
            BZ + 4
          EndIf
        Case 4 To 5
          If OP < $C0                       ;also nicht %11xxxxxx = Register-Register   
            MSBytes(OP)
          EndIf
        Case 7
          If OP < $C0                       ;also nicht %11xxxxxx
            BZ + 4
          EndIf
      EndSelect               
    ;------------------------ 
    Case $AF To $B1
      M()
    ;----------------------
    Case $B2
      OP = PeekB(BZ) & $FF     
      BZ + 1
    ;------------------------ 
    Case $B3                                ;Ev, Gv
      M()
    ;------------------------ 
    Case $B4 To $B5
      OP = PeekB(BZ) & $FF     
      BZ + 1
    ;------------------------ 
    Case $B6
      M()
    ;------------------------ 
    Case $B7
      OP = PeekB(BZ) & $FF     
      BZ + 1
      MSBytes(OP)
    ;------------------------ 
    Case $B8
      M()
    ;------------------------ 
    Case $BA                                ;Gruppe 8  Ev, Ib
      OP = PeekB(BZ) & $FF     
      BZ + 1
      MSBytes(OP)
      BZ + 1
    ;------------------------
    Case $BB To $C1
      M()
    ;----------------------
    Case $C2
      M() : BZ + 1
    ;------------------------    
    Case $C3                                ;Md, Gd
      M()
    ;----------------------
    Case $C4 To $C6
      M() : BZ + 1
    ;----------------------
    Case $C7                                ;Gruppe 9
      BZ + 5
    ;------------------------ 
    Case $C8 To $CF
    ;----------------------
    Case $D0 To $FE
      M()

  EndSelect
EndProcedure

Procedure Next_Code_Address(VAR)
  BZ = VAR                                  ;Start-Adresse
  BZA = PeekB(BZ) & $FF                     ;1.Byte für Override  
    
  Repeat
    OV = 0
    OP = PeekB(BZ) & $FF                    ;Opcode Byte für Byte einlesen
    BZ + 1
    ;------------------------------------------------------------------------------------ 
    Select OP
      ;----------------------
      Case $00 To $03
        M()
      ;----------------------
      Case $04                              ;AL, Ib
        BZ + 1
      ;----------------------
      Case $05                              ;rAX, Iz
        If BZA = $66
          BZ + 2
         Else 
          BZ + 4
        EndIf  
      ;----------------------
      Case $06 To $07
      ;----------------------
      Case $08 To $0B
        M()
      ;----------------------
      Case $0C                              ;AL, Ib
        BZ + 1
      ;----------------------
      Case $0D                              ;rAX, Iz
        If BZA = $66
          BZ + 2
         Else 
          BZ + 4
        EndIf
      ;----------------------
      Case $0E
      ;----------------------
      Case $0F                              ;Shift-Byte (1.Byte=0Fh)
        Codes_Shift()
      ;----------------------
      Case $10 To $13
        M()
      ;----------------------
      Case $14                              ;AL, Ib
        BZ + 1
      ;----------------------
      Case $15                              ;rAX, Iz
        If BZA = $66
          BZ + 2
         Else 
          BZ + 4
        EndIf      
      ;----------------------
      Case $16 To $17
      ;----------------------
      Case $18 To $1B
        M()
      ;----------------------
      Case $1C                              ;AL, Ib
        BZ + 1
      ;----------------------
      Case $1D                              ;rAX, Iz
        If BZA = $66
          BZ + 2
         Else 
          BZ + 4
        EndIf
      ;----------------------
      Case $1E To $1F
      ;----------------------
      Case $20 To $23
        M()
      ;----------------------
      Case $24                              ;AL, Ib
        BZ + 1
      ;----------------------
      Case $25                              ;rAX, Iz
        If BZA = $66
          BZ + 2
         Else 
          BZ + 4
        EndIf
      ;----------------------
      Case $26                              ;zeigt in ES:
        OV = 1
      ;----------------------
      Case $27
       ;----------------------
      Case $28 To $2B
        M()
      ;----------------------
      Case $2C                              ;AL, Ib
        BZ + 1
      ;----------------------
      Case $2D                              ;rAX, Iz
        If BZA = $66
          BZ + 2
         Else 
          BZ + 4
        EndIf      
      ;----------------------
      Case $2E                              ;zeigt in CS:
        OV = 1
      ;----------------------
      Case $2F
       ;----------------------
      Case $30 To $33
        M() 
      ;----------------------
      Case $34                              ;AL, Ib
        BZ + 1
      ;----------------------
      Case $35                              ;rAX, Iz
        If BZA = $66
          BZ + 2
         Else 
          BZ + 4
        EndIf
      ;----------------------
      Case $36                              ;zeigt in SS:
        OV = 1
      ;----------------------
      Case $37
      ;----------------------
      Case $38 To $3B
        M()
      ;----------------------
      Case $3C                              ;AL, Ib
        BZ + 1
      ;----------------------
      Case $3D                              ;rAX, Iz
        If BZA = $66
          BZ + 2
         Else 
          BZ + 4
        EndIf     
      ;----------------------
      Case $3E                              ;zeigt in DS:
        OV = 1
      ;----------------------
      Case $3F To $61
      ;----------------------
      Case $62                              ;Gv, Ma
        M()
      ;----------------------
      Case $63                              ;Ew, Gw
        OP = PeekB(BZ) & $FF     
        BZ + 1
        MSBytes(OP)
      ;----------------------
      Case $64 To $67
        OV = 1
      ;----------------------
      Case $68                              ;PUSH mit DWord-Konstante
        BZ + 4
       ;----------------------
      Case $69                              ;Gv, Ev, Iz
        OP = PeekB(BZ) & $FF     
        BZ + 1      
        If (OP >> 6) <> 3                   ;also nicht Register-Register
          MSBytes(OP)
        EndIf
        If BZA = $66
          BZ + 2
         Else
          BZ + 4
        EndIf
      ;----------------------
      Case $6A                              ;PUSH mit Byte-Konstante, wird auf DWord aufgefüllt
        OP = PeekB(BZ) & $FF     
        BZ + 1
      ;----------------------
      Case $6B                              ;Gv, Ev, Ib
        OP = PeekB(BZ) & $FF     
        BZ + 1      
        If (OP >> 6) <> 3                   ;also nicht Register-Register
          MSBytes(OP)
        EndIf
        BZ + 1
      ;----------------------
      Case $6C To $6F
      ;----------------------
      Case $70 To $7F
        BZ + 1
      ;----------------------
      Case $80                              ;Gruppe 1   Eb, Ib
        OP = PeekB(BZ) & $FF     
        BZ + 1
        MSBytes(OP)
        BZ + 1
      ;----------------------
      Case $81                              ;Gruppe 1   Ev,Iz
        OP = PeekB(BZ) & $FF     
        BZ + 1
        MSBytes(OP)
        If BZA = $66
          BZ + 2
         Else
          BZ + 4
        EndIf
      ;----------------------
      Case $82 To $83                       ;Gruppe 1   Eb/Ev, Ib
        OP = PeekB(BZ) & $FF     
        BZ + 1
        MSBytes(OP)
        BZ + 1
      ;----------------------
      Case $84 To $8B
        M()
      ;----------------------
      Case $8C                              ;Ev, Sw   Segment-Register!
        OP = PeekB(BZ) & $FF     
        BZ + 1
        MSBytes(OP)
       ;----------------------
      Case $8D                              ;Gv, M
        M()
      ;----------------------
      Case $8E                              ;Sw, Ew   Segment-Register!
        OP = PeekB(BZ) & $FF     
        BZ + 1
        MSBytes(OP)
      ;----------------------
      Case $8F                              ;Ev
        OP = PeekB(BZ) & $FF     
        BZ + 1
        MSBytes(OP)
      ;----------------------
      Case $90 To $99
      ;----------------------
      Case $9A                              ;Ap
        MSBytes(OP)
      ;----------------------
      Case $9B To $9F
      ;----------------------
      Case $A0 To $A3
        BZ + 4
      ;----------------------
      Case $A4 To $A7
      ;----------------------
      Case $A8                              ;AL, Ib
        BZ + 1
      ;----------------------
      Case $A9                              ;rAX, Iz
        If BZA = $66
          BZ + 2
         Else 
          BZ + 4
        EndIf       
      ;----------------------
      Case $AA To $AF
      ;----------------------
      Case $B0 To $B7
        BZ + 1
      ;----------------------
      Case $B8 To $BF                       ;MOV 32-Bit-Reg,DWord-Konstante  rXX, Iv
        If BZA = $66
          BZ + 2
         Else
          BZ + 4
        EndIf
      ;----------------------
      Case $C0                              ;Eb, Ib
        OP = PeekB(BZ) & $FF     
        BZ + 1
        MSBytes(OP)
        BZ + 1
       ;----------------------
      Case $C1                              ;Ev, Ib
        OP = PeekB(BZ) & $FF     
        BZ + 1
        MSBytes(OP)
        BZ + 1
       ;----------------------
      Case $C2                              ;near Return mit Wert
        BZ + 2
      ;----------------------
      Case $C3                              ;near Return
      ;----------------------
      Case $C4 To $C5
        BZ + 1
      ;----------------------
      Case $C6                              ;Gruppe11  Eb, Ib
        OP = PeekB(BZ) & $FF     
        BZ + 1
        MSBytes(OP)
        BZ + 1 
      ;----------------------
      Case $C7                              ;Gruppe 11  Ev, Iz
        OP = PeekB(BZ) & $FF     
        BZ + 1
        MSBytes(OP)
        If BZA = $66
          BZ + 2
         Else
          BZ + 4
        EndIf 
      ;----------------------
      Case $C8                              ;Iw, Ib
        BZ + 3
      ;----------------------
      Case $C9                              ;LEAVE
       ;----------------------
      Case $CA                              ;far Return mit Wert
        BZ + 2
      ;----------------------
      Case $CB To $CC
        ;----------------------
      Case $CD                              ;INT Ib
        BZ + 1
      ;----------------------
      Case $CE To $CF                       ;INTO
       ;----------------------
      Case $D0                              ;Eb, 1
        OP = PeekB(BZ) & $FF     
        BZ + 1
        MSBytes(OP)
       ;----------------------
      Case $D1                              ;Ev, 1
        OP = PeekB(BZ) & $FF     
        BZ + 1
        MSBytes(OP)
       ;----------------------
      Case $D2                              ;Eb, CL
        OP = PeekB(BZ) & $FF     
        BZ + 1
        MSBytes(OP)
       ;----------------------
      Case $D3                              ;Ev, CL
        OP = PeekB(BZ) & $FF     
        BZ + 1
        MSBytes(OP)
      ;----------------------
      Case $D4 To $D5
        BZ + 1
      ;----------------------
      Case $D7
      ;---------------------- 
      Case $D8 To $DF                       ;FPU-Instruktionen
        FPU()
      ;----------------------
      Case $E0 To $E7
        BZ + 1
      ;----------------------   
      Case $E8 To $EA
        BZ + 4
      ;----------------------
      Case $EB                              ;Jb
        BZ + 1
      ;----------------------
      Case $EC To $F0
      ;----------------------
      Case $F2
        If (PeekB(BZ) & $FF) = $0F          ;Präfix für SSE
          OV = 1
        EndIf  
      ;----------------------
      Case $F3 
        If (PeekB(BZ) & $FF) = $0F          ;Präfix für SSE        
          OV = 1
        EndIf      
      ;----------------------
      Case $F4 To $F5
      ;----------------------
      Case $F6                              ;Eb   Gruppe 3
        OP = PeekB(BZ) & $FF     
        BZ + 1
        RM = (OP & %00111000) >> 3          ;reg/opcode für Befehl        
        MSBytes(OP)
        If RM = 0                           ;für TEST
          BZ + 1
        EndIf 
      ;----------------------
      Case $F7                              ;Ev   Gruppe 3
        OP = PeekB(BZ) & $FF     
        BZ + 1
        RM = (OP & %00111000) >> 3          ;reg/opcode für Befehl        
        MSBytes(OP)
        If BZA = $66                        ;Operand Override
          If RM = 0
            BZ + 2
          EndIf
         Else 
          If RM = 0 
            BZ + 4
          EndIf 
        EndIf  
       ;----------------------  
      Case $F8 To $FD
      ;----------------------
      Case $FE                              ;Eb
        OP = PeekB(BZ) & $FF     
        BZ + 1
        MSBytes(OP) 
      ;----------------------    
      Case $FF
        OP = PeekB(BZ) & $FF     
        BZ + 1
        MSBytes(OP)
      ;----------------------     
    EndSelect 

    If OV = 0                               ;nur, wenn kein Override
      Break 
    EndIf 
   
  ForEver                                   ;für Overrides

 ProcedureReturn BZ 
EndProcedure

;- hier Test-Code 
Goto Q                                      ;damit Test-Code nicht ausgeführt wird
Code_Start:                                 ;hier Test-Code, es wird nur die erste Instruktion ausgewertet!
  !ADD EAX,1                                ;Länge 3
  ;!IMUL EDX,ECX,12345                       ;6   Zeile drüber dann auskommentieren!
  ;usw.
Code_End:
Q:
;------------------

Last_Code_Address$ = Hex(?Code_Start)       ;für Exception-Handler: ExceptionAddress
Next_Code_Address$ = Hex(Next_Code_Address(?Code_Start))
MessageRequester("Next_Code_Address", "Last_Code_Address :  $" + Last_Code_Address$ + #LFCR$ + "Next_Code_Address : $" + Next_Code_Address$)
Die Code-Mnemonik (also z.B. "MOV EAX,EDX") wird nicht ermittelt, aber dafür gibt es ja den Dis-Assembler! Ist für einen Exception-Handler auch erstmal nicht von Interesse.

Gruß
Helle
Benutzeravatar
Thorium
Beiträge: 1722
Registriert: 12.06.2005 11:15
Wohnort: Germany
Kontaktdaten:

Beitrag von Thorium »

Cool, thx für den Code. Brauch man auch für inline-Hooks.
Zu mir kommen behinderte Delphine um mit mir zu schwimmen.

Wir fordern mehr Aufmerksamkeit für umfallende Reissäcke! Bild
Benutzeravatar
Helle
Beiträge: 566
Registriert: 11.11.2004 16:13
Wohnort: Magdeburg

Beitrag von Helle »

Habe die Dis-Assemblierung von DLL´s hinzugefügt (Download s.o.). Ein zweites (Neben-)Fenster zeigt die Adressen der einzelnen DLL-Funktionen an, so dass im Hauptfenster dort hin navigiert werden kann.
Schwachpunkt ist immer noch die geringe Geschwindigkeit bei grossem Code-Anteil; dies liegt aber am enormen Zeitverbrauch für das Erstellen der Gadgets (AddGadgetItem sowie Colorierung; möchte darauf aber nicht verzichten).
Demnächst ist die 64-Bit-Dis-Assemblierung dran.

Viel Spaß!
Gruß
Helle
real
Beiträge: 468
Registriert: 05.10.2004 14:43

Beitrag von real »

Ich habe gerade keinen praktischen Nutzen für einen/den Disassembler. Aber ich muss zumindest meinen Respekt vor dem Programm zum Ausdruck bringen! Das ist schon klasse.

:allright:
Benutzeravatar
Helle
Beiträge: 566
Registriert: 11.11.2004 16:13
Wohnort: Magdeburg

Beitrag von Helle »

Habe soeben die 32/64-Bit-Version hochgeladen (ZIP, 28KB). Der 64-Bit-Teil wird noch weiter vervollständigt und irgendwo lauert sicher noch eine kleine (? :D ) Wanze; meine Tests liefen aber erstmal durch. Unter Win32 sind auch 64-Bit-Files disassemblierbar und umgekehrt.

Gruß
Helle
Benutzeravatar
Helle
Beiträge: 566
Registriert: 11.11.2004 16:13
Wohnort: Magdeburg

Re: Simpler 32/64-Bit-Dis-Assembler in PB

Beitrag von Helle »

Hallo,
ich habe die letzte Version (völlig neu überarbeitet, mit Disassemblierung Programme im Speicher usw.) vorhin hochgeladen (Link s.o.). AVX ist noch nicht komplett; kommt, wenn eine Sandy Bridge (demnächst) auf dem Mutterbrett tickt. Da das Ganze aber jetzt überschaubar ist, wird die Speed-Frage wieder aktuell. Der reine Disassembler-Teil ist nicht die Bremse; wenn ich den durch z.B. die BeaEngine-DLL ersetze, wird´s auch nicht (viel) schneller. "Schuld" ist wie oben schon festgestellt die Verwendung von AddGadgetItem (also ListIconGadget usw.). Praktisch ist dies ja schon, aber eben verflucht langsam. Hat jemand eine schnellere Alternativ-Lösung parat? Ich könnte es direkt per ASM im Speicher verwalten, aber meine Zielstellung war eben, weitestgehend PB zu verwenden.
Viel Spaß!
Helle
Antworten