GetKeyState, interne Darstellung des Rückgabewertes



  • Hallo,

    Mit der Funktion GetKeyState kann ich abfragen, ob eine Taste gedrückt wurde. Ist dies der Fall, werden nach jedem Tastendruck im Register EAX abwechselnd die hexadezimalen Werte 'FFFFFF80' und 'FFFFFF81' übergeben. Leider verstehe ich diese interne Darstellung nicht so richtig. Beim Rückgabewert handelt es sich um den Datentyp 'SHORT', also eine 16-Bit Zahl, die im 32-Bit Register EAX übergeben wird. Im Falle einer Tastenbetätigung wird das höchstwertige Bit, also das Linke, auf '1' gesetzt. Ist das linke Bit=1, wird die Zahl als negative Zahl interpretiert. Die '80' am Ende des Wertes hängen wohl mit der internen Datendarstellung im Little Endian Format zusammen. Soweit verstehe ich es (hoffentlich) richtig.
    Kann mir bitte mal jemand genau erklären, warum der Wert 'FFFFFF80' übergeben wird, obwohl letztendlich nur das höchstwertige Bit auf '1' gesetzt wurde.

    Viele Grüße
    hardi



  • Es ist irrelevant wie die die anderen Bits aussehen - entscheiden sind nur die Bits 0 und 15, da diese Dokumentiert sind.
    Die andern Bits hängen davon ab, wie der Rückgabewert gebildet wird.



  • hardi schrieb:

    Kann mir bitte mal jemand genau erklären, warum der Wert 'FFFFFF80' übergeben wird, obwohl letztendlich nur das höchstwertige Bit auf '1' gesetzt wurde.

    Das kann man auch als arithmetische Berücksichtigung der Werteverhältnisse verstehen.
    Wenn man 0 - 1 rechnet, also (16Bit Hex) 0000 - 0001, dann kommt FFFF raus. FFFE wäre dann -2 usw. Du kannst dann z.B. 3 - 2 rechnen durch FFFE + 3. Additionen lassen sich in der Digitalwelt etwas einfacher rechnen/konstruieren als Abzüge.

    Wenn man dem Rechner Komplimente machen will..äh quatsch, den kleinsten Wert in eine Komplementärzahl umwandeln will, dann geht das in der Digitalwelt recht einfach, 0001 -> 1110 + 1 also alle Bits umwandeln, und eins draufzählen.
    Nochmal gezeigt am Beispiel 2: 0010 (alle Bits umkehren)-> 1101 + 1 = 1110 (Dh +1)



  • hardi schrieb:

    Kann mir bitte mal jemand genau erklären, warum der Wert 'FFFFFF80' übergeben wird, obwohl letztendlich nur das höchstwertige Bit auf '1' gesetzt wurde.

    Bei mir castet die Funktion GetKeyState tatsächlich AX (Rückgabe von NtUserGetKeyState) vorzeichenbehaftet auf EAX, d. h. ein negatives SHORT wird zu einem negativen INT mit demselben Absolutwert. Das geschieht mit dem Assemblerbefehl MOVSX EAX, AX . Die '80' hat sicherlich mit dem Format der KeyState-Tabelle zu tun (http://msdn.microsoft.com/en-us/library/windows/desktop/ms646299.aspx). Diese Tabelle ist ein Byte-Array, bei dem jeweils Bit7 und Bit0 ('80') die gewünschten Informationen beinhalten. Intern werden die Werte für die KeyState-Tabelle und das 'FF80' für NtUserGetKeyState auf dieselbe Weise ermittelt (OR EDI, 0xFF80).

    Damit Dir die Sache mit dem Absolutwert klarer wird, hier ein kleines C-Programm:

    #include <stdio.h>
    
    int main( void )
    {
    	signed char c = 0x81;
    	short s = 0xFF81;
    	int i = 0xFFFFFF81;
    
    	printf (" 8 Bit: %i\n",c);
    	printf ("16 Bit: %i\n",s);
    	printf ("32 Bit: %i\n",i);
    
    	return 0;
    }
    

    Du siehst, der Wert bleibt immer derselbe (-127), egal welche Variable Du Dir anzeigen lässt. Damit kann ein Programm ohne Probleme auf den Wert testen: z. B. if (-127 == GetKeyState('A'))...
    Allerdings hat masm recht: Nur Bit15 und Bit0 sind dokumentiert, d. h. alle anderen Bits können auch ganz andere Werte haben - und ein Test auf den Wert kann fehlschlagen.

    viele grüße
    ralph



  • Zuerst einmal vielen Dank für Eure Antworten. Aber die Frage, wie der Rückgabewert von hexadezimal 'FFFFFF80' gebildet wird, beschäftigt mich immer noch. Wird im Falle einer Tastenbetätigung das höchstwertige Bit eines Wertes vom Datentyp 'SHORT' auf '1' gesetzt, sollte das doch hexadezimal '8000' ergeben. Aber warum wird daraus der Wert 'FFFFFF80' gebildet? Die '8' taucht ja noch auf, aber wieso erscheint die '0' nur einmal und nicht dreimal?
    Sorry, ich bin eben einer von denen, die es manchmal ganz genau wissen möchten, kann eben auch nicht aus meiner Haut ...

    Viele Grüße
    hardi



  • hardi schrieb:

    Zuerst einmal vielen Dank für Eure Antworten. Aber die Frage, wie der Rückgabewert von hexadezimal 'FFFFFF80' gebildet wird, beschäftigt mich immer noch. Wird im Falle einer Tastenbetätigung das höchstwertige Bit eines Wertes vom Datentyp 'SHORT' auf '1' gesetzt, sollte das doch hexadezimal '8000' ergeben. Aber warum wird daraus der Wert 'FFFFFF80' gebildet? Die '8' taucht ja noch auf, aber wieso erscheint die '0' nur einmal und nicht dreimal?
    Sorry, ich bin eben einer von denen, die es manchmal ganz genau wissen möchten, kann eben auch nicht aus meiner Haut ...

    Viele Grüße
    hardi

    *Soifz* Also nochmal:

    Der eigentlich zentrale Wert ist die '80' bzw '81' bzw '00' bzw. '01'. Das sind die möglichen Werte in der KeyState-Tabelle. Wandelt man dieses Byte (z. B. '80') in eine vorzeichenbehaftete Zahl um, dann erhält man -128. Erweitert man diese Zahl in ein (vorzeichenbehaftetes SHORT), dann braucht man den Hexadezimalwert 'FF80', damit man wieder auf -128 dezimal kommt. Erweitert man das SHORT in ein INT, braucht man den Hexadezimalwert 'FFFFFF80', damit man wieder auf -128 kommt. Ist einem das nicht geheuer oder will man das irgendwann ändern, dokumentiert man nur Bit15, obwohl Bit31-Bit7 identisch sind.

    Wenn aber nur Bit15 und Bit0 dokumentiert sind, dann darf Microsoft mit den übrigen Bits machen was es will. Da dürfen Nullen und Einsen stehen, wie sie gerade daherkommen. Sei froh, dass sie da keine Teufelsanbetung hineingecodet haben - oder etwa doch? 🙂

    viele grüße
    ralph


Anmelden zum Antworten