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.


Anmelden zum Antworten