Zahl -> String
-
Hi!
Welche Möglichkeiten gibt es eigentlich in (x86) assembler eine Zahl in einen String zu konvertieren und umgekehrt?
-
Prinzipiell die gleichen wie auf jedem anderen programmierbaren Rechner-System mit jeder anderen Sprache auch.
-
Und ... wie? Ich steh grad irgendwie aufm Schlauch!
-
Hm... Dann versuche ich's mal (keine Garantie auf Korrektheit - mir schwirrt gerade die Ruebe
) :
Ok, Zahl (ich nehme mal an: int)->String (ASCII):
Du nimmst dir deinen int und dividierst ihn so lange durch die Basis des Zahlensystems, das du im String sehen willst (also zB. 10 fuer das Dezimalsystem), bis nichts mehr uebrig bleibt (also Quotient == 0 ist Abbruchbedingung der Schleife). Die "Reste" der Divisionen stellen nun die Ziffern deiner Zahl dar. Um das Ganze nun zB. fuer Dezimal in ASCII umzuwandeln, addierst du je auf alle Ziffern 0x30 (ASCII '0'). Da die Divisionen die Ziffern in "umgekehrter" Reihenfolge liefern (niedrigste Ziffer zuerst) musst du evtl. noch in deinem String die Reihenfolge umkehren -> fertig.String->Zahl ist vom Prinzip her das Gleiche:
Du nimmst dir das letzte Zeichen und wandelst es von ASCII in eine 0-basierte Ziffer um (fuer dezimal einfach wieder die 0x30 wieder abziehen - dabei kannst du auch gleich pruefen, ob das Zeichen in '0'-'9' war). Addierst es auf deine Variable, wenn du das erste Zeichen erreicht hast, waere hier der Punkt, auszusteigen. Sonst multiplizierst du das ganze mit der Basis der im String dargestellten Zahl, nimmst das vorherige Zeichen (dh. eins vor dem Letzten, usw. bis Anfang), wandelst es in eine 0-basierte Ziffer, addierst, pruefst Abbruchbedingung, usw.Je nach Zahlensystem gibt es natuerlich noch unterschiedliche Optimierungsmoeglichkeiten...
-
Ah ok, danke, warum bin ich da nich selber draufgekommen
Jetzt würde mich noch eins interessieren:
Kann man mit irgendeiner Berechnung rausfinden, was bei einer zahl x mit der basis n die anzahl Anzahl an Ziffern ist? Denn irgendwie muss man ja in Assembler, oder andere API's in C oder ähnlichem rausfinden, wie viel Speicher man für die Konvertierung reservieren muss.
Man könnte ja erst mal probieren mehrmals durch 10 zu teilen, aber da gibts doch sicher auch ne elegantere lösung, oder?
-
Ich denke, das Eleganteste wird sein, pauschal das Maximum moeglicher Stellen zu reservieren. So unglaublich viel ist das idR. nicht.
-
konvertierungen dieser art kann man auch mit substitution realisieren (mit hilfe von xlatb). ist der wertebereich recht gering (wie bei konvertierungen von zahlen zu chars) spricht auch nichts dagegen die substititionstabelle im codesegment zu integrieren. der vorteil dieser methode ist der geringe rechenaufwand. hier ein beispiel um ein beliebiges byte als char in hexdarstellung (also "00" bis "FF") zu konvertieren.
mov bx, $+0x10 mov ah, al shr ah, 0x04 and al, 0x0F xlatb xchg al, ah xlatb jmp $+0x12 db 0x30 db 0x31 db 0x32 db 0x33 db 0x34 db 0x35 db 0x36 db 0x37 db 0x38 db 0x39 db 0x41 db 0x42 db 0x43 db 0x44 db 0x45 db 0x46
wie man sehen kann definiere ich die zeichen "0" bis "F" mittels db im codesegment. man beachte das '$', welches eine nasm/yasm erweiterung ist. der assembler ersetzt dieses mit der aktuellen adresse im codesegment.
das umzuwandelnde byte wird in al erwartet, das ergebnis ist in ax.edit: oh ja, der code kommt aus einem kleinen testprojekt von mir, welches im realmode des prozessors ausgeführt wird. daher das 16 bit bx register. im 32/64bit mode erwartet xlatb die adresse der substitutionstabelle entsprechend in ebx, bzw. rbx.