Seite 2 von 2

Re: Structure bitweise füllen / abfragen

Verfasst: 25.08.2013 00:56
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:

Re: Structure bitweise füllen / abfragen

Verfasst: 25.08.2013 01:34
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.

Re: Structure bitweise füllen / abfragen

Verfasst: 25.08.2013 01:48
von mk-soft
Ach so...

falsch verstanden.

Re: Structure bitweise füllen / abfragen

Verfasst: 27.08.2013 12:17
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

Re: Structure bitweise füllen / abfragen

Verfasst: 27.08.2013 19:21
von STARGÅTE
´könntest du mal bitte schreiben, welche Version du jetzt dafür genutzt hast?

Re: Structure bitweise füllen / abfragen

Verfasst: 29.08.2013 10:30
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

Re: Structure bitweise füllen / abfragen

Verfasst: 29.08.2013 11:54
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.