Sub mit Parameter by Reg mit Alias

    Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

    Aufgrund technischer Veränderungen ist der Mailverkehr innerhalb des Forums (Private Nachrichten) nur noch eingeschränkt möglich. Die Einschränkung ist notwendig, um zusätzliche Betriebskosten für das Forum zu vermeiden. Näheres zu den Hintergründen im Thread "Aktuelles zum Forum".Wir bitten um Verständnis.

    Hinweis kann nach Kenntnisnahme deaktiviert werden!

    • Sub mit Parameter by Reg mit Alias

      Hallo

      Ich versuche gerade Ausgabe-Routinen für das Display zu beschleunigen.

      Dafür habe ich 2 Sub-Routinen vorgesehen, die eine, um ein Byte auszugeben, die andere um ein Word auszugeben.
      Die Deklaration sieht wie folgt aus:

      BASCOM-Quellcode

      1. Declare Sub TFT_Write_Data(ByReg r18 as Byte)
      2. Declare Sub TFT_Write_Word(ByReg r18 as Word)


      Das funktioniert auch soweit.

      Die eigentlichen Ausgaberoutinen werden aber dann erst von der Sub angesprungen. Diese erwarten dann die Daten in bestimmten Registern.
      Dafür habe ich Aliasse definiert.

      BASCOM-Quellcode

      1. ' verwendete Register
      2. rTmpH Alias r19
      3. rTmpL Alias r18
      4. ' Hier die angesprungenen Assembler-Routinen
      5. ' Datenword auf Bus schreiben
      6. ' rTmpL enthält H-Byte; rTmpH enthält L-Byte
      7. _tft_write_word:
      8. Reset PIN_CS
      9. Set PIN_RS
      10. Config PORT_DATA = Output
      11. !RCALL _tft_write_byte ' zuerst H-Byte ausgeben
      12. !MOV rTmpL,rTmpH ' L-Byte in Ausgaberegister
      13. !RJMP _tft_write_byte ' L-Byte ausgeben
      14. _tft_write_data:
      15. Reset PIN_CS
      16. Set PIN_RS
      17. _tft_write_byte:
      18. Reset PIN_WR
      19. !OUT PORT_DATA,rTmpL
      20. Set PIN_WR
      21. !RET
      Alles anzeigen
      Jetzt ist es aber so, dass wenn ich z.B. ein Datenbyte ausgeben möchte, macht es doch aus Performance-Gründen Sinn, das richtige Register in der Deklaration der Sub anzugeben.
      Das erspart Rumschieben von Register und ist damit schneller.

      Jetzt zum Problem.
      Ich dachte, ich kann doch in der Deklaration auch den Alias des Registers nehmen. Wenn ich dann mal den Alias ändere, wird überall das neue Register verwendet.
      Ist doch praktisch - dachte ich.

      Die Routinen sehen dann so aus:

      BASCOM-Quellcode

      1. Sub TFT_Write_Data(ByReg rTmpL as Byte)
      2. !JMP _tft_write_data
      3. End Sub
      4. Sub TFT_Write_Word(ByReg rTmpL as Word)
      5. !JMP _tft_write_word ; Word ausgeben
      6. End Sub
      Die Routinen leiten also die Daten nur weiter an die Assembler-Routine.

      Den Alias in der 1. Routine (TFT_Write_Data()) nimmt der Compiler an.
      Wenn ich aber den Alias verwende, um ein Word zu übergeben, funktioniert das nicht.

      Error : 218 Line : 63 Register must be in range from R16-R31 [R1[1110KKKKDDDDKKKK]] , in File : C:\Users\Michael\Documents\Projekte\Experimente\Temp\noname1.bas

      Wieso geht der Alias, wenn ich Bytewerte übergebe, aber bei Word-Werten nicht? Ein Versehen? Bug?

      Hier noch ein Auszug aus der Hilfe "Declare Sub"
      Spoiler anzeigen

      BYREG


      Use BYREG to pass a copy of the variable using a register. The value will be passed to the register(s) you specify. When multiple bytes need to be passed, multiple registers will be used. Registers are named from R0-R31. When you pass a WORD to register R16, you will also use R17 since a word requires 2 bytes.


      You can not pass strings. Only numeric variables and constants.


      Using BYREG requires some knowledge of the routines you call. The current implementation does not protect already loaded registers. This means that when you pass multiple registers you could destroy some already loaded registers just because a parameter will destroy the register.


      Example : declare Sub MySub(byreg R16 as Word, byreg R18 as long, byreg R22 as dword)


      mysub 1000, var(J+100), var(j)


      In this example, R16 and R17 are loaded, after this the array index of variable var() need to be calculated which uses the ML16 routine which uses R16-R21


      Numeric constants and expression do not alter registers but functions might. A future version will track and protect registers.


      Why would you want to use BYREG ? Using BYREG is equivalent to using ASM. It is intended to be used with ASM code inside subs. The FT800 include files use BYREG and BYSTACK.





      Example from FT800:


      Sub Stencilfunc(byreg r18 As Byte , Byreg r17 As Byte , Byreg R16 As Byte)


      Cmd32 _stencilfunc(r18 , R17 , r16)


      End Sub



    • Ich habe es jetzt mal in der Version 2.0.8.2 getestet.
      Das verhalten ist das gleiche. Aber mir sind ein paar Dinge aufgefallen.

      Hier erst mal das Testprogramm:

      BASCOM-Quellcode: Testprogramm. Parameterübergabe ByReg mit Alias für Registername

      1. $Regfile = "m8def.dat"
      2. $hwstack = 30
      3. $swstack = 30
      4. $framesize = 30
      5. ' Register r0 bis r14 funktionieren
      6. ' Ab register r15 gibts Fehlermeldung:
      7. ' "Error : 218 Line : 16 Register must be in range from R16-R31 [R1[1110KKKKDDDDKKKK]] , in File : C:\Users\Michael\Documents\Projekte\Temp\noname1.bas"
      8. rTmpL Alias r14
      9. 'Declare Sub _Test_Write_Word(ByReg r14 as Word) ' Das funktioniert korrekt
      10. Declare Sub _Test_Write_Word(ByReg rTmpL as Word) ' Mit Alias-Angabe (rTmpL) wird nur 1 Byte in die Register geschrieben
      11. Declare Sub _Test_Write_Byte(ByReg rTmpL as Byte)
      12. Do
      13. Call _Test_Write_Byte(&h66)
      14. Call _Test_Write_Word(&h1234)
      15. Loop
      16. ' Register rTmpL und rTmpH entgalten den Word-Wert
      17. _Test_Write_Word:
      18. !Ret
      19. _Test_Write_Byte:
      20. !RET
      Alles anzeigen
      Also zum einen:
      Die Fehlermeldung meint, dass das Register im Bereich von r16 bis r31 sein muss.
      Aber in dem Bereich wird genau der Fehler ausgegeben.
      Genauer, wenn ich in Zeile 9 Register r15 und höher einstelle gibt's Fehler in Zeile 12.

      Der Compiler meckert nicht, wenn ich Register < r15 (Zeile 9) einstelle.

      Aber jetzt wird nur 1 Byte per Register übergeben. Korrekt wären es, wenn 2 aufeinander folgende Register mit dem Wert belegt werden.

      Das funktioniert, wenn wie in Zeile 11 gezeigt, das Register direkt angegeben wird.

      Ich vermute hier ein Bug.
      Weis jemand mehr?
    • Hi

      Ich habe zwar null Zeit, doch ich konnte nicht widerstehen.
      Probier es so:

      BASCOM-Quellcode

      1. $Regfile="m328def.dat"
      2. $Crystal=4000000
      3. $hwstack=40
      4. $swstack=16
      5. $framesize=32
      6. Config Submode = new
      7. rTmpH Alias r19
      8. rTmpL Alias r18
      9. dim rTmp as iram word at 18 overlay
      10. Sub TFT_Write_Word(Byreg rTmp as Byte)
      11. !nop
      12. End Sub
      13. TFT_Write_Word 1234
      14. end
      Alles anzeigen
    • Den Parameter in der Sub als Byte deklarieren und dann Word übergeben?
      Wenn ich Compiler wäre, würde ich meckern.

      Es ist zudem keine gute Idee das Byte zuvor auch noch auf 2 Register (18 und 19) zu legen.
      Bascom nimmt keine Rücksicht auf Register, wenn es Befehle ausführt.
      Es könnte also passieren, dass ein Befehl die Register verwendet und dann war es da mit der Variablen rTmp.

      Und wieso noch übergeben, wenn die Werte schon im Register liegen?

      Trotzdem Danke für deinen Ideen-Ansatz.
    • Versuchst du mich etwa zu verhöhnen?

      Was Sinn macht oder keinen weiß ich selbst noch ganz gut und das war auch nicht die Frage, oder? Du wolltest den Registern in der Parameterliste einen Alias verpassen.
      Die Anlage einer Iram Variable ist da ein Mittel das funktioniert und ist hier nicht dazu gedacht als Variable außerhalb der Sub benutzt zu werden.

      Ich habe dir einen Weg gezeigt wie man es machen könnte. Gehe ihn oder lass es. Zumindest wie es nicht geht, hast du ja selbst herausgefunden.
    • Ich habs in einem Display mal umgesetzt mit zwei Words . Rennt wie die Katz. a_38_b45e201d

      Quellcode

      1. Rcolh Alias R19
      2. Rcoll Alias R18
      3. Dim Rcol As Iram Word At 18 Overlay
      4. Rzahh Alias R25
      5. Rzahl Alias R24
      6. Dim Rzah As Iram Word At 24 Overlay
      7. Dim Rout As Iram Byte At 18 Overlay
      8. Declare Sub Lcd_write_data(byreg Rout As Byte)
      9. Declare Sub Lcd_write_col(byreg Rcol As Byte , Byreg Rzah As Byte)
      10. '*************************************************
      11. Sub Lcd_write_data(byreg Rout As Byte) '4
      12. $asm
      13. cbi portd,4 '2 Res CS
      14. sbi portd,5 '2 Set Data
      15. ldi r16,8 '1 Bitzähler
      16. Rol r18 '1 Highbit in Carry
      17. cbi portb,6 '2 Res CLK
      18. brcs +3 '1 Sprung if Carry High
      19. cbi portb,7 '2 Res Data
      20. jmp +2 '2 Überspringe nächstes
      21. sbi portb,7 '2 Set Data
      22. sbi portb,6 '2' Set CLK
      23. dec r16 '1
      24. brne -8 '2
      25. sbi portd,4 '2 Set CS
      26. $end Asm '4 '116
      27. End Sub
      28. '**********************************************************
      29. Sub Lcd_write_col(byreg Rcol As Byte , Byreg Rzahl As Byte)
      30. $asm '7
      31. cbi portd,4 '2 Res CS
      32. sbi portd,5 '2 Set Data
      33. Co1:
      34. mov r17,r19 '1 FarbHigh
      35. ldi r20,2 '1 Bytezähler
      36. ldi r16,8 '1 Bitzähler
      37. 'Highcol
      38. Rol r17 '1 Highbit in Carry
      39. cbi portb,6 '2 Res CLK
      40. brcs +3 '1 Sprung if Carry High
      41. cbi portb,7 '2 Res Data
      42. jmp +2 '2 Überspringe nächstes
      43. sbi portb,7 '2 Set Data
      44. sbi portb,6 '2' Set CLK
      45. dec r16 '1
      46. brne -8 '2
      47. ldi r16,8 '1
      48. mov r17,r18 '1
      49. 'Lowcol
      50. Rol r17 '1
      51. cbi portb,6 '2
      52. brcs +3 '1
      53. cbi portb,7 '2
      54. jmp +2 '2
      55. sbi portb,7 '2
      56. sbi portb,6 '2'
      57. dec r16 '1
      58. brne -8 '2
      59. sbiw r24 ,1 ' Word zähler
      60. brne co1 ' Noch mal?
      61. sbi portd,4
      62. $end Asm
      63. End Sub
      Alles anzeigen
      Würden die Register geschickt ausgewählt könnten die Variablen sogar außerhalb der Sub genutzt werden z.B. den Rest einer Berechnung abzuholen (anstelle MOD)
    • Galahat schrieb:

      rcol ist wohl schon irgendwo benannt.
      Scheint so zu sein, obwohl weder die Hilfe noch die .def es kennen. :huh:
      Dann sind die Endungen 0 und 1 zwingend. Da gefällt mir die erste Variante besser. ^^
      Mit "Dim Rcol As Iram Word At 18 Overlay" alleine gehts auch. Ich denke das wird meine favorisierte Methode.
      Auch wenn der Aufruf "as Byte" dann eher unlogisch aussieht so hat es den Vorteil (die Gefahr) :evil: von Außen darauf zugreifen zu können.
    • Galahat schrieb:

      Numm alias....oder beides
      Oder beides nicht ;) Einzelne Register lassen sich auch problemlos auch mit Namen bearbeiten (Tmp=R18).
      Bei einem Word ist die Iram im Vorteil zu zwei Einzelanweisungen mit Overlay Variablen
      Dim Rcol As Iram Word At 18 Overlay
      Dim Tempw As Word

      Tempw=Rcol (Eine Zeile , 6 Takte) zu

      Dim Tempwl As Byte At Tempw Overlay
      Dim Tempwh As Byte At Tempw + 1 Overlay
      Tempwl = R18
      Tempwh = R19 (Vier Zeilen , 8 Takte)

      Über ".def" konnte ich nichts finden. Eine Alias Version in ASM? Dann vermutlich nur dort gültig/bekannt.
      Auch das läßt sich compilieren:
      !.def Arcol0 = R20
      Arcol0 Alias R18
      Arcol1 Alias R19
      !.def Arcol0 = R20(position egal) . Es wird erst wirksam wenn das alias auskommentiert wird

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Pluto25 ()