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


von Klaus...(Norad) (Gast)


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

von Peter D. (peda)


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

von Klaus...(Norad) (Gast)


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

von Läubi (Gast)


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 :)

von Klaus...(Norad) (Gast)


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

von Peter D. (peda)


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

von Klaus...(Norad) (Gast)


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

von Läubi (Gast)


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.

von ??? (Gast)


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.

von Simon K. (simon) Benutzerseite


Lesenswert?

schieben? addieren !

von Simon K. (simon) Benutzerseite


Lesenswert?

1
void inttoasc(signed int Val, unsigned char *s)
2
{
3
4
    unsigned char temp;
5
    unsigned char i=0;
6
   
7
    if (Val & 0b1000000000000000)                           //Signed
8
Bit ?
9
    {
10
        s[i] = '-';                                        
11
//-Zeichen ausgeben
12
        Val = Val ^ 0b1111111111111100;                     //Alles
13
invertieren (Bit 0 und 1 ist IMMER LOW und muss ignoriert werden)
14
        Val += 1;                                          
15
//Korrekterweise 1 addieren
16
    
17
    } else
18
    {
19
        s[i] = ' ';                                         //kein
20
Signed, dann Leerstelle ausgeben
21
    }
22
    
23
    
24
    temp  = Val/1000;                                       //temp2 =
25
1000er Stelle
26
    Val   = Val%1000;                                       //Val =
27
Rest von 1000er Division
28
    s[++i]  = temp+48;                                      //+48 für
29
ASCII Umwandlung
30
31
    temp  = Val/100;                                        //temp2 =
32
100er Stelle
33
    Val   = Val%100;                                        //Val =
34
Rest von 100er Division
35
    s[++i]  = temp+48;                                      //+48 für
36
ASCII Umwandlung
37
38
    temp  = Val/10;                                         //temp2 =
39
10er Stelle
40
    Val   = Val%10;                                         //Val =
41
Rest von 10er Division
42
    s[++i]  = temp+48;                                      //+48 für
43
ASCII Umwandlung
44
45
    s[++i]  = Val+48;                                       //Nur noch
46
Rest ausgeben und +48 für ASCII Umwandlung
47
    
48
    s[++i]  = '\0';                                         //String
49
Ende

von Simon K. (simon) Benutzerseite


Lesenswert?

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

von Peter D. (peda)


Lesenswert?


von Klaus...(Norad) (Gast)


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

von Klaus...(Norad) (Gast)


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

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.