Sub mit Parameter by Reg mit Alias

    This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

    • 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 Source Code

      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 Source Code

      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
      Display All
      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 Source Code

      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"
      Display Spoiler

      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 Source Code: 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
      Display All
      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?