Jump to content

Help with 2's complement / data conversion/Negative numbers - (Moved)


Recommended Posts

Good afternoon,
I'm looking for some help with my project, I am working with negative 32bit integers I receive from an snmp request, but I have no issue here* 
once these numbers are processed they are no longer negative, which I require here is a code extract this cannot run** as many elements are missing and I cannot share the broader software this is part of,
The value of $fiberint would be -400 from the snmp table, although it will be 65136 ($testfiber is just for comparison) before I have made any modifications to it, its binary value is 1111111001110000, that will make its signed 2sc -400 the value I am looking to utilize, How can I create a function to assign this value to a variable
This snippet is part of a loop and this number cannot be hardcoded as it will change due to external factors


Am I approaching this issue entirely wrong? doesn't change much to completely start over its only one method that uses negative numbers, I have scanned through many of the forum mentions of these topics and looked through the help file, only bitshift/ bitrotate stuck out
Sorry if this is a small bit messy, any and all ideas welcome, I only have a few weeks with autoIt but willing to learn

$Traffic_Prioritization = $SNMP_Util[1][1]

      Local $testfiber = 65136

      
      Local $fiberint = Int($Traffic_Prioritization, $NUMBER_32BIT) ; $NUMBER_AUTO (0) $NUMBER_32BIT (1) $NUMBER_64BIT (2) 

      Local $fiberbin = Binary($Traffic_Prioritization)
      
      Local $fiberhex = Hex($fiberint)



      Local $testfiberbin = Binary($testfiber)
      
      $Traffic_Prioritization_Array[$i - 1] = $fiberint


    GUICtrlSetData($idMyedit,"sfpport test: " & $fiberint & @CRLF,1)
    GUICtrlSetData($idMyedit,"fiber bin test: " & $fiberbin & @CRLF,1)

 

I Love It When a *Autoit Script* Comes Together

Link to comment
Share on other sites

Not exactly sure what you asking us...But what I decoded is that you want to convert -400 int into a ushort.  Because -400 in a 32bit uint equals 4294966896, but -400 in a ushort is 65136.

Anyway here a simple way to perform the conversion : 

Local $iNeg = -400, $iPos
Local $tConv16 = DllStructCreate("ushort value")  ; 16 bits conversion
Local $tConv32 = DllStructCreate("uint value")    ; 32 bits conversion

$tConv16.value = $iNeg
$iPos = $tConv16.value
ConsoleWrite($iPos & @CRLF)

$tConv32.value = $iNeg
$iPos = $tConv32.value
ConsoleWrite($iPos & @CRLF)

 

Link to comment
Share on other sites

How do you get the signed values? I mean: how do you load the value into $SNMP_Util[1][1]

The binary you show is 16 bits but AutoIt integers are 32- or 64-bit signed integers.

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to comment
Share on other sites

If you're confined to pulling the data this way, then you could also test for the sign and pad out the top 16bits...

To convert backwards you should be able to just take the low word verbatim. (Keeping in mind any value higher than 0x7FFF would be out of range for a signed 16-bit int.)

$iNum = 65136 ;0x0000FE70
If BitAND($iNum, 0x8000) Then $iNum = BitOR(0xFFFF0000, $iNum)
ConsoleWrite($iNum & @CRLF)

$iNum = -400 ;0xFFFFFE70
$iNum = BitAND($iNum, 0xFFFF)
ConsoleWrite($iNum & @CRLF)
Link to comment
Share on other sites

@A-Team Looking at your post here it looks like you are using different int ranges as guys above noted. So you can use something like this:

ConsoleWrite(SInt(341) & @CRLF)
ConsoleWrite(SInt(194) & @CRLF)
ConsoleWrite(SInt(65136) & @CRLF)

Func SInt($iValue)
    Local $iIntRange = ($iValue <= 0xFF ? 0xFF : ($iValue <= 0xFFFF ? 0xFFFF : 0xFFFFFFFF))
    Local $iSignedRange = ($iValue <= 0xFF ? 0x80 : ($iValue <= 0xFFFF ? 0x8000 : 0x80000000))
    Return BitAND($iValue, $iSignedRange) ? BitNOT(BitAND(BitNOT($iValue), $iIntRange)) : $iValue
EndFunc
Edited by Andreik

When the words fail... music speaks.

Link to comment
Share on other sites

  • Moderators

Moved to the appropriate AutoIt General Help and Support forum, as the AutoIt Example Scripts forum very clearly states:

Quote

Share your cool AutoIt scripts, UDFs and applications with others.


Do not post general support questions here, instead use the AutoIt Help and Support forums.

Moderation Team

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

6 hours ago, Andreik said:

Looking at your post here it looks like you are using different int ranges as guys above noted.

I would be very careful here - you can't really tell what data type you have based only on it's value.

0xFF is -1 as a signed 8-bit int, but for anything longer its 255.
So basically you need to know what you've got in $SNMP_Util[1][1] before converting.

I mean, without context Binary("0x41") might be representing the number 65. But it could just as easily be the letter "A"

Edited by MattyD
Link to comment
Share on other sites

Good afternoon
First off Thank you all for your inputs although I think I have confused just about everyone with my fine choice of words above :0, I will try to clarify what the data looks like, how its populated and what I need to do with such,
first the data, the table will look like this from the source the snmp agent
image.png.1d950add5f2001b974fba6176d4f66fd.png 
these values will fluctuate, the negative numbers are the only important ones, stored as int32 
the values just from the snmp until will look like this image.png.55c1a4c36d61c72fe1181711ccbd2024.png
these values are not all in $traffic_priortization at the same time, more so added as it increments in the loop,
these values are populated with an snmp get request that code looks like this 
 

$SNMP_Command = _SNMPBuildPacket($SNMP_OID, $SNMP_Community ,$SNMP_Version, $SNMP_ReqID, "A0") ; A single GetRequest
   UDPSend($Socket, $SNMP_Command)
   _StartListener() ; 250ms timeout.
   If @error Then
      error checking condition i have removed for sake of example
   Else

      $Traffic_Prioritization = $SNMP_Util[1][1]

The outcome I am is looking for is to retain the negative numbers in my functions, 

I Love It When a *Autoit Script* Comes Together

Link to comment
Share on other sites

The function above does exactly this:

ConsoleWrite(SInt(595) & @CRLF)
ConsoleWrite(SInt(333) & @CRLF)
ConsoleWrite(SInt(339) & @CRLF)
ConsoleWrite(SInt(193) & @CRLF)
ConsoleWrite(SInt(65136) & @CRLF)

Func SInt($iValue)
    Local $iIntRange = ($iValue <= 0xFF ? 0xFF : ($iValue <= 0xFFFF ? 0xFFFF : 0xFFFFFFFF))
    Local $iSignedRange = ($iValue <= 0xFF ? 0x80 : ($iValue <= 0xFFFF ? 0x8000 : 0x80000000))
    Return BitAND($iValue, $iSignedRange) ? BitNOT(BitAND(BitNOT($iValue), $iIntRange)) : $iValue
EndFunc

Result:

Quote

595
333
339
-63
-400

 

When the words fail... music speaks.

Link to comment
Share on other sites

50 minutes ago, A-Team said:

these values are not all in $traffic_priortization at the same time, more so added as it increments in the loop,
these values are populated with an snmp get request that code looks like this

Yet your code don't show how $SNMP_Util[1][1] is populated! Most probably the step where the data is butchered.

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to comment
Share on other sites

As @MattyD said, you cannot blindly convert 193 into -63 without knowing the size base of the source (8/16/32 bits).  You will have to follow (debug) the UDF till you find exactly where and how the data is received with/by the UDF (and it is quite possible that you will need to adapt the UDF).  Since we only have a very small part of the code, it is very difficult for us to provide a proven solution.

Link to comment
Share on other sites

Posted (edited)
2 hours ago, jchd said:

Yet your code don't show how $SNMP_Util[1][1] is populated! Most probably the step where the data is butchered.

that would be correct, I am using the snmp UDF Version 1.7.4 HERE
I did start here but will see if I can find the issue as "Nine" Mentioned
the function for populating snmp_until, exactly from the UDF no changes of mine
 

Func _ShowSNMPReceived($rcvDATA)
    Global $SNMP_Util[1000][3]
    Local $_sPacketRecv_ = $rcvDATA
    Local $_PDUcontent      = ""
    Local $_ExtractedDATA
    Local $_IsError = 0
    Local $_PDU_content = ""
    Local $_delimSTR_ = ""
    _WriteArrayValues($SNMP_Received, 1, "SNMP Answer", $rcvDATA)
    $rcvDATA = StringTrimLeft($rcvDATA, 4)          ;strip 0x30
    Local $_l_pl = _GetPacLen_(StringLeft($rcvDATA, 6))
    Local $_pacLen_ = StringLeft($rcvDATA, $_l_pl)
    $rcvDATA = StringTrimLeft($rcvDATA, $_l_pl) ;strip packet length
    _WriteArrayValues($SNMP_Received, 2, "(Total) PDU Length", $_pacLen_)
;------------- SNMP Version Block -------------------------------------------------
    _WriteArrayValues($SNMP_Received, 3, "SNMP Version Block", StringLeft($rcvDATA, 6))
    $rcvDATA = StringTrimLeft($rcvDATA, 4)          ;strip 0201 from SNMP ver block
    Local $_snmpV_ = StringLeft($rcvDATA, 2)+1              ;SNMP Version
    $rcvDATA = StringTrimLeft($rcvDATA, 2)          ;strip SNMP Version
;------------- Community String ---------------------------------------------------
    $rcvDATA = StringTrimLeft($rcvDATA, 2)          ;strip 04 from community block
    Local $_commLen_ = Dec(StringLeft($rcvDATA, 2))*2       ;Length of community string
    $rcvDATA = StringTrimLeft($rcvDATA, 2)          ;strip community length
    Local $_commHex_ = StringLeft($rcvDATA, $_commLen_) ;community string (hex)
    Local $_commTex_ = _HexToString($_commHex_)
    $rcvDATA = StringTrimLeft($rcvDATA, $_commLen_)
    _WriteArrayValues($SNMP_Received, 4, "Community String", $_commTex_)
;------------- PDU Type -----------------------------------------------------------
    Local $_pduT_ = StringLeft($rcvDATA, 2)
    _WriteArrayValues($SNMP_Received, 5, "PDU Type", $_pduT_)
    $rcvDATA = StringTrimLeft($rcvDATA, 2)
    $rcvDATA = _StripPacket($rcvDATA)
;------------- Request ID ---------------------------------------------------------
    $rcvDATA = _StripBlocks($rcvDATA, 6, "Request ID Block")
;------------- Error Block --------------------------------------------------------
    Local $_sErr_ = StringMid($rcvDATA, 5, 2)
    If $_sErr_ <> "00" Then
        _ThrowError($_sErr_, $_sPacketRecv_)
        Return SetError(1)
    EndIf
    _WriteArrayValues($SNMP_Util, 0, "SNMP Error Value:", $_sErr_)
    $rcvDATA = _StripBlocks($rcvDATA, 7, "Error Block")
;------------- Error Index --------------------------------------------------------
    $rcvDATA = _StripBlocks($rcvDATA, 8, "Error Index Block")
;------------- PDU Total Len ------------------------------------------------------
    $rcvDATA = StringTrimLeft($rcvDATA, 2)
    $_l_pl = _GetPacLen_(StringLeft($rcvDATA, 6))
    Local $_pacTotLen_ = StringLeft($rcvDATA, $_l_pl)
    $rcvDATA = StringTrimLeft($rcvDATA, $_l_pl)                     ;strip packet length
;------------- PDU Data -----------------------------------------------------------
    Local $_snmpR_idx = 9, $_snmpA_idx = 1
    Do
        $rcvDATA = StringTrimLeft($rcvDATA, 2)                              ;cut "30" (data type: SEQ)
        $_l_pl = _GetPacLen_(StringLeft($rcvDATA, 6))                       ;length of Data PDU
        $_pacLen_ = StringLeft($rcvDATA, $_l_pl)
        $rcvDATA = StringTrimLeft($rcvDATA, $_l_pl)                         ;cut length
        $_PDU_content = StringLeft($rcvDATA, Dec($_pacLen_)*2)              ;get what is left from PDU
        $rcvDATA = StringTrimLeft($rcvDATA, Dec($_pacLen_)*2)               ;remove that from message
        $_delimSTR_ = "30|"&$_pacLen_&"|"                                   ;build delimited string
        If StringLeft($_PDU_content, 2) = "06" Then
            $_delimSTR_ &= "06|"
            $_PDU_content = StringTrimLeft($_PDU_content, 2)                ;cut "06" (data type: OID)
            $_l_pl = _GetPacLen_(StringLeft($_PDU_content, 6))              ;Length of OID sequence
            $_pacLen_ = StringLeft($_PDU_content, $_l_pl)
            $_PDU_content = StringTrimLeft($_PDU_content, $_l_pl)           ;cut length
            Local $_OID_val = StringLeft($_PDU_content, Dec($_pacLen_)*2)   ;OID (hex)
            $_delimSTR_ &= $_pacLen_&"|"&$_OID_val&"|"
            Local $_Decoded_OID = _TranslateOID($_OID_val, "2d")            ;OID (dec)
            $_PDU_content = StringTrimLeft($_PDU_content, Dec($_pacLen_)*2)
            Local $_data_type = StringLeft($_PDU_content, 2)                ;returned data type
            $_PDU_content = StringTrimLeft($_PDU_content, 2)
            If StringLen($_PDU_content) >= 6 Then
                $_l_pl = _GetPacLen_(StringLeft($_PDU_content, 6))              ;Length of data sequence
            Else
                $_l_pl = _GetPacLen_(StringLeft($_PDU_content, 4))              ;Length of data sequence
            EndIf
            Local $_raw_data = StringTrimLeft($_PDU_content, $_l_pl)
            Local $_RealData = _ExtractData($_data_type, $_raw_data)
            _WriteArrayValues($SNMP_Received, $_snmpR_idx, $_Decoded_OID, $_RealData)
            $_snmpR_idx += 1
            $_delimSTR_ &= $_data_type&"|"&StringLeft($_PDU_content, $_l_pl)&"|"&$_raw_data
            _WriteArrayValues($SNMP_Received, $_snmpR_idx, "Raw PDU (delimited string)", $_delimSTR_)
            $_snmpR_idx += 1
            _WriteArrayValues($SNMP_Util, $_snmpA_idx, $_Decoded_OID, $_RealData)
            $_snmpA_idx += 1
            $_delimSTR_ = ""
        Else
            Return SetError(2)      ;bad SNMP Packet
        EndIf
    Until Int(StringLen($rcvDATA)) = 0
    ReDim $SNMP_Received[$_snmpR_idx][3]
    ReDim $SNMP_Util[$_snmpA_idx][3]
    Return $SNMP_Util
EndFunc     ;==>_ShowSNMPReceived
#endregion

 

Edited by A-Team

I Love It When a *Autoit Script* Comes Together

Link to comment
Share on other sites

Link to comment
Share on other sites

36 minutes ago, Nine said:

Well $rcvDATA should contain all the information necessary to extract correctly -63.

Show an example of $rcvDATA, especially the one with -63 inside.

at least I thought the same thing trying to track the changes through, 
image.png.7baac38ff82a6a3a2295659e53d85c19.png
image.png.9bf52d44c326c0ec82d3c9b595e0dc8d.png
taken from here as the line after the variable is empty, 
the "real" value is taken from the "$_RealData" further down this is just to compare with
there is so much other information in the rcv the correct value could be there but i will continue trying to decode

I Love It When a *Autoit Script* Comes Together

Link to comment
Share on other sites

Posted (edited)
38 minutes ago, Andreik said:

It's not very helpful. Post the content of $rcvDATA that is sent to _ShowSNMPReceived().

Func _ShowSNMPReceived($rcvDATA)
    ConsoleWrite($rcvDATA & @CRLF)
    ...
EndFunc

 

image.png.f58105d9ebcb5180faade02a3862b500.png

as you wish
yes the number has changed it was 192 its currently 193 with source remaining is -63 I don't believe this is anything to do with the code its just sensitive  
Isn't the C1 at the end where the value is that is 193 

Edited by A-Team

I Love It When a *Autoit Script* Comes Together

Link to comment
Share on other sites

5 hours ago, Andreik said:

The function above does exactly this:

ConsoleWrite(SInt(595) & @CRLF)
ConsoleWrite(SInt(333) & @CRLF)
ConsoleWrite(SInt(339) & @CRLF)
ConsoleWrite(SInt(193) & @CRLF)
ConsoleWrite(SInt(65136) & @CRLF)

Func SInt($iValue)
    Local $iIntRange = ($iValue <= 0xFF ? 0xFF : ($iValue <= 0xFFFF ? 0xFFFF : 0xFFFFFFFF))
    Local $iSignedRange = ($iValue <= 0xFF ? 0x80 : ($iValue <= 0xFFFF ? 0x8000 : 0x80000000))
    Return BitAND($iValue, $iSignedRange) ? BitNOT(BitAND(BitNOT($iValue), $iIntRange)) : $iValue
EndFunc

Sorry I should have replied to this earlier, I have implemented this  this works exactly as I had envisioned🤑, Although I am unsure if this is working for all scenarios, (as nine mentions) but I will be testing my software in a larger environment soon and will give feedback then, for now thank you everyone for the feedback and ideas! 
have a great evening!

 

 

I Love It When a *Autoit Script* Comes Together

Link to comment
Share on other sites

It should work properly since SNMP encode fields using 1, 2, 4 bytes or some length according to ASN.1 BER rules. Probably this is why the data extraction is done in this UDF by simply converting the hex to an integer using the minimum amount of bytes without any further validation or by casting to an integer of a specific size (see _ExtractData() and _SNMPHexToDec()). But do your tests and let us know the results.

When the words fail... music speaks.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...