Structure bitweise füllen / abfragen

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
mk-soft
Beiträge: 3695
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Structure bitweise füllen / abfragen

Beitrag von mk-soft »

Äh... Warum so kompliziert?

Uralt von mir... 2007

Code: Alles auswählen

Macro TestBit(value,bit)
  (value>>bit&1)
EndMacro

Macro SetBit(value,bit)
  (1 << bit | value)
EndMacro

Macro ClrBit(value,bit)
  (~(1 << bit) & value)
EndMacro

Debug "Die Zahl 5 - Bit für Bit"
Val = 5
r1 = TestBit(Val,0)
Debug "Das 1. Bit:     "+Str(r1)
r1 = TestBit(Val,1)
Debug "Das 2. Bit:     "+Str(r1)
Debug "Das 3. Bit:     "+Str(TestBit(Val,2))
Debug "Und hier in einer Zeile: "+Bin(5)

Value = 0

Debug "Setze Bit 0"
Value = SetBit(Value,0)
Debug "Setze Bit 2"
Value = SetBit(Value,2)
Debug "Ergebis= " + Str(Value)

Debug "Lösche Bit 0"
Value = ClrBit(Value, 0)
Debug "Ergebis= " + Str(Value)

lVal.l = 0

Debug "Setze Bit 31"
lVal = SetBit(lVal,31)
Debug "Ergebis= " + Str(lVal)
Debug "Ergebis= " + Bin(lVal)

llVal.q = 0

Debug "Setze Bit 63"
llVal = SetBit(llVal,63)
Debug "Ergebis= " + StrQ(llVal)
Debug "Ergebis= " + BinQ(llVal)
:wink:

P.S. Als ASM hatte ich das auch schon mal... Kann ich leider nicht wiederfinden :cry:
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 6996
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Structure bitweise füllen / abfragen

Beitrag von STARGÅTE »

mk-soft hat geschrieben:Äh... Warum so kompliziert?
Weil...
  • es direkt im speicher passieren soll, weil die Struktur 30 Bytes lang ist, was nicht per A=B änderbar ist.
  • es mit mehr als einem Bit funktionieren sollte (einige Felder hatten 2 Bits)
  • ein Bit auf 0/1 setzbar sein sollte, ohne zwei verschiedene Prozeduren/Makros zu verwenden.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
mk-soft
Beiträge: 3695
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Structure bitweise füllen / abfragen

Beitrag von mk-soft »

Ach so...

falsch verstanden.
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
andi256
Beiträge: 100
Registriert: 06.11.2004 11:23
Computerausstattung: PB 5.30 (x64) Win7
Wohnort: Österreich

Re: Structure bitweise füllen / abfragen

Beitrag von andi256 »

Vielen herzlichen Dank für Eure Mühen!!!

Hab den Code mal soweit eingebaut ... und läuft auch gut bis auf eine kleinigkeit ...

mir ist aufgefallen das die Procedure

bei SetBit(*Buff,28,0,1) das 29 bit auch mit löscht

auch bei SetBit(*Buff,28,1,1) verschwindet das 29ste bit

Andi
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 6996
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Structure bitweise füllen / abfragen

Beitrag von STARGÅTE »

´könntest du mal bitte schreiben, welche Version du jetzt dafür genutzt hast?
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
andi256
Beiträge: 100
Registriert: 06.11.2004 11:23
Computerausstattung: PB 5.30 (x64) Win7
Wohnort: Österreich

Re: Structure bitweise füllen / abfragen

Beitrag von andi256 »

Hallo,

sorry ...

deine Version (letzter Post Seite 1)

Code: Alles auswählen

Structure AllTypes
   StructureUnion
      b.b : w.w : l.l : q.q
   EndStructureUnion
EndStructure

Procedure SetBit(*Buffer.AllTypes, Position.i, Value.i, Length.i=1)
   If Position > 7
      SetBit(*Buffer + Position/8, Position%8, Value, Length)
   EndIf
   Select Position+Length
      Case 1 To 8
         *Buffer\b = *Buffer\b & ~(($FF>>(8-Length))<<Position) | (Value<<Position)
      Case 9 To 16
         *Buffer\w = *Buffer\w & ~(($FFFF>>(16-Length))<<Position) | (Value<<Position)
      Case 17 To 32
         *Buffer\l = *Buffer\l & ~(($FFFFFFFF>>(32-Length))<<Position) | (Value<<Position)
      Case 33 To 64
         *Buffer\q = *Buffer\q & ~(($FFFFFFFFFFFFFFFF>>(64-Length))<<Position) | (Value<<Position)
   EndSelect
EndProcedure

Procedure.s out(*mem,l)
 str$=""
 For i =  0 To l-1
  str$ + RSet(Bin(PeekB(*mem+i)),8,"0") + " "
 Next
ProcedureReturn str$
EndProcedure

DataSection 
test:
Data.b $00,$00$,$00,$FF,$00,$00,$00,$00
EndDataSection

*test = AllocateMemory(8)

CopyMemory(?test,*test,8)
Debug out (*test,4)
SetBit(*test, 28,1,1)
Debug out (*test,4)

Debug "---"

CopyMemory(?test,*test,8)
Debug out (*test,8)
Debug RSet(Bin(PeekL(*test) ),64,"0")
SetBit(*test, 28,0,1)
Debug out (*test,8)
Debug RSet(Bin(PeekL(*test) ),64,"0")

FreeMemory(*test)
von wo kommen beim 1. "PeekL" die führenden Einsen her ? ... 64 müsste zwar ein Quad sein (mit dem das auch passt -> PeekQ)

.... aber da *Buffer\l (Case 17 To 32) ein Long ist shiften sich da denke ich die "einsen" ein -> mittels "~" werden das Nullen in der "maske" die die high bits rauslöschen ?

(PB 4.20 & 5.11 WIN7 64bit)

mfg Andi
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 6996
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Structure bitweise füllen / abfragen

Beitrag von STARGÅTE »

Ah klar, dass ist das angesprochene Problem, wenn ich $FFFF.FFFF shifte, dann bleibt das Vorzeichen "leider" erhalten.
Somit ist $FFFF.FFFF >> 16 zB nicht $0000.FFFF sondern leider immer noch $FFFF.FFFF

Das PeekL() bei $FF00.0000 im Bin viele 1 davor hat, liegt auch daran, dass versucht wird, das Vorzeichen zu erhalten.

Hier die neue Version, die das Problem behebt:

Code: Alles auswählen

Structure AllTypes
	StructureUnion
		b.b : w.w : l.l : q.q
	EndStructureUnion
EndStructure

Procedure SetBit(*Buffer.AllTypes, Position.i, Value.q, Length.i=1)
	Protected Mask.q
	If Position > 7
		SetBit(*Buffer + Position/8, Position%8, Value, Length)
	Else
		If Length = 64
			Mask = $0000000000000000
		Else
			Mask = ~(($7FFFFFFFFFFFFFFF>>(63-Length))<<Position)
		EndIf
		Select Position+Length
			Case 1 To 8
				*Buffer\b = *Buffer\b & Mask | (Value<<Position)
			Case 9 To 16
				*Buffer\w = *Buffer\w & Mask | (Value<<Position)
			Case 17 To 32
				*Buffer\l = *Buffer\l & Mask | (Value<<Position)
			Case 33 To 64
				*Buffer\q = *Buffer\q & Mask | (Value<<Position)
		EndSelect
	EndIf
EndProcedure

Procedure.q GetBit(*Buffer.AllTypes, Position.i, Length.i=1)
   Protected Mask.q
	 If Position > 7
      ProcedureReturn GetBit(*Buffer + Position/8, Position%8, Length)
   EndIf
		If Length = 64
			Mask = $FFFFFFFFFFFFFFFF
		Else
			Mask = $7FFFFFFFFFFFFFFF>>(63-Length)
		EndIf
   Select Position+Length
      Case 1 To 8
         ProcedureReturn (*Buffer\b>>Position)&Mask
      Case 9 To 16
         ProcedureReturn (*Buffer\w>>Position)&Mask
      Case 17 To 32
         ProcedureReturn (*Buffer\l>>Position)&Mask
      Case 33 To 64
         ProcedureReturn (*Buffer\q>>Position)&Mask
      Default
   EndSelect   
EndProcedure

Procedure.s out(*mem,l)
	str$=""
	For i =  0 To l-1
		str$ + RSet(Bin(PeekB(*mem+i), #PB_Byte),8,"0") + " "
	Next
	ProcedureReturn str$
EndProcedure

DataSection
	test:
	Data.b $00,$00$,$00,$FF,$00,$00,$00,$00
EndDataSection

*test = AllocateMemory(8)

CopyMemory(?test,*test,8)
Debug out (*test,4)
SetBit(*test, 28, 0)
Debug out (*test,4)

Debug "---"

CopyMemory(?test,*test,8)
Debug out (*test,8)
Debug RSet(Bin(PeekL(*test) ),64,"0")
SetBit(*test, 28,0,1)
Debug out (*test,8)
Debug RSet(Bin(PeekL(*test) ),64,"0")

FreeMemory(*test)
Du hattest allerdings auch ein Fehler in out(), bei Bin(PeekB()) musst du ,#PB_Byte mit angeben, sonst haut dir Bin auch 64-8 Einsen davor.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Antworten