Word aus 2 Byte erstellen fehlerhaft

    • Offizieller Beitrag

    Auch wenn es selten ist: Heute habe auch ich mal eine Frage. :D
    Hat jemand eine Erklärung für dieses Problem:
    Wenn ich eine Variable vom Typ 'Word' aus deren Lo- und HiByte erstelle, erhalte ich korrekte Werte nur für positive Word.
    Wo steckt da der Fehler? Habe es extra mit zwei völlig verschiedenen Methoden zur Erstellung der Word-Variable probiert. Das Ergebnis ist identisch.
    (Wofür man sowas braucht? Nun, z.B. werden Tastaturinfos auf Wordbasis übermittelt mit getrennten Werten im LoByte und HiByte.)

    Spoiler anzeigen
    [autoit]

    #cs
    WORD LOBYTE HIBYTE
    513 1 2
    258 2 1
    -2 254 255
    -257 255 254
    #ce

    [/autoit] [autoit][/autoit] [autoit]

    Local $aByte[4][3] = [[513,1,2],[258,2,1],[-2,254,255],[-257,255,254]]

    [/autoit] [autoit][/autoit] [autoit]

    For $i = 0 To 3
    ConsoleWrite('_MakeWord_1 [' & $aByte[$i][1] & ', ' & $aByte[$i][2] & '] erwartet: ' & $aByte[$i][0] & ', Func: ' & _MakeWord_1($aByte[$i][1], $aByte[$i][2]) & @CRLF)
    ConsoleWrite('_MakeWord_2 [' & $aByte[$i][1] & ', ' & $aByte[$i][2] & '] erwartet: ' & $aByte[$i][0] & ', Func: ' & _MakeWord_2($aByte[$i][1], $aByte[$i][2]) & @CRLF & @CRLF)
    Next

    [/autoit] [autoit][/autoit] [autoit]

    Func _MakeWord_1($iLo, $iHi)
    Return BitOR(BitShift($iHi, -8), BitAND($iLo, 0xFF))
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _MakeWord_2($iLo, $iHi)
    Local $tWord = DllStructCreate("WORD")
    Local $tBytes = DllStructCreate("BYTE;BYTE;", DllStructGetPtr($tWord))
    DllStructSetData($tBytes, 1, $iLo)
    DllStructSetData($tBytes, 2, $iHi)
    Return DllStructGetData($tWord, 1)
    EndFunc

    [/autoit]
  • Hallo BugFix,

    wenn es denn unbedingt vorzeichenbehaftet sein soll, ginge das so:

    [autoit]

    Func _MakeWord_1($iLo, $iHi)
    Local $Word = BitOR(BitShift($iHi, -8), BitAND($iLo, 0xFF))
    If $Word > 0x7FFF Then $Word = BitOR($Word, 0xFFFF0000)
    Return $Word
    EndFunc

    [/autoit]

    Ich bin mir allerdings nicht sicher, ob der Datentyp WORD überhaupt vorzeichenbehaftet sein kann. Wäre das dann nicht eher SHORT?

    [autoit]

    Func _MakeWord_2($iLo, $iHi)
    Local $tWord = DllStructCreate("SHORT")
    Local $tBytes = DllStructCreate("BYTE;BYTE;", DllStructGetPtr($tWord))
    DllStructSetData($tBytes, 1, $iLo)
    DllStructSetData($tBytes, 2, $iHi)
    Return DllStructGetData($tWord, 1)
    EndFunc

    [/autoit]

    Zu spät, aber immerhin!

  • Zitat

    Klar, ist ja logisch - "Word = unsigned 16 Bit integer"

    Klassiker, man "setzt" die richtigen Bits und Bytes, aber was man "ausliest", das steht auf einem ganz anderen Blatt! Dazu kommt noch das Intelsche Little Endian, und die Verwirrung ist komplett^^. Hat mich früher auch schon einige Nachtschichten gekostet, daher kann ich das nachvollziehen :D

  • Ich hab das bis jetzt immer so gemacht:

    Spoiler anzeigen
    [autoit][/autoit] [autoit][/autoit] [autoit]

    $Word1 = _MakeWord_2(2, 3)
    $Word2 = _WordFrom2Byte(2, 3)

    [/autoit] [autoit][/autoit] [autoit]

    ConsoleWrite($Word1 & @cr)
    ConsoleWrite($Word2 & @cr)

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func _WordFrom2Byte($iLo, $iHi)
    Return BitShift($iHi, -8) + $iLo
    EndFunc

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func _MakeWord_2($iLo, $iHi)
    Local $tWord = DllStructCreate("SHORT")
    Local $tBytes = DllStructCreate("BYTE;BYTE;", DllStructGetPtr($tWord))
    DllStructSetData($tBytes, 1, $iLo)
    DllStructSetData($tBytes, 2, $iHi)
    Return DllStructGetData($tWord, 1)
    EndFunc

    [/autoit]

    Aber nur weil's kürzer ist. :P


    Edit: Fehler korrigiert.