Endlosschleife in meinem Debugger

  • VB.NET
  • .NET (FX) 1.0–2.0

Es gibt 17 Antworten in diesem Thema. Der letzte Beitrag () ist von Vultrax.

    Endlosschleife in meinem Debugger

    Ich schreibe ihm Moment einen kleinen Debugger, womit ich durch Hardware-Haltepunkte auf Ereignisse innerhalb einer anderen Anwendung reagieren kann.
    Wenn die Adresse von meinem Haltepunkt ausgelöst wird, erhalte ich die Nachricht "Breakpoint reached!". Das Problem ist nun, dass mein Debugger nicht zur nächsten Anweisung im Speicher springt und stattdessen mein Haltepunkt in einer Endlosschleife ausgelöst wird (der Haltepunkt soll nur ausgelöst werden, wenn der Code ausgeführt wird).



    VB.NET-Quellcode

    1. Do
    2. WaitForDebugEvent(DebugEvent, &HFFFFFFF)
    3. If DebugEvent.Exception.ExceptionRecord.ExceptionCode = EXCEPTION_SINGLE_STEP Then
    4. If DebugEvent.Exception.ExceptionRecord.ExceptionAddress = BreakpointAddress Then
    5. System.Console.WriteLine("Breakpoint reached!")
    6. End If
    7. End If
    8. ContinueDebugEvent(DebugEvent.dwProcessId, DebugEvent.dwThreadId, DBG_CONTINUE)
    9. Loop

    In einem Thread auf stackoverflow schreibt jemand, dass man die Resume Flag (EFlag) setzen soll, allerdings hat er kein Beispiel gezeigt oder einen Wert genannt, den man in das Context.EFlag-Register schreiben könnte.
    Die Antwort aus dem Thread: stackoverflow.com/a/38479357

    VB.NET-Quellcode

    1. Do
    2. WaitForDebugEvent(DebugEvent, &HFFFFFFF)
    3. If DebugEvent.Exception.ExceptionRecord.ExceptionCode = EXCEPTION_SINGLE_STEP Then
    4. If DebugEvent.Exception.ExceptionRecord.ExceptionAddress = BreakpointAddress Then
    5. Dim hThread2 As IntPtr = OpenThread(&H1F03FF, False, DebugEvent.dwThreadId)
    6. If GetThreadContext(hThread2, Context) Then
    7. Context.EFlags = &H0 'Welcher Wert soll hier rein?
    8. SetThreadContext(hThread2, Context)
    9. End If
    10. CloseHandle(hThread2)
    11. System.Console.WriteLine("Breakpoint reached!")
    12. End If
    13. End If
    14. ContinueDebugEvent(DebugEvent.dwProcessId, DebugEvent.dwThreadId, DBG_CONTINUE)
    15. Loop

    Wen Ihr mir weiterhelfen könntet, wäre ich sehr dankbar! :)
    "Denken ist die schwerste Arbeit, die es gibt. Das ist wahrscheinlich auch der Grund, warum sich so wenig Leute damit beschäftigen." - Henry Ford

    Dieser Beitrag wurde bereits 12 mal editiert, zuletzt von „Vultrax“ ()

    die context struct ist einfach nur nen thread context in welchem natürlich die register abgelegt werden müssen um den thread entsprechend fortsetzen zu können, deshalb sollte man einfach allgeim für die register nachgucken können:
    en.wikipedia.org/wiki/FLAGS_register

    jetzt würde ich das flags register nicht einfach überschreiben, sondern viel eher das jeweilige bit setzen.

    Versuch also mal:

    Visual Basic-Quellcode

    1. Context.EFlags = Context.EFlags Or &H100

    was dem Trap-Flag entspricht oder eben auch mit &H10000 was dem Resume-Flag entspricht...
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    @jvbsl - Danke für Deine Antwort!

    Es ist schon ein wenig komplexer als ich es mir vorgestellt habe. Ich dachte, wenn ich meinen Haltepunkt in eines der Dr0- bis Dr3-Register setze, der Prozess die Ausführung stoppt und ich schlicht mit ContinueDebugEvent die Ausführung fortsetzen kann, ohne weitere Register ändern zu müssen.

    Mit der gesetzten Flag (0x10000) im EFlag-Register springt der Prozess nun auch ordnungsgemäß zu nächsten Anweisung.



    jvbsl schrieb:

    jetzt würde ich das flags register nicht einfach überschreiben, sondern viel eher das jeweilige bit setzen.

    Wie genau meinst du das? Die Flag muss doch überschrieben werden, damit die Ausführung fortgesetzt werden kann, oder nicht?

    Was genau bewirkt das Or hier? Der Wert 0x100 wird ja auch so gesetzt.

    VB.NET-Quellcode

    1. Context.EFlags = Context.EFlags Or &H100

    Vielen Dank erstmal für Deine Hilfe! :)
    "Denken ist die schwerste Arbeit, die es gibt. Das ist wahrscheinlich auch der Grund, warum sich so wenig Leute damit beschäftigen." - Henry Ford
    nunja 0x100 ist ja binär "1 00000000" und entscheidend für das fortsetzen ist nur die 1, an den nullen sollten theoretisch beliebige Werte stehen können. Bzw. halt die Werte die bereits da stehen.Das Or ist hier eben Bitwise-Or. Was eben für jedes einzelne Bit zweier Zahlen eine Or-Überprüfung macht(1 als Ergebnis, wenn eines der beiden bits oder auch beide 1 sind und wenn beide 0 sind ist das Ergebnis auch 0).

    Das ist die Bedeutung eines BitFlags wobei jedes Bit eine andere Eigenschaft/Bedeutung hat welche voneinander unabhängig sind. Man kann sie auch als unabhängige Boolean Values sehen.
    Jetzt willst du nur ein einzelnes Bit setzen, weil du nur eine einzelne Eigenschaft verändern möchtest. Deshalb verwendet man dieses Bitwise-Or.

    Ob du mit 0x100 oder 0x10000 verodern musst weiß ich nicht, aber oben scheint es ja mit 0x10000 funktioniert zu haben^^
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    @jvbsl

    Binärcode ist auf jeden Fall nochmal ein Thema, mit dem ich mich genauer beschäftigen muss.
    Das Or vergleicht also jede Zahl (Bit) in einem Block (00000001 00000000) mit den Zahlen (Bits) in den Blöcken der anderen Zahl, korrekt? (Ein Block (8 Bits) stellt einen Byte da, oder?)

    So wie ich es verstanden habe, wird die Trap Flag (0x100) dafür genutzt, die Ausführung bei der nächsten Anweisung zu stoppen und die Continue Flag (0x10000), um die Ausführung einfach fortzusetzen.
    "Denken ist die schwerste Arbeit, die es gibt. Das ist wahrscheinlich auch der Grund, warum sich so wenig Leute damit beschäftigen." - Henry Ford
    Or vergleicht nicht Or verrechnet:
    (x entspricht einer Variablen, hier also 0 oder 1)
    1 Or x = 1
    x Or 1 = 1
    0 Or 0 = 0

    und das ganze nun bitwise, heißt eben genau das oben auf jedes Bit anzuwenden z.B.

    Quellcode

    1. (dez) 10 Or 3 = 11
    2. (bin) 1010 Or 11 =
    3. 1010
    4. Or 0011
    5. ________
    6. 1011


    Edit: achja 8 bit werden in aller Regel als Byte bezeichnet, das ist korrekt. Jedoch wenn man es ganz genau nimmt kann es die unterschiedlichsten bedeutungen haben und z.B. die kleinstmögliche Speichergröße sein(was aber auf den meisten heutigen Architekturen zumindest alles über Microcrontroller eben 8 Bit enstpricht).
    als Word wird dann eine Zahl von 16-Bit bezeichnet DWord(Double Word) 32-Bit und LWord(Long Word) 64 Bit.

    Gern gemachter Fehler dabei ist bezeichnungen wie short/int/long dafür zu verwenden, diese sind aber in ihrer größe nicht eindeutig und hängen von Sprache und Architektur ab.
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „jvbsl“ ()

    @jvbsl

    Ich habe nicht das Gefühl, dass es sich hierbei um Raketenwissenschaften handelt, dennoch qualmt mir ganz schön der Kopf.

    Wenn ich dein Beispiel richtig verstanden habe, müssten meine Ergebnisse korrekt sein:

    Quellcode

    1. 0010
    2. 1101
    3. = 1111

    Quellcode

    1. 0110
    2. 0100
    3. = 0110

    Quellcode

    1. 1000
    2. 0001
    3. = 1001


    Die Mechanik von Or verstehe ich dennoch immer noch nicht so genau.

    VB.NET-Quellcode

    1. Context.EFlags = Context.EFlags Or &H10000

    Wenn EFlags nun 0x40 (Binär: 0100 0000) ist und ich die Continue Flag 0x10000 (Binär: 0001 0000 0000 0000 0000) setzen möchte, bewirkt Or also nun, dass der zugeteilte Wert am ende so aussieht 0x10040 (Binär: 0001 0000 0000 0100 0000), korrekt?
    Was ist, wenn ich die die Flag wieder auf 0x40 haben möchte?


    Ich gebe mir voll Mühe! :S
    "Denken ist die schwerste Arbeit, die es gibt. Das ist wahrscheinlich auch der Grund, warum sich so wenig Leute damit beschäftigen." - Henry Ford

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Vultrax“ ()

    Deine ersten Berechnungen passen.

    Vultrax schrieb:

    Wenn EFlags nun 0x40 (Binär: 0100 0000) ist und ich die Continue Flag 0x10000 (Binär: 0001 0000 0000 0100 0000) setzen möchte, bewirkt Or also nun, dass der zugeteilte Wert am ende so aussieht 0x10040 (Binär: 0001 0000 0000 0100 0000), korrekt?
    Fast. Kleiner C&P-Fehler: 0x10000 = 0001 0000 0000 0000 0000
    zur "Mechanik von Or": Oder-Gatter - obwohl es hier eher um Eletrotechnik/Elektronik geht.
    Der Sinn hinter Or - zumindest hier: einen Schalter in einer Schalterreihe einschalten. Wenn Du 8 Ja-Nein-Einstellungen hast, kannst Du die alle in VB als einzelne Boolean-Variablen führen. Oder Kompakt als eine Variable, die eben als Stellen einer binär dargestellten Zahl repräsentiert werden. Hättest Du z.B. 1001 0110, dann steht jede 1 für eingeschaltet, jede 0 für ausgeschaltet. Lass es z.B. Lichtschalter oder die Optionen für eine Schrift sein. Ganz allgemein eben Ja-Nein-Einstellungen. Bleiben wir bei Text: Du könntest sagen: der Schalter ganz links steht für fett geschrieben, danach kommt kursiv, dann hochgestellt, unterstrichen, durchgetrichen usw. Wenn Du Deine Schrift nun so eingestellt hast, dass sie erstmal nur fett geschrieben wird, dann wäre die Zahl, die die Einstellungen repräsentiert: 1000 0000. Nun willst Du die Schrift zusätzlich kursiv machen. Also den "2. Schalter einschalten". Dazu schreibst Du z.B. (ja, es geht auch eleganter, aber es geht um die Erklärung):

    VB.NET-Quellcode

    1. FontSettings = FontSettings Or ItalicSetting
    ItalicSetting ist eine Zahl, die mit 0100 0000 definiert ist. Und durch das Or wird so aus den Anfangseinstellungen 1000 0000 nun 1100 0000 => fett und kursiv.

    Wenn Du einen Schalter jedoch deaktivieren willst, arbeite mit And:

    VB.NET-Quellcode

    1. FontSettings = FontSettings And NotItalicSetting
    NotItalicSetting definiere ich als 1011 1111. And bewirkt, dass im Ergebnis nur dann eine 1 steht, wenn in beiden Ausgangssignalen an gleicher Position eine 1 steht, sonst wird das zu 0:
    fett und kursiv: 1100 0000
    NotItalic: 1011 1111

    Brainfuck-Quellcode

    1. 1100 0000
    2. And 1011 1111
    3. ---------
    4. 1000 0000

    PS: Ich bin elektrotechnisch Laie. Alle Profis/Experten mögen bitte etwas Nachsicht haben.

    Hm ... Ich weiß zwar nicht, warum das angeblich Brainfuck-Code sein soll, da ich die normalen [code][ /code]-Tags verwendet habe, aber egal.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    @VaporiZed

    Ahhh! So langsam verstehe ich das!
    Nun verstehe ich auch den Satz, der auf Wikipedia steht:
    Diese Technik wird eingesetzt, um Speicherplatz zu sparen, wenn Programme sehr viele Boolesche Werte verwalten müssen.

    Wie sieht das nun mit Werten wie den oben benötigen Flags aus? Das Or setzt nun alle Bits auf 0 die nicht der Flag zugehörig sind, oder?
    Kannst du mir dein Boolean-Beispiel noch mal mit den Flags veranschaulichen?
    "Denken ist die schwerste Arbeit, die es gibt. Das ist wahrscheinlich auch der Grund, warum sich so wenig Leute damit beschäftigen." - Henry Ford

    Vultrax schrieb:

    Das Or setzt nun alle Bits auf 0 die nicht der Flag zugehörig sind, oder?
    Kannst du mir dein Boolean-Beispiel noch mal mit den Flags veranschaulichen?
    Ich glaube, dass da bei einem von uns noch ein Denkfehler drin ist. Ein Flag ist eine Art Einstellungsschalter. Also eine spezialisierte Ein-Aus-Geschichte, ähnlich einer Boolean-Variable, auch wenn man dank Bit-Operationen keine Booleans, sondern (passende) Zahlen verwendet. Boolean-Variablen kann man auch für andere Dinge nutzen (ich glaub, die Verwendung von Boolean-Variablen brauch ich nicht zu erklären).
    Ein Beispiel (auch wenn's praxisfern ist):

    VB.NET-Quellcode

    1. Public Class MySpecialRadio
    2. Private CanReceiveDabPlus, IsMute, CanRememberStations, HasAntenna, IsMobile As Boolean
    3. '...
    4. End Class

    5 Booleans. Naja. Geht noch, ist aber bei noch mehr Einstellungen irgendwann langatmig.
    Jetzt kann man dahergehen und sagen:

    VB.NET-Quellcode

    1. Public Class MySpecialRadio
    2. Private Properties As Integer
    3. '...
    4. End Class

    Dann kann man hergehen und sich notieren:
    CanReceiveDabPlus = 1 (= 00001)
    IsMute = 2 (= 00010)
    CanRememberStations = 4 (= 00100)
    HasAntenna = 8 (= 01000)
    IsMobile = 16 (= 10000)
    Immer 2er Potenzen eben. Und dann kann man sich mit Or sein Radio zusammenbasteln.
    Properties = HasAntenna Or CanReceiveDabPlus
    => 01000 Or 00001 = 01001 (= 9, also aus 8 + 1; man kann also sagen, dass Or wie ein Plus wirkt)
    Und auch erweitern: Properties = Properties Or IsMobile (01001 Or 10000 = 11001)
    Das kleine logisch-denken-aber-falsch-verstehen-Problem bei Bitoperationen ist, dass Or wie ein "gesprochenes" Und wirkt: "Die neuen Radioeigenschaften setzen sich zusammen aus den bisherigen UND der neuen Eigenschaft."

    Anders nun And: Properties = HasAntenna And CanReceiveDabPlus (11001 And 00001 = 00001); Man verwendet es eher als eine Art Überprüfung, ob ein Schalter gesetzt ist, also ob das Radio eine bestimmte Eigenschaft hat. So kann man schreiben:

    VB.NET-Quellcode

    1. If (Properties And CanReceiveDabPlus) = CanReceiveDabPlus Then ...
    da man so rausbekommt, ob das Radio DAB+ empfangen kann. Kann es das nicht (01000), ergibt sich bei 01000 And 00001 eben 00000 (gar nix) und nicht 00001 (kann DAB+).

    Zum Ausschalten müsste man auch mit And arbeiten, allerdings mit inversen Werten: will man bei den Radioeigenschaften (01001) die DAB+-Eigenschaft (00001) abschalten, verwendet man den inversen DAB+-Wert (11110). Dann erhält man mit And: 01001 And 11110 = 01000 => das letzte Bit wurde auf 0 gesetzt, was der Radiogesamteigenschaft entspricht: HasAntenna = True; CanReceiveDabPlus = False.

    Anmerkung: Wer mit Enum-Flags anfangen will, nur zu. Mir geht's hier erstmal um's Verständnis.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    @VaporiZed

    Fühlt sich ein wenig so an, als ob ich es nun verstanden habe ... Könntest du mir vielleicht sowas wie eine kleine Aufgabe zum lösen geben? :)
    Ich bin wirklich dankbar, dass Du Dir die Mühe machst, es mir einfach zu erklären und so geduldig bist!
    "Denken ist die schwerste Arbeit, die es gibt. Das ist wahrscheinlich auch der Grund, warum sich so wenig Leute damit beschäftigen." - Henry Ford
    Stimm ich nicht zu, da du damit anmachst, falls es bereits aus war etc... Und um das zu verhindern bräuchtest du nen if. Und das wär echt unnötiges branching...
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    @Vultrax: Nur nochmal zum Klarmachen: Du kannst mit Not noch Zahlen in ihr bitweises Gegenteil umwandeln:

    Quellcode

    1. 00111001010 = 00111001010
    2. Not 00111001010 = 11000110101

    Somit bräuchtest Du nicht gegenteilige Einstellungen definieren, sondern kannst, um bei dem Radio zu bleiben, auch einfach sagen, um ein DAB+-, Antennen-, Mobilradio (Einstellung = 11001) die DAB+-Eigenschaft (00001) wegzunehmen, auch schreiben: Properties = Properties And Not CanReceiveDabPlus. Das ergäbe dann (Berechnung, kein Code!): Properties = 11001 And Not 00001 = 11001 And 11110 = 11000

    Das mit dem Übungsaufgaben: Sorry, da muss ich passen. Ich weiß, das Forum ist dazu da, um was Neues zu lernen. Aber das geht dann doch irgendwie in ne falsche Richtung. Vielleicht die anderen? Der Punkt ist, dass ich es zwar halbwegs verstehe, aber selbst kaum damit arbeite. Vor nem Jahr hatten wir mal an anderer Stelle das Thema.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VaporiZed“ ()

    @EaranMaleasi

    Wenn man die Werte kennt, ist die Verwendung von XOR wohl sicherlich hilfreich.

    @VaporiZed

    Ich habe dazu auch eine schöne Seite gefunden: whatis.techtarget.com/definiti…XOR-NOT-NAND-NOR-and-XNOR
    Wenn man erstmal die Funktionsweise dahinter verstanden hat, geht das schon deutlich besser von der Hand.

    Schade, dennoch hast Du und @jvbsl mir schon sehr gut damit geholfen, es zu verstehen und bald auch umsetzen zu können, vielen Dank dafür!
    Ich werde nochmal einen Blick in dein Thread werfen, den Du am Ende verlinkt hast.
    "Denken ist die schwerste Arbeit, die es gibt. Das ist wahrscheinlich auch der Grund, warum sich so wenig Leute damit beschäftigen." - Henry Ford

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Vultrax“ ()

    Eines der geschicktesten Gesetze ist finde ich das hier:
    de.wikipedia.org/wiki/De_Morgansche_Gesetze

    Damit kann man dann solche Dinge machen.

    Quellcode

    1. a And b = Not ((Not a) Or (Not b))


    Oder auch einfach so über logik der Werte:

    Quellcode

    1. a Xor b = (a and (Not b)) or ((Not a) and b)

    Denn wenn man überlegt isst a Xor b nur 1 wenn a ungleich b und das ist oben durch die Fallunterscheidung gegeben.

    Wenn du Minecraft kennst, dann entspricht eine einfache Redstone Verbindung einem Or und eine Redstone torch einem Not.
    Und mit Or und Not allein kann man bereits alle logischen Schaltungen machen. Denn aus Not und Or kann man logischerweiße Nor machen, man kann wie oben gezeigt auch ein And machen somit logischerweiße wieder auch ein Nand. Und Xor wurde auch schon gezeigt. Und so kann man weiter machen ;)
    Und so geht das in Minecraft auch, dass man sogesehen alle möglichen logischen Schaltungen machen kann, auch wenn die groß werden :D

    Edit: btw. reicht auch ein NOR alleine um alles zu machen, da man mit NOR(beide inputs gleich) ein Not machen kann und somit aus dem NOR ein OR und man ist wieder am anfang ;) Und And und Not geht auch, ist also nicht nur Or und Not, gibt so noch ein paar kombinationen, aber du wirst immer eine Möglichkeit zur Negierung benötigen
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    @jvbsl - Bitte verzeihe mir meine verspätete Antwort!

    Das finde ich wirklich interessant, da es tatsächlich Spieler gibt, die bereits einen funktionsfähigen Computer mit Redstone-Verbindungen ohne Mods in Minecraft gebaut haben.



    Auch wenn mir die ungefähre Funktionsweise eines Computers doch denke ich bekannt ist, kann ich mir dies nun schon deutlich besser vorstellen als vorher.
    Dank Dir und VaporiZed verstehe ich nun endlich, wie man nur bestimmte Rechte verwenden kann statt einfach immer nur auf ALL_ACCESS zu setzen.
    "Denken ist die schwerste Arbeit, die es gibt. Das ist wahrscheinlich auch der Grund, warum sich so wenig Leute damit beschäftigen." - Henry Ford