 |
Das deutsche QBasic- und FreeBASIC-Forum Für euch erreichbar unter qb-forum.de, fb-forum.de und freebasic-forum.de!
|
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
Autor |
Nachricht |
Digga

Anmeldungsdatum: 07.01.2006 Beiträge: 48
|
Verfasst am: 21.07.2009, 22:10 Titel: Binary Get und sein Hex-Wert |
|
|
Hallo alle zusammen.
Hab ein kleines Problem. Und zwar möchte ich Werte Binär aus einer Datei lesen. Solange ich dies mit Byte als Datentyp mache,
klappt es auch wunderbar. Nur so bald ich Als Datentyp Integer benutze kommt ein ganz anderer Wert raus.
Wert in der Datei =
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000 24 3D F9 E7
Doch das Programm sagt: E7F93D24
Code: |
DIM Zahl AS UINTEGER
DIM file AS UINTEGER = FREEFILE
OPEN "test.dat" FOR BINARY AS #file
GET #file, , Zahl
CLOSE #file
PRINT HEX(Zahl)
|
Wäre schön wenn jemand mir weiterhelfen kann. Komme sonst nicht weiter.
Gruß Digga |
|
Nach oben |
|
 |
St_W

Anmeldungsdatum: 22.07.2007 Beiträge: 956 Wohnort: Austria
|
Verfasst am: 21.07.2009, 22:28 Titel: |
|
|
Intel Prozessoren arbeiten mit der Byte-Anordnung Little Endian.
Mehr dazu auf Wikipedia unter http://de.wikipedia.org/wiki/Byte-Reihenfolge
Vielleicht helfen dir folgende Funktionen:
Code: | 'Interpretiert einen String als Zahl im BigEndian Format
Function Str2IntBE(ByRef tmpStr As String) As UInteger
Dim q As UInteger
Dim w As UInteger = 0
Dim l As Integer = Len(tmpStr)
For q = 1 To l
w = w Or (Asc(Mid(tmpStr,q,1)) Shl ((l-q)*8))
Next
Return w
End Function
'Interpretiert einen String als Zahl im LittleEndian Format
Function Str2IntLE(ByRef tmpStr As String) As UInteger
Dim q As UInteger
Dim w As UInteger = 0
Dim l As Integer = Len(tmpStr)
For q = 1 To l
w = w Or (Asc(Mid(tmpStr,q,1)) Shl ((q-1)*8))
Next
Return w
End Function
'Stellt eine Zahl als String im BigEndian Format dar
'(Laenge = Länge der Zeichenkette, links mit 0 aufgefüllt. Laenge = 0 --> benötigte Länge)
Function Int2StrBE(ByVal tmpInt As UInteger, ByVal Laenge As Integer = 0) As String
Dim q As Integer = 0
Dim tmpStr As String = ""
Do
tmpStr = Chr((tmpInt Shr q*8) And &b11111111) + tmpStr
q += 1
If (tmpInt Shr (q*8)) = 0 Then Exit Do
Loop
If Laenge > 0 Then tmpStr = RPad(tmpStr,0,Laenge)
Return tmpStr
End Function
'Stellt eine Zahl als String im LittleEndian Format dar
Function Int2StrLE(ByVal tmpInt As UInteger, ByVal Laenge As Integer = 0) As String
Dim q As Integer = 0
Dim tmpStr As String = ""
Do
tmpStr += Chr((tmpInt Shr q*8) And &b11111111)
q += 1
If (tmpInt Shr (q*8)) = 0 Then Exit Do
Loop
If Laenge > 0 Then tmpStr = RPad(tmpStr,0,Laenge)
Return tmpStr
End Function
'//edit: Achja, folgende Funktionen werden von den obigen zwei benötigt:
Declare Function LPad OverLoad (Daten As String, PadZeichen As String, Laenge As Integer) As String
Declare Function LPad(Daten As String, PadZeichen As Integer, Laenge As Integer) As String
Declare Function RPad OverLoad (Daten As String, PadZeichen As String, Laenge As Integer) As String
Declare Function RPad(Daten As String, PadZeichen As Integer, Laenge As Integer) As String
Function LPad(Daten As String, PadZeichen As String, Laenge As Integer) As String
Return LPad(Daten, Asc(PadZeichen), Laenge)
End Function
Function LPad(Daten As String, PadZeichen As Integer, Laenge As Integer) As String
If Len(Daten) = Laenge Then Return Daten
If Len(Daten) > Laenge Then Return Left(Daten, Laenge)
Return Daten & String(Laenge - Len(Daten), PadZeichen)
End Function
Function RPad(Daten As String, PadZeichen As String, Laenge As Integer) As String
Return RPad(Daten, Asc(PadZeichen), Laenge)
End Function
Function RPad(Daten As String, PadZeichen As Integer, Laenge As Integer) As String
If Len(Daten) = Laenge Then Return Daten
If Len(Daten) > Laenge Then Return Left(Daten, Laenge)
Return String(Laenge - Len(Daten), PadZeichen) & Daten
End Function
|
_________________ Aktuelle FreeBasic Builds, Projekte, Code-Snippets unter http://users.freebasic-portal.de/stw/
http://www.mv-lacken.at Musikverein Lacken (MV Lacken)
Zuletzt bearbeitet von St_W am 22.07.2009, 02:03, insgesamt einmal bearbeitet |
|
Nach oben |
|
 |
Jojo alter Rang

Anmeldungsdatum: 12.02.2005 Beiträge: 9736 Wohnort: Neben der Festplatte
|
Verfasst am: 21.07.2009, 22:40 Titel: |
|
|
50% Chance, 100% Falsch. Die x86-Architektur ist so ziemlich die einzige LittleEndian-Architektur, die heute noch lebt... _________________ » Die Mathematik wurde geschaffen, um Probleme zu lösen, die es nicht gäbe, wenn die Mathematik nicht erschaffen worden wäre.
 |
|
Nach oben |
|
 |
St_W

Anmeldungsdatum: 22.07.2007 Beiträge: 956 Wohnort: Austria
|
Verfasst am: 22.07.2009, 02:06 Titel: |
|
|
Ooops
Intel is natürlich Little Endian und Motorola is Big Endian.
(Habs wahrscheinlich verwechselt, da ich in letzter Zeit mit dem ganzen ID3, EXIF, etc. Zeugs überwiegend BigEndian gebraucht hab. An dieser Stelle: EXIF-(Lese)-Unterstützung für mein Projekt Multimedia-Tag is schon in der Testphase) _________________ Aktuelle FreeBasic Builds, Projekte, Code-Snippets unter http://users.freebasic-portal.de/stw/
http://www.mv-lacken.at Musikverein Lacken (MV Lacken) |
|
Nach oben |
|
 |
Digga

Anmeldungsdatum: 07.01.2006 Beiträge: 48
|
Verfasst am: 22.07.2009, 16:14 Titel: |
|
|
Hallo.
Danke für deinen Hinweis und die Hilfe St_W.
Habe es jetzt so gelöst:
Code: |
DIM Zahlgross AS UINTEGER
DIM Zahlklein AS UBYTE
DIM file AS UBYTE = FREEFILE
DIM Index AS UBYTE = 1
OPEN "test.dat" FOR BINARY AS #file
DO UNTIL (Index = 5)
GET #file, , Zahlklein
Zahlgross += Zahlklein * (256^(4 - Index))
Index += 1
LOOP
CLOSE #file
|
Geht zwar auch bestimmt schneller, aber für meine zwecke wird es erst einmal ausreichen.
Zur Erläuterung, ich möchte eine Datei auslesen in der Dateiinterne Adressen gespeichert sind.
Wenn ich sie einfach so eingelesen hätte wäre alles raus gekommen,
nur nicht das was ich will...
gruß Digga |
|
Nach oben |
|
 |
Jojo alter Rang

Anmeldungsdatum: 12.02.2005 Beiträge: 9736 Wohnort: Neben der Festplatte
|
Verfasst am: 22.07.2009, 16:24 Titel: |
|
|
Also Endian-Konvertierung mit Potenzen zu lösen ist doof und langsam. FreeBASIC kann doch sogar Bitshifting (SHR, SHL), nimm lieber das.
Könnte z.B. so gehen:
Code: |
dim as integer gesamtwert = 0, bytewert
For i as integer = 0 to 4
get #file,, bytewert
gesamtwert = (gesamtwert shl 8) + bytewert
next
|
_________________ » Die Mathematik wurde geschaffen, um Probleme zu lösen, die es nicht gäbe, wenn die Mathematik nicht erschaffen worden wäre.
 |
|
Nach oben |
|
 |
Digga

Anmeldungsdatum: 07.01.2006 Beiträge: 48
|
Verfasst am: 22.07.2009, 17:11 Titel: |
|
|
Stimmt das geht ja auch
bytewert muss in dem Fall aber vom Typ Byte sein, sonst kommt da ein ganz
anderer Wert raus
Code: |
dim as integer gesamtwert = 0
dim as byte bytewert
For i as integer = 0 to 4
get #file,, bytewert
gesamtwert = (gesamtwert shl 8) + bytewert
next
|
Ansonsten klappt es wunderbar. Danke schon.
gruß Digga |
|
Nach oben |
|
 |
volta
Anmeldungsdatum: 04.05.2005 Beiträge: 1876 Wohnort: D59192
|
Verfasst am: 22.07.2009, 18:14 Titel: |
|
|
Code: | 'Es gibt zwei Formen der Speicherorganisation,
'sie nennen sich Little Endian und Big Endian.
'Little Endian findet vor allem bei x86-Prozessoren Anwendung,
'Big Endian bei den 68000 von Motorola (Apples Macintosh)
'sowie bei vielen RISC-Prozessoren.
'Little Endian zeichnet sich dadurch aus, dass der niederwertigste Teil
'eines Datums im Speicher an der niedrigsten Adresse steht.
'Bei Big Endian verhält es sich genau umgekehrt.
'Adresse Little Endian Big Endian
' + 0 Byte 0 Byte 3
' + 1 Byte 1 Byte 2
' + 2 Byte 2 Byte 1
' + 3 Byte 3 Byte 0
'Durch tauschen von Byte 0 mit Byte 3 sowie Byte 1 mit Byte 2
'kann man von Little Endian nach Big Endian oder umgekehrt konvertieren.
'Die entsprechende ASM-Anweisug nennt sich BSWAP
#Macro BSWAP32(a)
Asm
mov eax, [a]
bswap eax
mov [a], eax
End Asm
#EndMacro
DIM AS INTEGER gesamtwert
GET #file,, gesamtwert
BSWAP32(gesamtwert) |
_________________ Warnung an Choleriker:
Dieser Beitrag kann Spuren von Ironie & Sarkasmus enthalten.
Zu Risiken & Nebenwirkungen fragen Sie Ihren Therapeuten oder Psychiater. |
|
Nach oben |
|
 |
Jojo alter Rang

Anmeldungsdatum: 12.02.2005 Beiträge: 9736 Wohnort: Neben der Festplatte
|
Verfasst am: 22.07.2009, 22:49 Titel: |
|
|
@Digga: Sorry, war ungetestet. Aber gut, dass du den Fehler aufgedeckt hast, das zeigt dass du dich damit befasst und es verstanden hast.
@Volta: Ich persönlich würde auf den Einsatz von ASM aus Portierbarkeitsgründen hier verzichten. Im OpenMPT-Code haben wir folgende Makros, sollte sich ja leicht auf FB übertragen lassen:
Code: | #ifdef PLATFORM_BIG_ENDIAN
// PPC
inline DWORD LittleEndian(DWORD x) { return ((x & 0xFF) << 24) | ((x & 0xFF00) << 8) | ((x & 0xFF0000) >> 8) | ((x & 0xFF000000) >> 24); }
inline WORD LittleEndianW(WORD x) { return (WORD)(((x >> 8) & 0xFF) | ((x << 8) & 0xFF00)); }
#define BigEndian(x) (x)
#define BigEndianW(x) (x)
#else
// x86
inline DWORD BigEndian(DWORD x) { return ((x & 0xFF) << 24) | ((x & 0xFF00) << 8) | ((x & 0xFF0000) >> 8) | ((x & 0xFF000000) >> 24); }
inline WORD BigEndianW(WORD x) { return (WORD)(((x >> 8) & 0xFF) | ((x << 8) & 0xFF00)); }
#define LittleEndian(x) (x)
#define LittleEndianW(x) (x)
#endif |
_________________ » Die Mathematik wurde geschaffen, um Probleme zu lösen, die es nicht gäbe, wenn die Mathematik nicht erschaffen worden wäre.
 |
|
Nach oben |
|
 |
28398
Anmeldungsdatum: 25.04.2008 Beiträge: 1917
|
Verfasst am: 22.07.2009, 23:06 Titel: |
|
|
FBC gibbet erst für x86...
Und BSWAP gibt es ab i486... |
|
Nach oben |
|
 |
Jojo alter Rang

Anmeldungsdatum: 12.02.2005 Beiträge: 9736 Wohnort: Neben der Festplatte
|
Verfasst am: 22.07.2009, 23:21 Titel: |
|
|
Zitat: | FBC gibbet erst für x86... |
die unteren Makros kann man ja trotzdem verwenden.  _________________ » Die Mathematik wurde geschaffen, um Probleme zu lösen, die es nicht gäbe, wenn die Mathematik nicht erschaffen worden wäre.
 |
|
Nach oben |
|
 |
28398
Anmeldungsdatum: 25.04.2008 Beiträge: 1917
|
Verfasst am: 23.07.2009, 01:26 Titel: |
|
|
Sind aber DEUTLICH langsamer. BSWAP wird vermutlich bei neueren Prozis mit einem oder zwei Takten abgearbeitet. Deine Makros? |
|
Nach oben |
|
 |
Jojo alter Rang

Anmeldungsdatum: 12.02.2005 Beiträge: 9736 Wohnort: Neben der Festplatte
|
Verfasst am: 23.07.2009, 09:47 Titel: |
|
|
Den richtigen Compiler gegeben, wird er auf x86-Platformen höchstwahrscheinlich etwas wie bswap verwenden. Und ich hoffe du bist dir über die Geschwindigkeit von logischen Operationen wie & oder << im Klaren... _________________ » Die Mathematik wurde geschaffen, um Probleme zu lösen, die es nicht gäbe, wenn die Mathematik nicht erschaffen worden wäre.
 |
|
Nach oben |
|
 |
28398
Anmeldungsdatum: 25.04.2008 Beiträge: 1917
|
Verfasst am: 23.07.2009, 15:49 Titel: |
|
|
FBC hat noch keinen "richtigen" Optimierer. Und selbst die logischen Ops brauchen jeweils mindestens einen Takt. Zzgl. den Code um das mit den Klammern umzusetzen. |
|
Nach oben |
|
 |
Jojo alter Rang

Anmeldungsdatum: 12.02.2005 Beiträge: 9736 Wohnort: Neben der Festplatte
|
Verfasst am: 23.07.2009, 15:58 Titel: |
|
|
Ein Prozessor kennt keine Klammern... Der führt das nur in der richtigen Reihenfolge aus.
Außerdem, wer sagt dir dass BSWAP atomar ist, also wirklich nur einen Taktyklus benötigt? _________________ » Die Mathematik wurde geschaffen, um Probleme zu lösen, die es nicht gäbe, wenn die Mathematik nicht erschaffen worden wäre.
 |
|
Nach oben |
|
 |
St_W

Anmeldungsdatum: 22.07.2007 Beiträge: 956 Wohnort: Austria
|
Verfasst am: 23.07.2009, 22:28 Titel: |
|
|
@Jojo,28398: Es kommt ja immer wieder vor, dass ihr zwei euch gegenseitig mit (mehr oder weniger) sinnvollen Beiträgen von eurer Meinung überzeugen wollt (was ja solang es sachlich bleibt nichts Schlechtes ist). Normalerweise möchte ich mich ja in sowas nicht einmischen, aber dieses Mal muss ich doch 283.. Recht geben:
BSWAP ist definitiv schneller, benötigt weniger Speicherplatz, und einfacher zu verstehen, .., als ein paar SHL, AND, OR, ...
Code: | FreeBasic macht z.B. aus
((x shr 8) and &HFF) or ((x shl 8) and &HFF00)
den folgenden Assemblercode:
(sinngemäß vereinfacht, einige zusätzliche MOV, PUSH & POP entfernt)
shr eax, 8
and eax, 255
shl ebx, 8
and ebx, 65280
or eax, ebx |
Auf einem Intel 80486er Prozessor benötigt BSWAP 2 Bytes Speicherplatz und einen (1) Takt zur Ausführung.
Obiges Beispiel im Vergleich:
shr reg,const 3 Takte, 2 Bytes
and reg,const 1 Takt, 3 Bytes
shl reg,const 3 Takte, 2 Bytes
and ebx,const 1 Takt, 3 Bytes
or reg,reg 1 Takt, 2 Bytes
===========================
9 Takte, 12 Bytes
Welches von den beiden da einfacher, schneller und Speicherplatzschonender ist muss ich wohl kaum noch ausführlich erleutern...
(Lasset die Flut von Gegenargumenten beginnen... ) _________________ Aktuelle FreeBasic Builds, Projekte, Code-Snippets unter http://users.freebasic-portal.de/stw/
http://www.mv-lacken.at Musikverein Lacken (MV Lacken) |
|
Nach oben |
|
 |
Jojo alter Rang

Anmeldungsdatum: 12.02.2005 Beiträge: 9736 Wohnort: Neben der Festplatte
|
Verfasst am: 23.07.2009, 22:43 Titel: |
|
|
Einfaches Gegenargument: Läuft nur auf x86-Plattformen. Gerade durch die Entwicklung von OpenMPT / libmodplug (und auch die Vorlesung Rechnersysteme ) wurde ich auf so Plattformabhängigkeiten aufmerksam. Es mag sein, dass FB im Moment nur für x86 existiert, aber Sourcecode sollte immer so zukunftssicher wie eben möglich sein - Von daher, bei so trivialen dingen lieber gleich alles so machen, wie es auch noch in fünf Jahren funktionieren wird! _________________ » Die Mathematik wurde geschaffen, um Probleme zu lösen, die es nicht gäbe, wenn die Mathematik nicht erschaffen worden wäre.
 |
|
Nach oben |
|
 |
volta
Anmeldungsdatum: 04.05.2005 Beiträge: 1876 Wohnort: D59192
|
Verfasst am: 24.07.2009, 00:12 Titel: |
|
|
Jojo, zieh die Brense ...
In anderen Sprachen mag diese Art Portierbarkeit ihre Berechtigung haben.
In Freebasic mache ich mir in punkto Portierbarkeit höchstens Gedanken ob es noch in älteren oder neueren Versionen (auch Win-Versionen) kompiliert wird.
Sicher, BSWAP läuft nur auf x86-Pattform, dort habe ich damit eine schnelle Möglichkeit zu konvertieren.
Auf Plattformen die im Big Endian-Format lesen brauche ich diese Anweisung nicht. Die müssen sich entsprechendes für Little Endian-Format einfallen lassen.
Ich wüßte im Moment auch nicht wie ich andere Freebasic-Anweisungen z.B. "SCREEN 18" portierbar machen sollte? _________________ Warnung an Choleriker:
Dieser Beitrag kann Spuren von Ironie & Sarkasmus enthalten.
Zu Risiken & Nebenwirkungen fragen Sie Ihren Therapeuten oder Psychiater. |
|
Nach oben |
|
 |
Jojo alter Rang

Anmeldungsdatum: 12.02.2005 Beiträge: 9736 Wohnort: Neben der Festplatte
|
Verfasst am: 24.07.2009, 14:13 Titel: |
|
|
das macht freebasic ja für dich. der SCREEN-Aufruf ist ja überall identisch.
Dass du nicht BigEndian in BigEndian konvertieren musst, ist natürlich ein argument...  _________________ » Die Mathematik wurde geschaffen, um Probleme zu lösen, die es nicht gäbe, wenn die Mathematik nicht erschaffen worden wäre.
 |
|
Nach oben |
|
 |
28398
Anmeldungsdatum: 25.04.2008 Beiträge: 1917
|
Verfasst am: 24.07.2009, 18:29 Titel: |
|
|
Ich behaupte einfach mal, dass es sowas ähnliches wie BSWAP auch in vielen anderen Architekturen gibt.
Klar wäre das hier ein C Forum hättest du recht, aber falls FBC jemals was anderes als x86 (x86_64) unterstüzten sollte (was überhaupt nicht zu erwarten ist, da die Entwicklung nahezu stagniert ist), ist das auch nur ein #IfDef _X86 o. ä. |
|
Nach oben |
|
 |
|
|
Du kannst keine Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum nicht antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen.
|
|