mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Umwandlung integer Zahl in einen String (Hilfe)


Autor: Klaus...(Norad) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!
ich hoffe ich bin im richtigen Thread!

Ich möchte folgendes Codefragment in Assembler realisieren
(8051 - Code)

        if(zahl >= 1000 )
    buffer[1] = (zahl/1000) %10 + 0x30;

Also ich möchte eine x belibeige Integerzahl in einen String umwandeln
und ihn am einem Grafigdisplay ausgeben das ganze möchte ich in
Assembler realisieren so das auch von C aufgerufen werden kann.

Die Übergabe einer Dezimalzahl in C nach Assembler erfolgt über die
Register R7 bis R2.

Allerdings fehlt mir der Ansatz wie man in Assembler sowas löst.

Z.B. wird die Zahl 4030 in R6 und R7 abgelegt und das auch noch in
Hex.

Und hier fangen die probleme schon an.


Ich hoffe das jemand ne Idee oder einen Ansatz hat.


Vielen Dank im vorraus.

Mfg Klaus

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Warum denn bloß Assembler unter C ?

Wenn Du unter C eine Assemblerfunktion aufrufen willst, dann mußt Du
wissen, welcher Compiler, welche Version, welches Speichermodell,
welche Optimierung.

Daher ist Assembler unter C nur der absolute Notnagel, nicht portabel
und fehleranfällig.
Man muß sich in jedem Fall sehr gut mit dem jeweiligen Compiler
auskennen.


Peter

Autor: Klaus...(Norad) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Peter!

Nun ich Arbeite momentan mit Ride von Raisonance und ich möchte es rein
intresse halber so ne routine schreiben weil in der Demoversion die
Function itoa  nicht zu verfügung steht.

Um die Programmen laufen zulassen benutze ich von Atmel den AT89C51ED2,
Speichermodell ist momentan auf small eingestellt.

Soweit laufen die Programme in Mischform.

Das Ziel ist ein Displaymodul zuschreiben ganz in Assembler mit allen
nötigen Funktionen die ich dann auch aus C aufrufen kann.

Dazu gehört eben auch Zahlen.

In C Funzt die sache schon nur hätte ich gerne es in Assembler

MFG   Klaus

Autor: Läubi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also man kann eine Zahl nicht "umwandeln".
Es gibt halt bytes auf Assembler Ebenee, wichtig ist wie du das
interpretierst.
In C ist es z.B. so, das ein String aus einer folge von Characters
besteht, abgeschlossen durch einen \0 (NULL) Character.

Du nimmst also jezt deine Zahl, teilst sie: 4 0 3 0
dann wandeslt du sie in die ASCII COdes um
52, 48, 52, 48 udn hängst noch ne 0 drann also schreisbt du an die
Adresse wo der String steht:

52 48 52 48 0

und fertig ist der String :)

Autor: Klaus...(Norad) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Läubi

Vielen Dank für deine Unterstützung dein Vorschlag habe ich schon in C
gelöst siehe Codfragment.

Vielmehr Interresiert mich wie das in Assembler realisiert wird.

Die X-belibige Zahl z.B. 4030 wird auf der Assmblerebene in R7,R6
abgelegt.
          R6 = 0F   und R7 = BE      ergibt logischerweise = 0FBE

Das Problem besteht jetzt darin die Zahl in beiden Registern  zuteilen
nach dem Schema Codfragment in C siehe Oben.

Ich weiss jetzt nich wie man es anstellt die Werte die in R6 und R7
abgelegt sind  richtig zuteilen.


Für jeden Tipp bin ich dankbar

MFG Klaus

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Frage ist immer noch, was soll das bringen, außer daß der Code
fehleranfälliger, schlechter wartbar und erweiterbar ist ?


Ich habe früher mal mit Assembler angefangen, hier findest Du was:

http://home.tiscali.de/peterd/appl/soft/arithmet/index.htm

Die Funktion ADIVR10 ist das, was Du brauchst.
Wie Du sie aber in Deinen C-Compiler einbindest, ist Dein Problem.


Peter

Autor: Klaus...(Norad) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Peter

Nun! was wirds mir bringen,mmmh  ich hoffe mehr verständnis.

Ich bin ja kein Profi hab nur  Grundwissen in Assembler und C und damit
die sache nicht ganz einschläft möchte ich noch etwas an
Programmiertechnik lernen.

Trotzdem Danke schön

MFG Klaus

Autor: Läubi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also... das war wie das in assembler funktioniert.
Der compiler legt das in zwei registern ab weil ein register nur 8bit
speicher kann (0...255) die zahl aber größer ist.
deswegen werden zwei regsiter zusammen gneommen.
Das prinzip ist aber das gleiche du teilst durch 10 natuerlich dann
16bit operation auf zwei register.
dann vom Orginal abziehen und schon hast du das ergebniss fuer die
lezte stelle, und immer so weiter bis du alle Zahlen hast.
diese dna nach dem mir beschriebene verfahren speicher und dann sollte
das klappen.

Autor: ??? (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aber dabei mal die Codetabelle des Displays anschauen! Bei ASCII ist
sinnigerweise die "0" auf 48dez also 30hex oder  110000bin man muss
also nur etwas schieben. Damit wird auch das BCD-Format noch
verständlicher. Das spart nicht nur Platz, das ist auch einfach durch
schieben zu verarbeiten.

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
schieben? addieren !

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
void inttoasc(signed int Val, unsigned char *s)
{

    unsigned char temp;
    unsigned char i=0;
   
    if (Val & 0b1000000000000000)                           //Signed
Bit ?
    {
        s[i] = '-';                                        
//-Zeichen ausgeben
        Val = Val ^ 0b1111111111111100;                     //Alles
invertieren (Bit 0 und 1 ist IMMER LOW und muss ignoriert werden)
        Val += 1;                                          
//Korrekterweise 1 addieren
    
    } else
    {
        s[i] = ' ';                                         //kein
Signed, dann Leerstelle ausgeben
    }
    
    
    temp  = Val/1000;                                       //temp2 =
1000er Stelle
    Val   = Val%1000;                                       //Val =
Rest von 1000er Division
    s[++i]  = temp+48;                                      //+48 für
ASCII Umwandlung

    temp  = Val/100;                                        //temp2 =
100er Stelle
    Val   = Val%100;                                        //Val =
Rest von 100er Division
    s[++i]  = temp+48;                                      //+48 für
ASCII Umwandlung

    temp  = Val/10;                                         //temp2 =
10er Stelle
    Val   = Val%10;                                         //Val =
Rest von 10er Division
    s[++i]  = temp+48;                                      //+48 für
ASCII Umwandlung

    s[++i]  = Val+48;                                       //Nur noch
Rest ausgeben und +48 für ASCII Umwandlung
    
    s[++i]  = '\0';                                         //String
Ende

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
die negativ routine stimmt nur halb, und i brauch man natürlich  nicht
dimensionieren.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Klaus...(Norad) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Vielen Dank vorerst für die vielen Tipps und Anregungen.

Ich werde mal das eine oder andere ausprobieren.

Werde dann Echo geben wenns Funzt.


Nochmal Dank an Alle!


MFG Klaus

Autor: Klaus...(Norad) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

ich hab mal hier was zusammen gebastelt das Funzt für mein problem.
Ich hoffe es lacht sich keiner kaputt aber zumindest kann ich damit
bis  4095 DEZ  in ASCII-Umwandeln und Direkt zum Display senden.
Der Aufruf zum senden an Display fehlt hier (ist Absicht).

Hier habe ich immer den Rest der division im Stack abgelegt.

Zur Erinnerung:  Ausgang war z.B. die Zahl 4030 dez in C und sollte in
Assembler übergeben werden in die Register R6 und R7 dort
steht die Zahl natürlich in Hex --> 0FBE h = 4030 dez .






$NOMOD51
$include(c51rd2.inc)

org      00h
         ljmp  Teilen



org      4000h

;Der hier beschriebene Ablauf gilt für einen Durchlauf
;Der Rest der Division im Register B wird im Stack abgelegt und wird
Später
;weiter verarbeitet.
;
Teilen:
         MOV  R6,#0Fh    ; 0FBEh  = 4030 dez in die Register R6 u. R7
laden
         MOV  R7,#0BEh   ;R6 u. R7 bilden den Dividenden
LOOP:    mov  B,#10      ;Divisor  ist 10

         mov  A,R6       ;Inhalt von R6 in Akku laden
         div  AB         ;Teile A / B    ( hier 0F / A = 1 Rest 5)
         mov  R0,A       ;Das Ergebnis in Register 0 ablegen
         mov  A,R7       ;Lade R7 in Akku ( hier  BE)
         anl  A,#0F0h    ;Lösche das unteres nibble
         orl  A,B        ;Verodere Akku mit Bilfsakku B  (Ergebnis =
B5)
         swap A          ;vertausche Akkuinhalt (Ergebnis = 5B) neuer
Dividend
         mov  B,#10      ;Divisor  ist 10
         div  AB         ;Teile A / B    ( hier 5B / A = 9 Rest 1)
         swap A          ;vertausche Akkuinhalt (Ergebnis = 90)
         mov  R1,A       ;Das Ergebnis in Register 1 ablegen
         mov  A,R7       ;Lade R7 in Akku ( hier  BE)
         swap A          ;vertausche Akkuinhalt (Ergebnis = EB)
         anl  A,#0F0h    ;Lösche das unteres nibble
         orl  A,B        ;Verodere Akku mit Bilfsakku B  (Ergebnis =
E1)
         swap A          ;vertausche Akkuinhalt (Ergebnis = 1E)
         mov  B,#10      ;Divisor  ist 10
         div  AB         ;Teile A / B    ( hier 1E / A = 3 Rest 0)
         orl  A,R1       ;Verodere Akku mit Bilfsakku B  (Ergebnis =
93)
         mov  R1,A       ;Das Ergebnis in Register 1 ablegen
         mov  a,R0       ;Neuer Dividend in Register 6 u. 7 ablegen
         mov  R6,A
         mov  A,R1
         mov  R7,A

      push B          ;Rest der divison im Stack ablegen
      cjne R7,#0,LOOP ;Widerhole bis Register 7  null ist
      pop  B          ;Stelle den Letzten Rest der Division
                      ;wieder her. ( hier   4)
      mov  A,#48      ;Lade den ASCII- Code für 0 (hier 30h)
      orl  A,B        ;wird nun ASCII = 4  (hier 34h)
      pop  B          ;Stelle den Letzten Rest der Division
                      ;wieder her. ( hier   0)
      mov  A,#48      ;Lade den ASCII- Code für 0 (hier 30h)
      orl  A,B        ;Aus 0 wird nun ASCII = 0  (hier 30h)
      pop  B          ;Stelle den Letzten Rest der Division
                      ;wieder her. ( hier   3)
      mov  A,#48      ;Lade den ASCII- Code für 0 (hier 30h)
      orl  A,B        ;Aus 3 wird nun ASCII = 3  (hier 33h)
      POP  B

         sjmp LOOP

         ret
END



Wenn jemand etwas besseres in Assembler einfällt darf er es hier ruhig
Posten.


MfG Klaus

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.