Assembler/BASIC: Upper + Lower String Funktionen


Assembler/BASIC: Upper + Lower String Funktionen

von mp-one » Mo 18. Mai 2009, 13:47
Hallo Assembler-Freunde,

ich habe für ein Programm, an dem ich gerade bastele, Assembler-Routinen zum Aufruf aus BASIC (X=USR...) heraus geschrieben, die zur Konvertierung von Strings in Groß- und Kleinbuchstaben dienen sollen. Die Routinen funktionieren soweit. Ich bin nicht so ganz sattelfest in Assembler und habe bestimmt einiges "durch die Brust ins Auge" programmiert. Ich traue mich aber trotzdem mal, sie hier zu posten :oops:. Vielleicht könnt Ihr mal einen Blick drauf werfen und ggf. Optimierungsvorschläge machen. Ist evtl. ja auch für andere ASM-Freunde interessant.

Code: Alles auswählen
* UPPERCASE 255
* KONVERTIERT STRING IN GROSSBUCHST.
* FUER STRINGS BIS 255 ZEICHEN
* ERSTELLT:18.05.2009
* GEANDERT:18.05.2009
* ASSEMBLER: ATMAS II

SADR     EQU $CB  STRING ADRESSE

         ORG $0600         Startadresse
         PLA               Anzahl Param. vom Stack holen
         PLA               Adresse des Strings :H
         STA SADR+1        speichern
         PLA               Adresse des Strings :L
         STA SADR          speichern
         LDY #$0
START    LDA (SADR),Y      HOLE ZEICHEN
         CMP #$00          STRING-ENDE erreicht?
         BEQ EXIT          JA: ENDE
         CMP #$60          >96 : KLEINBUCHSTABEN?
         BMI CONT          NEIN: nächstes Zeichen
         AND #$DF          JA: -32
         STA (SADR),Y      ZEICHEN SPEICHERN
CONT     INY
         CPY #$FF          255 ERREICHT?
         BNE START
EXIT     RTS


Die Routine holt erst die Adresse des Strings vom Stack, prüft dann für jedes Zeichen, ob es >96 ist und falls ja, wird 32 durch ausmaskieren von Bit 5 abgezogen. Das geänderte Zeichen wird dann wieder zurückgeschrieben. Das geht solange, bis entweder ATASCII #0 (Stringende) oder 255 Durchläufe erreicht sind. Die LOWER-Routine macht fast das Gleiche, nur wird auf <91 geprüft und dann durch Setzen von Bit 5 mit ORA $5B 32 addiert.

Bei Gelegenheit will ich die Routine noch für eine Länge von bis zu 65535 umschreiben. Aber da muss ich mich noch in die 16-Bit-Additionen reinfuchsen.

Gruß,

Michael

von Ghost » Mo 18. Mai 2009, 15:06
Hi Michael,
das cmp #$00 koenntest Du weg lassen. Wenn das
LDA (SADR),Y den Akku mit 0 laedt, wird das Zero-Flag
automatisch gesetzt.
BEQ verzweigt abhaengig vom Zero-Flag. Ist das Zero-Flag
gesetzt, wird verzweigt.

Beste Gruesse
Martin

von cas » Mo 18. Mai 2009, 16:56
Hi,

bei der Laengen-Abfrage kann man auch optimieren, INY setzt auch das Zero-Flag wenn das Y-Register auf 0 gezaehlt wird. Also statt

Code: Alles auswählen
CONT     INY
         CPY #$FF          255 ERREICHT?
         BNE START


geht auch

Code: Alles auswählen
CONT     INY
             BNE START    0 ERREICHT?


so kann man auch mit vollen 255 Byte Strings arbeiten.

Ciao

Carsten

von cas » Mo 18. Mai 2009, 17:07
bei 16bit nicht mit addition arbeiten, sondern auch mit INC

Beispiel:

Code: Alles auswählen
SADR     EQU $CB  STRING ADRESSE

         ORG $0600         Startadresse
         PLA               Anzahl Param. vom Stack holen
         PLA               Adresse des Strings :H
         STA SADR+1        speichern
         PLA               Adresse des Strings :L
         STA SADR          speichern
         LDY #$0
START    LDA (SADR),Y      HOLE ZEICHEN
         BEQ EXIT           STRING-ENDE erreicht?  JA: ENDE
         CMP #$60          >96 : KLEINBUCHSTABEN?
         BMI CONT          NEIN: nächstes Zeichen
         AND #$DF          JA: -32
         STA (SADR),Y      ZEICHEN SPEICHERN
CONT     INC SADR       low erhoehen
             BNE START     kein ueberlauf -> start
             INC SADR+1   sonst, high erhoehen
             BNE START     und weiter
EXIT     RTS

von mp-one » Mo 18. Mai 2009, 21:03
Hallo cas & Ghost,

vielen Dank, das sind genau die Tricks, wo es bei mir noch hapert. Die Verwendung des Register-Überlaufs und die Kenntnis, welche Flags genau beeinflusst werden. Ich werde Eure Tipps demnächst mal einarbeiten.

Welche Assembler-Bücher würdet Ihr empfehlen? Ich habe "Der ATARI Assembler" von D.&K. Inman und "Das Assemblerbuch" von P. Finzel als "richtige" Bücher und dann natürlich die Online-Bücher auf atariarchives in Reichweite.

Beste Grüße,

Michael

von cas » Di 19. Mai 2009, 00:02
Die 6502 Buecher von Rodney Zaks sind gut
http://www.amazon.com/Programming-6502- ... 0895880466

Auch das CompyShop Magazin hatte gute Assembler Tutorials.

www.6502.org ist DIE Quelle fuer alle 6502 Programmierer

http://www.6502.org/books

Bei AtariArchives gibt es das Buch "Machine Language For Beginners"
http://www.atariarchives.org/mlb/

Apple Assembly Line ist eine sehr gute Quelle fuer Assembler Tricks:
http://homepage.mac.com/bobsc/aal/

The Art of Assembly Language
http://webster.cs.ucr.edu/A2%20Hyde%206 ... 20Lang.pdf

Fuer Atari-Spezifische Assembler Programmierung:

Mapping the Atari
Atari Profibuch
Atari Hardware Reference (Bob Duhamel)
ABBUC Atari Compyshop Hardware Buch (Jahresgabe)
Atari Roots -> http://www.atariarchives.org/roots/index.php

von Dietrich » Di 19. Mai 2009, 22:24
@mp-one: Etwas seltsam finde ich die Abfrage:

Code: Alles auswählen
cmp #$60
bmi cont

In Pseudocode ist das gleichbedeutend mit IF A<$60 OR A>=$E0 THEN GOTO CONT, was vermutlich nicht gemeint war. Hat Dein String auch Sonderzeichen? Willst Du auch inverse Buchstaben verarbeiten? Dann benutze besser folgenden
Code: Alles auswählen
lda (sadr),y
tax                  Bit 7 merken
and #$7f
cmp #'a
bcc cont             < 'a
cmp #'z+1
bcs cont             >= 'z+1, also > 'z
and #$df             (oder sec: sbc #$20)
cpx #$80
bcc .1               ggf. Bit 7 wiederherstellen
ora #$80
.1 sta (sadr),y
cont

von mp-one » Mi 20. Mai 2009, 22:06
Dietrich hat geschrieben:@mp-one: Etwas seltsam finde ich die Abfrage:

Code: Alles auswählen
cmp #$60
bmi cont

In Pseudocode ist das gleichbedeutend mit IF A<60>=$E0 THEN GOTO CONT, was vermutlich nicht gemeint war. Hat Dein String auch Sonderzeichen? Willst Du auch inverse Buchstaben verarbeiten? Dann benutze besser folgenden
Code: Alles auswählen
lda (sadr),y
tax                  Bit 7 merken
and #$7f
cmp #'a
bcc cont             <a> 'z
and #$df             (oder sec: sbc #$20)
cpx #$80
bcc .1               ggf. Bit 7 wiederherstellen
ora #$80
.1 sta (sadr),y
cont


Hallo Dietrich,

danke für Deine Tipps! In den Strings, auf die ich die Routine anwende, kommen keine Sonderzeichen oder inverse vor, es ist nur Text. Nur deshalb funktioniert wohl die etwas unsaubere Abfrage mit dem CMP #$60. Deine Routine mit der Bereichsabfrage und dem Merken von Bit 7 für die inversen ist natürlich wesentlich universeller. Ich werde mal zur Übung eine Routine 2.0 basteln, die die hier genannten Tipps umsetzt.

Gruß,

Michael