-         

Ergebnis 1 bis 7 von 7

Thema: 16-Bit Parameter vom Stack holen und in 2 Register packen

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    01.07.2008
    Beiträge
    10

    16-Bit Parameter vom Stack holen und in 2 Register packen

    Anzeige

    Hi, im Zuge meiner Klausurvorbereitung, hänge ich an einer Übungsaufgabe:

    "Einem Unterprogramm sollen 2 Parameter über den Stack übergeben werden:
    A: 8-Bit
    B: 16-Bit

    Ergänzen Sie das untenstehende Programm derart, dass der Parameter A in r16, der Parameter B in r24:r25 geladen werden"

    Hier der vorgegebene code:
    Code:
    .cseg
    lds r16, A
    push r16
    lds r16, B+0
    push r16
    lds r16, B+1
    push r16
    rcall Unterprogramm
    
    .dseg
    A: .BYTE 1
    B: .BYTE 2
    .cseg
    
    Unterprogramm:
    ; Hier nun mein code den ich überlegt hatte
    pop r16       ;r16 von stack holen, müsste B+1 sein, also der HIGH-BYTE von B
    mov r24, r16
    pop r16       ;nächsten stack-Inhalt holen, müsste B+0 sein, also LOW-BYTE von B
    mov r25, r16
    pop r16       ;letzten Teil vom stack holen, müsste A sein, somit fertig
    ret              ;return
    Kann es so einfach sein ?? Irgendwie sieht mir das nicht richtig aus. Muss ich irgendwie dem System noch sagen dass in r24 die HIGH-bytes sein sollen und die dazugehörigen LOW-bytes in r25 ?
    Oder muss ich bei späterer Verwendung selber mich "erinnern" dass r24 und r25 gemeinsam eine 16-Bit-Wert darstellen ?

    Sorry falls ich so blöd frage, aber alle haben doch ein gewisses Problem mit der Didaktik unseres Dozenten, so dass so (anscheinend) einfache Dinge wie der Umgang mit 16-Bit-Werten in 8-Bit-Registern nicht grad detailliert durchgenommen wurde.

    Hoffe auf Hilfe hier

    Gruss,
    Lalas

  2. #2
    Erfahrener Benutzer Roboter Experte Avatar von sternst
    Registriert seit
    07.07.2008
    Beiträge
    672

    Re: 16-Bit Parameter vom Stack holen und in 2 Register packe

    Nein. Du vergisst, dass "rcall Unterprogramm" die Rücksprungadresse für das "ret" auf den Stack packt.
    Also überlegt nochmal.

  3. #3
    Super-Moderator Robotik Visionär Avatar von PicNick
    Registriert seit
    23.11.2004
    Ort
    Wien
    Beiträge
    6.836
    Werte auf den Stack laden, is ja klar:
    Code:
              lds r16, A 
              push r16 
              lds r16, B+0 
              push r16 
              lds r16, B+1 
              push r16
    Situation auf dem Stack:
    stckp + 2 -> wert A
    stckp + 1 -> wert B+0
    stckp + 0 -> wert B+1

    aaaaaaber:
    Jetz rufst du dein Unterprogramm
    RCALL Unterprogramm

    und so sieht daher der Stack beim Unterprogramm aus
    stckp + 4 -> wert A
    stckp + 3 -> wert B+0
    stckp + 2 -> wert B+1
    stckp + 1 -> rücksprungadresse Hi
    stckp + 0 -> rücksprungadresse Lo

    Jetzt gibt's mehre Möglichkeiten:
    1) Brutal und nicht schön, geht aber:
    Code:
    Unterprogramm: 
            pop   r0       rücksprungadresse sichern    
            pop   r1       rücksprungadresse sichern      
    
            pop   R25    (B+1,  siehe oben)
            pop   R24    (B+0,  siehe oben)
            pop   R16    (A,  siehe oben)
    
    ;--- irgendwas machen, R0 und R1 aber in Ruhe lassen
    
            push   r1       rücksprungadresse wieder auf den Stack
            pop    r0       r0, r1 immer symmetrisch poppen, pushen !  
            ret
    2) Besser:
    Code:
    Unterprogramm: 
                    IN            ZL, SPL       Stackpointer nach ZL:ZH 
                    IN            ZH, SPH                übernehmen
    ; und mit "Offset"  in die Zielregister laden
                    LDD          R25, Z+2      (B+1,  siehe oben)
                    LDD          R24, Z+3      (B+0,  siehe oben)
                    LDD          R16, Z+4      (A,  siehe oben)
    
    ;--- irgendwas machen
    
                   RET
    2) AAAAAAAAber:
    Im hauptprogramm müssen jetzt noch die drein gepushten
    Parameter wieder weg
    Daher sieht das jetzt so aus
    Code:
              lds r16, A 
              push r16 
              lds r16, B+0 
              push r16 
              lds r16, B+1 
              push r16 
            RCALL    Unterprogramm 
             pop     r0    (irgendein Register)
             pop     r0    (irgendein Register)
             pop     r0    (hauptsache, der Stack stimmt wieder)
    
    ------- jetzt ist alles wieder paletti
    Is gar nicht so ohne
    mfg robert
    Wer glaubt zu wissen, muß wissen, er glaubt.

  4. #4
    Neuer Benutzer Öfters hier
    Registriert seit
    01.07.2008
    Beiträge
    10
    Zitat Zitat von PicNick
    Situation auf dem Stack:
    stckp + 2 -> wert A
    stckp + 1 -> wert B+0
    stckp + 0 -> wert B+1

    aaaaaaber:
    Jetz rufst du dein Unterprogramm
    RCALL Unterprogramm

    und so sieht daher der Stack beim Unterprogramm aus
    stckp + 4 -> wert A
    stckp + 3 -> wert B+0
    stckp + 2 -> wert B+1
    stckp + 1 -> rücksprungadresse Hi
    stckp + 0 -> rücksprungadresse Lo
    okay, soweit verstanden, ich muss als die Rücksprung-Adresse (welche ja 16-Bit ist) zunächst vom stack holen und sichern.

    Zitat Zitat von PicNick
    Jetzt gibt's mehre Möglichkeiten:
    1) Brutal und nicht schön, geht aber:
    Code:
    Unterprogramm: 
            pop   r0       rücksprungadresse sichern    
            pop   r1       rücksprungadresse sichern      
    
            pop   R25    (B+1,  siehe oben)
            pop   R24    (B+0,  siehe oben)
            pop   R16    (A,  siehe oben)
    
    ;--- irgendwas machen, R0 und R1 aber in Ruhe lassen
    
            push   r1       rücksprungadresse wieder auf den Stack
            pop    r0       r0, r1 immer symmetrisch poppen, pushen !  
            ret
    Hier kommt eine Frage auf. Alles soweit verständlich, aber wieso schiebst du r1 auf den stack zurück (push r1) und machst dann pop r0 ?? r0 muss doch auch zurück auf den stack, also push r0.
    Denkfehler von mir oder war das ein Schreibfehler ?

    Zitat Zitat von PicNick
    2) Besser:
    Code:
    Unterprogramm: 
                    IN            ZL, SPL       Stackpointer nach ZL:ZH 
                    IN            ZH, SPH                übernehmen
    ; und mit "Offset"  in die Zielregister laden
                    LDD          R25, Z+2      (B+1,  siehe oben)
                    LDD          R24, Z+3      (B+0,  siehe oben)
                    LDD          R16, Z+4      (A,  siehe oben)
    
    ;--- irgendwas machen
    
                   RET
    2) AAAAAAAAber:
    Im hauptprogramm müssen jetzt noch die drein gepushten
    Parameter wieder weg
    Daher sieht das jetzt so aus
    Code:
              lds r16, A 
              push r16 
              lds r16, B+0 
              push r16 
              lds r16, B+1 
              push r16 
            RCALL    Unterprogramm 
             pop     r0    (irgendein Register)
             pop     r0    (irgendein Register)
             pop     r0    (hauptsache, der Stack stimmt wieder)
    
    ------- jetzt ist alles wieder paletti
    Aber ist das nicht gepfuschter code, wenn ich einfach die letzten 3 stack-Inhalte runterhole, nur damit der stack wieder korrekt ist ?

    Aber vielen Dank für die Erläuterungen.

    Noch eine Sache zum Verständnis:

    Wenn ich also einen 16-Bit Wert in z.B. r20, r21 packe, dann muss ich nicht irgendwie defnieren was davon HIGH-byte und LOW-byte ist ?? ich kopiere die einfach rein und muss bei späterer Verwendung halt selber wissen in welchem Register welcher Inhalt ist ?

    Weil bei den Registern X, Y , Z ist ja die Unterteilung in L und H gegeben

  5. #5
    Super-Moderator Robotik Visionär Avatar von PicNick
    Registriert seit
    23.11.2004
    Ort
    Wien
    Beiträge
    6.836
    war das ein Schreibfehler ?


    gepfuschter code ?
    durchaus nicht. Man könnte auch die Zahl 3 auf den Stackpointer addieren, is genauso grauslich.

    Das Problem ist, dass die Sache mit den Parametern für Unterprogramme gar nicht so ohne ist. Jede Hochsprache von C aufwärts bis Java hat da ihren eigene "CALL standards", will dir damit garnicht erst die Ohren voll-labern.
    However, beim Assembler hört der gottgegebene Standard bereits mit POP u. PUSH auf, der Rest bleibt dir überlassen.

    Hi- Lo: meist (bei den AVRs und anderen) isses so, dass 16-Bit gruppierungen immer aus dem geraden (low) und dem ungeraden Register (high) bestehen. R0:R1 , ..... R24:R25

    Das gilt aber zwingend nur für diese 16-Bit Befehle (ADIW, LD, etc.) Es hängt also vom Befehl ab

    Wenn du also LD r24, X sagen willst (muttu gucken) MUSS
    xl mit low und Xh mit hi geladen sein

    Bei anderen Befehlen is dem AVR das eigentlich völlig wurst. Ich würde aber raten, diese verwendung von hi-lo auch beizubehalten.
    mfg robert
    Wer glaubt zu wissen, muß wissen, er glaubt.

  6. #6
    Neuer Benutzer Öfters hier
    Registriert seit
    01.07.2008
    Beiträge
    10
    Zitat Zitat von PicNick
    war das ein Schreibfehler ?
    Tut mir leid, ich hab grad eine seeeeehhhrrr laaange Leitung

    Soll dein rot werdender Smiley bedeuten das es ein Schreibfehler war ?

    Wenn nicht habe ich nicht ganz verstanden wieso r1 auf den stack gepackt wird und danach wieder vom stack geholt wird in ein anderes register

  7. #7
    Super-Moderator Robotik Visionär Avatar von PicNick
    Registriert seit
    23.11.2004
    Ort
    Wien
    Beiträge
    6.836
    ISt ein Schreibfehler
    mfg robert
    Wer glaubt zu wissen, muß wissen, er glaubt.

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •