PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Assembler Korrekturlesen, bitte


Capt'N Coax
2003-03-08, 22:53:51
Hoi alle Mann,

Es wäre echt ne super Geste von euch, wenn mal einer "flux" über meinen Ko...äh Code liest.
Ich hab nämlich echt keinen Plan ob dat hier so alles stimmt oder obs net auch ne wesentlich elegantere Lösung gibt.

Zum Problem:

Eigentlich Super Simpel, folgendes soll berechnet werden:
2*A-B-4*C, genau in dieser Reihenfolge.

Jetz bin ich allerdings nich' so Assemblerbewandert, aber habs trotzdem mal umgesetzt, bekomme zwar offensichtlich richtige Ergebnisse, das Ganze is mir aber suspekt.

Nochn Problem:
Der Code is fürn 6502 Prozzi, da ist zu beachten, das die Adressen 8 Bit breit sind. Bei der Aufgabe muss also bei Bereichsüberschreitung ins nächste Adressfeld übergegangen werden. 2 Bytes reichen hier voll aus.
Besonderheit 6502:
Bei der Subtraktion muss vorher das Carry- Flag gesetzt werden, wenns bei der Rechnung verschwindet haben wir einen Borger, also is der Adressbereich überschritten und wir müssen in die nächste gehen.

Also:

1. Subtrahiert man so wie ich es gemacht habe, oder rechnet man evtl. direkt mit Komplementen??
2. Wie ließe sich der Code vereinfachen?
3. Ist es Interpretationssache des Proggers, ob es sich um Kardinalzahlen (0-255, 1111 1111) Handelt oder um Ganzzahlen (-128 - 127)??? Unterscheiden kann man dies ja am N-Flag (negative)
4. Gehe ich richtig vor, wenn ich ein Endergebniss, das ich als Negativ interpretiere, da N Flag, dieses Invertier, +1 Rechne ($100 Komplement) und n' Minus davorschreibe? Rein rechnerisch kommts hin.
5. Is der verfluchte Code richtig?

Yo, das wär echt verdammt cool, wenn einer davon n Plan hat, und mir das mal erklären könnte.

Hier nu der Code:

;2*A-B-4*C

.ORG $4000 ;Startbereich

;************ 2*A ***********

LDA a ;a in Akku laden
ASL ;Linksshift (evtl. Bereichsüberschreitung)
STA erg1 ;Niederwertiges Byte speichern in erg1
LDA erg1+1 ;Höherwertiges Byte laden
ADC #$00 ;eventuelles Carry in höherwertigem Byte
STA erg1+1 ;speichern

;*********** 2*A-B **********

SEC ;6502 spezifisch, Vor Subtraktion Carry Flag
LDA erg1 ;setzen!
SBC b ;Subtrahiere B von erg1
STA erg2 ;Speichern in erg2

BCC correct ;Carry Flag bei Sub. gelöscht, dann Borger!
LDA erg1+1 ;Borger muss in correct berücksichtigt werden
STA erg2+1 ;ansonsten erg1+1 in erg2+1 übernehmen
jmp weiter1 ;correct überspringen


correct:
SEC ;Carry setzen
LDA erg1+1 ;erg1+1 laden
SBC #$01 ;Borger aufrechnen
STA erg2+1 ;in erg2+1 speichern

weiter1:

;********** 4*C *************
CLC ;vorsichtshalber Carry löschen
LDA c ;c laden
ASL ;Linksshift
STA erg3 ;speichern in erg3
LDA erg3+1 ;erg+1 laden
ADC #$00 ;Carry berücksichtigen, in hö.Byte
STA erg3+1 ;speichern

LDA erg3 ;Das ganze nochmal
ASL
STA erg3
LDA erg3+1
ROL ;Links Rollen, wg. Carry
STA erg3+1 ;speichern

;******** 2*A-B-4*C *********
SEC
LDA erg2
SBC erg3
STA erg4
BCC correct2 ;Wieder berücksichtigen, ob
SEC ;in den niedrigwertigen Stellen
LDA erg2+1 ;ein Borger auftritt
SBC erg3+1 ;Wenn ja, dann in correct2 springen
STA erg4+1 ;ansonsten Ergebnis von 2*A-B(erg2 & erg2+1)
jmp weiter2 ;verrechnen ohne Borger


correct2:
SEC ;Mit Borger verrechnen und in erg4+1
LDA erg2+1 ;speichern
SBC erg3+1
SEC
SBC #$01
STA erg4+1

weiter2:


RTS

a:.BYTE $C2 ;Variablen definieren
b:.BYTE $C0
c:.BYTE $C0

erg1:.BYTE $00, $00
erg2:.BYTE $00, $00
erg3:.BYTE $00, $00
erg4:.BYTE $00, $00
.END

Capt'N Coax
2003-03-08, 22:57:11
Verdammich!!!
Formatierung durchgeschossen!
Kann de Eintrag aber net editen...KA warum...

Sollte mir mal das Code Tag angewöhnen...
Sah allerdings in der Vorschau ganz passabel aus...
Gucken wie dat geht...

SRY


--Ach klar, Aus versehen als Guest...Mist, ich poste den Code nochma neu.

Capt'N Coax
2003-03-08, 23:07:27
Sodala:


;2*A-B-4*C

.ORG $4000

;************ 2*A ***********

LDA a ;a in Akku laden
ASL ;Linksshift (evtl. Bereichsüberschreitung)
STA erg1 ;Niederwertiges Byte speichern in erg1
LDA erg1+1 ;Höherwertiges Byte laden
ADC #$00 ;eventuelles Carry in höherwertigem Byte
STA erg1+1 ;speichern

;*********** 2*A-B **********

SEC ;6502 spezifisch, Vor Subtraktion Carry Flag
LDA erg1 ;setzen!
SBC b ;Subtrahiere B von erg1
STA erg2 ;Speichern in erg2

BCC correct ;Carry Flag bei Sub. gelöscht, dann Borger!
LDA erg1+1 ;Borger muss in correct berücksichtigt werden
STA erg2+1 ;ansonsten erg1+1 in erg2+1 übernehmen
jmp weiter1 ;correct überspringen


correct:
SEC ;Carry setzen
LDA erg1+1 ;erg1+1 laden
SBC #$01 ;Borger aufrechnen
STA erg2+1 ;in erg2+1 speichern

weiter1:

;********** 4*C *************
CLC ;vorsichtshalber Carry löschen
LDA c ;c laden
ASL ;Linksshift
STA erg3 ;speichern in erg3
LDA erg3+1 ;erg+1 laden
ADC #$00 ;Carry berücksichtigen, in hö.Byte
STA erg3+1 ;speichern

LDA erg3 ;Das ganze nochmal
ASL
STA erg3
LDA erg3+1
ROL ;Links Rollen, wg. Carry
STA erg3+1 ;speichern

;******** 2*A-B-4*C *********
SEC
LDA erg2
SBC erg3
STA erg4
BCC correct2 ;Wieder berücksichtigen, ob
SEC ;in den niedrigwertigen Stellen
LDA erg2+1 ;ein Borger auftritt
SBC erg3+1 ;Wenn ja, dann in correct2 springen
STA erg4+1 ;ansonsten Ergebnis von 2*A-B(erg2 & erg2+1)
jmp weiter2 ;verrechnen ohne Borger


correct2:
SEC ;Mit Borger verrechnen und in erg4+1
LDA erg2+1 ;speichern
SBC erg3+1
SEC
SBC #$01
STA erg4+1

weiter2:

RTS

a:.BYTE $C2 ;Variablen definieren
b:.BYTE $C0
c:.BYTE $C0

erg1:.BYTE $00, $00
erg2:.BYTE $00, $00
erg3:.BYTE $00, $00
erg4:.BYTE $00, $00
.END

Demirug
2003-03-08, 23:26:45
einen 64er oder einen Appel II ausgegraben ?

6502 Assembler also das ist verdammt lange her :D



;2*A-B-4*C

.ORG $4000

;************ 2*A ***********

LDA a ;a in Akku laden
ASL ;Linksshift = *2
STA erg1 ;Niederwertiges Byte speichern in erg1
LDA erg1+1 ;Höherwertiges Byte laden
ROL ; *2 + Carry highbyte
STA erg1+1 ;speichern

;*********** 2*A-B **********

SEC
LDA erg1
SBC b
STA erg2
LDA erg1+1
SBC b+1
STA erg2+1 ; carry flag geht automatisch

;********** 4*C *************
CLC ;vorsichtshalber Carry löschen
LDA c ;c laden
ASL ;Linksshift = *2
STA erg3 ;speichern in erg3
LDA c+1 ;c+1 laden
ROL ;highbyte *2 + Carry
STA erg3+1 ;speichern

ASL erg3
ROL erg3+1

;******** 2*A-B-4*C *********

SEC
LDA erg2
SBC erg3
STA erg4
LDA erg2+1
SBC erg3+1
STA erg4+1 ; carry flag geht automatisch

RTS

a:.BYTE $C2 ;Variablen definieren
b:.BYTE $C0
c:.BYTE $C0

erg1:.BYTE $00, $00
erg2:.BYTE $00, $00
erg3:.BYTE $00, $00
erg4:.BYTE $00, $00
.END


Keine Gewährleistung ;)

zeckensack
2003-03-09, 00:37:49
;2*A-B-4*C

.ORG $4000

;************ 2*A ***********

LDA a ;a in Akku laden
ASL ;Linksshift (evtl. Bereichsüberschreitung)
STA erg1 ;Niederwertiges Byte speichern in erg1
LDA erg1+1 ;Höherwertiges Byte laden
ADC #$00 ;eventuelles Carry in höherwertigem Byte
STA erg1+1 ;speichern

Was das denn?
Du lädst dort eine Null, aber garantieren kannst du das nur im ersten Aufruf der Funktion. Rufst du sie später nochmal auf, kann es gut sein daß dort buchstäblich 'irgendwas' geladen wird.

... wenn du natürlich keine Null haben wolltest, sondern weitere acht Bits von 'a', dann ist die Zeile trotzdem falsch, nur dann aus anderem Grund :)

Capt'N Coax
2003-03-09, 01:01:09
@ Zeckensack(Woher kommt eigentlich DER Name?? ;) ):

In der Tat läuft das Prog nur einmal durch, dann is' finito.
Also kann bei der 1. Rechnung entweder n Übertrag auftreten oder halt nicht. Soweit ich weiss (Kann mich selbsverständlich irren) verrechnet man das Carry per ADC (Add with carry), aber da ich das Ergebnis nicht verfälschen will (Auch wenns hier nix zu verfälschen gibt...hehe), rechne ich plus $00, erg+1= 0000 0001.
In diesem speziellen Falle tuts das denke ich prima...? Oder net? oder wie? hehe

Ich könnte hier natürlich auch direkt eine 00 innen Akku laden, same effect.

@Demirug

Nee, ich hatte zwar n' 64er, er leider nie mit geproggt...DOCH! n' Textadventure, war aber mit Basic geschrieben und beschränkte sich auf so Sachen wie "Neben dir sitzt n Typ, was willste machen? h) hauen u) umtreten s) sprechen" , wobei s) n' bad Argument war ;)

Brauchs nur fürs Studium, aber auch als Einstimmung, falls ich mal bischen "inlinern" muss...

STA erg2+1 ; carry flag geht automatisch

-- Echt? Beim speichern? Ich meine nicht, müsste ich aber mal probieren... Ansonsten offenbart dein Code ein paar gar nützlich' Änderungen, ich schau mir das alles mal in Ruhe an.

Und insgesamt würdet ihr das aber auch so proggen?

Jedenfalls schonmal danke bis hierhin!

Xmas
2003-03-09, 01:07:53
32-Bit Operanden sind wirklich ein Segen...
erinnert mich daran dass ich mal auf einem 4-Bit Rechner ca. 30 Instruktionen für eine 8-Bit Addition brauchte.

Capt'N Coax
2003-03-09, 01:24:47
Woa???

HAHAHA! Da hab ich's ja noch gut getroffen...

zeckensack
2003-03-09, 01:31:41
Originally posted by Capt'N Coax
@ Zeckensack(Woher kommt eigentlich DER Name?? ;) ):

In der Tat läuft das Prog nur einmal durch, dann is' finito.
Also kann bei der 1. Rechnung entweder n Übertrag auftreten oder halt nicht. Soweit ich weiss (Kann mich selbsverständlich irren) verrechnet man das Carry per ADC (Add with carry), aber da ich das Ergebnis nicht verfälschen will (Auch wenns hier nix zu verfälschen gibt...hehe), rechne ich plus $00, erg+1= 0000 0001.
In diesem speziellen Falle tuts das denke ich prima...? Oder net? oder wie? heheNein, tust du nicht! :)
Du rechnest plus das, was gerade in erg0+1 steht. Du machst diesen Fehler auch noch an ein paar anderen Stellen im Code.

Der Assembler setzt dir nicht automatisch bei jedem Einsprung in die Funktion alle ergs auf Null zurück. Dafür mußt du selbst sorgen. Um den Vergleich mit einer Hochsprache zu ziehen, erg0 bis erg3 verhalten sich wie globale Variablen. Ergo: was auch immer dort zuletzt hineingeschrieben wurde, bleibt.

Verbesserungsvorschlag:;************ 2*A ***********

LDA a ;a in Akku laden
ASL ;Linksshift (evtl. Bereichsüberschreitung)
STA erg1 ;Niederwertiges Byte speichern in erg1
LDA 0 ;Null laden
ADC #$00 ;Carry addieren
STA erg1+1 ;in höherwertiges byte speichern

Ich weiß leider nicht, ob diese Instruktion auf 'nem 6502 gültig ist. Um eine Null zu laden kann man alternativ auch XOR oder Subtraktion verwenden.

zB auf x86 'XOR EAX,EAX' oder 'SUB EAX,EAX', wobei ein einfaches 'MOV EAX,0' auch zulässig wäre. Subtraktion scheidet in deinem Fall wahrscheinlich aus (wg der Carry-Geschichte).

Capt'N Coax
2003-03-09, 01:53:56
Achso!

Jetz versteh ich worauf du hinauswillst.

Mal schauen:

erg1+1 ist hier an dieser speziellen Stelle definitiv #$00-
Dann rechne ich konkret #$00 auf, hat sich also nichts geändert.
Bis natürlich auf das Carry, das aufgerechnet wird, also erg1+1=#$01

Du meinst in diesem Falle, das der Akku aber noch belegt ist, also quasi ADC mit einer möglichen Vorbelegung verrechnet wird.
STIMMT. Kann natürlich passieren. Fällt nur an dieser Stelle nicht auf, ist im späteren Code aber evtl. signifikant.

Ist auf jeden Fall eine bessere Lösung als meine!

THX!

Demirug
2003-03-09, 08:07:31
Originally posted by Capt'N Coax
@Demirug

Nee, ich hatte zwar n' 64er, er leider nie mit geproggt...DOCH! n' Textadventure, war aber mit Basic geschrieben und beschränkte sich auf so Sachen wie "Neben dir sitzt n Typ, was willste machen? h) hauen u) umtreten s) sprechen" , wobei s) n' bad Argument war ;)

Brauchs nur fürs Studium, aber auch als Einstimmung, falls ich mal bischen "inlinern" muss...

STA erg2+1 ; carry flag geht automatisch

-- Echt? Beim speichern? Ich meine nicht, müsste ich aber mal probieren... Ansonsten offenbart dein Code ein paar gar nützlich' Änderungen, ich schau mir das alles mal in Ruhe an.

Und insgesamt würdet ihr das aber auch so proggen?

Jedenfalls schonmal danke bis hierhin!

Nicht beim speichern. Ich meinte damit den ganzen Abschnit. Diese 7 Anweisungen sind normalerweise die schnellste Variante einen 16 Bit Subtraction durchzuführen.

Capt'N Coax
2003-03-09, 13:32:13
@Demirug

Hoi,

Bin jetz mal dazu gekommen deine Verbesserungen zu testen, funktioniert allerdings in dieser Form noch nicht, liegt aber nur daran, dass du die Highbytes von z.B. variable C benutzt, die allerdings laut (der doofen) Aufgabenstellung nicht existieren.

Die Variablen müssten also wie folgt definiert sein:

a:.BYTE $C2, $00 ;Variablen definieren
b:.BYTE $C0, $00
c:.BYTE $C0, $00


Hatte aber auch nicht geschrieben dass diese 8-Bit breit sein MÜSSEN.
Mit dieser Definition funktioniert das Programm allerdings einwandfrei. Wenn ich in der ursprünglichen Version deinerseits arbeite bekomme ich ein falsches Ergebniss, ich schätze mal auf Grund der Belegung der c+1 Stelle durch einen anderen Wert, da diese Stelle ja nicht für c reserviert worden ist.

Is natürlich nur ne Änderung meinerseits notwendig, dann funzt es wieder ;)

Demirug
2003-03-09, 13:53:16
darauf habe ich gar nicht geachtet. Aber das ist ja leicht anzupassen:


;2*A-B-4*C

.ORG $4000

;************ 2*A ***********

LDA a ;a in Akku laden
ASL ;Linksshift = *2
STA erg1 ;Niederwertiges Byte speichern in erg1
LDA #$00 ;0 laden
ROL ; *2 + Carry highbyte
STA erg1+1 ;speichern

;*********** 2*A-B **********

SEC
LDA erg1
SBC b
STA erg2
LDA erg1+1
SBC #$00
STA erg2+1 ; carry flag geht automatisch

;********** 4*C *************
CLC ;vorsichtshalber Carry löschen
LDA c ;c laden
ASL ;Linksshift = *2
STA erg3 ;speichern in erg3
LDA #$00 ;0 laden
ROL ;highbyte *2 + Carry
STA erg3+1 ;speichern

ASL erg3
ROL erg3+1

;******** 2*A-B-4*C *********

SEC
LDA erg2
SBC erg3
STA erg4
LDA erg2+1
SBC erg3+1
STA erg4+1 ; carry flag geht automatisch

RTS

a:.BYTE $C2 ;Variablen definieren
b:.BYTE $C0
c:.BYTE $C0

erg1:.BYTE $00, $00
erg2:.BYTE $00, $00
erg3:.BYTE $00, $00
erg4:.BYTE $00, $00


So müsste es eigentlich gehen

Für 6502 CPUs gibt es übrigens eine nette Seite http://www.6502.org/. Kennst du aber sicher schon.

Capt'N Coax
2003-03-09, 14:47:47
Yepp, so funktionierts. Wunderbar!

6502 Org kannte ich schon ,ja. Hab ich meine Anleitungen her.

Übrigens finde ich es Klasse, wie flott Ihr Jungs antwortet, und wie schnell ihr den Code bei der Hand habt. Das ist leider nicht üblich in anderen Foren. Gerade in Richtung Assembler.
Also n' riesengroßes DANKESEHR!

Hoffe ich bin mal irgendwann soweit, dass ich auch mal ein paar Fragen beantworten kann ;), die Kommunikation ist bis jetzt noch ein wenig einseitig...