Hallo,
Vielleicht könnte mir jemand bei folgenden Problem helfen. Ich habe eine
kleine Beispiel Routine in C für den HCS12 in Assembler übersetzt und
würde gerne den Assembler code nachvollziehen.
C Listing:
------------------------------------------
int sum(int len , int arr [])
{
int i;
int sum = 0;
for (i = 0; i < len ; i++) {
sum += arr[i];
}
return sum;
}
-------------------------------------------
ASM Listing:
--------------------------------------------
_sum:
pshd <---hier speichert er den akku D auf den stack
leas -4,s <--- hier müsste er 4 bytes für die variablen
reservieren? (also den RÜckgabewert, len, und den array pointer=)
OFST: set 4 <--- Mir ist nicht ganz klar warum er den
Offset auf 4 stellt. s müsste ja die adresse vom stackpointer sein, und
der wächst doch nach unten (gegen kleinere adresse). Nur wenn offset 4
ist dann habe ich doch teils positive offsets?
.dcall "8,2,_sum"
clra
clrb
std OFST-2,s
clra
clrb
std OFST-4,s
bra L7
L3:
ldy OFST+4,s
ldd OFST-4,s
lsld
ldd d,y
addd OFST-2,s
std OFST-2,s
ldy OFST-4,s
iny
sty OFST-4,s
L7:
ldd OFST-4,s
cpd OFST+0,s
blt L3
ldd OFST-2,s
leas 6,s
rts
xdef _sum
end
-------------------------------------------------
LG
Mario Grotschar schrieb:> pshd <---hier speichert er den akku D auf den stack> leas -4,s <--- hier müsste er 4 bytes für die variablen
An dieser Stelle:
S[0..3] = lokale Variablen
S[4..5] = D (len)
S[6..7] = return
S[8..9] = arr
Offenbar wird der erste Parameter in D übergeben, der Rest auf dem
Stack. Negativ zu OFST sind so die lokalen Daten, positiv die Parameter.
Mario Grotschar schrieb:> pshd <---hier speichert er den akku D auf den stack
Das ist offensichtlich len. Es befindet sich später unter OFST+0,s.
> leas -4,s <--- hier müsste er 4 bytes für die variablen> reservieren? (also den RÜckgabewert, len, und den array pointer=)
Ja. Es sind zwei Variable: sum (später unter OFST-2,s) und i (später
unter OFST-4,s). Der Rückgabewert ist nicht dabei, denn der wird
offensichtlich beim Ausstieg über D übergeben.
> OFST: set 4 <--- Mir ist nicht ganz klar warum er den> Offset auf 4 stellt. s müsste ja die adresse vom stackpointer sein, und> der wächst doch nach unten (gegen kleinere adresse). Nur wenn offset 4> ist dann habe ich doch teils positive offsets?
Die Stackpointer-Arithmetik (OFST-x,s) hat nichts damit zu tun, wohin
der Stackpointer wächst. sum und i haben negative Werte gegenüber
OFST+0,s. len ist bei OFST+0, s. Darüber liegt die Rücksprungadresse
(OFST+2,s) und dann kommt die Adresse von arr (bei OFST+4,s), die vor
dem Aufruf aufs Stack gepusht wurde.
Vielen Danlk für die schnelle Antwort. Eine Frage hätte ich noch.
Wie macht er hier ein
L3:
ldy OFST+4,s <-- in Y register stack pointer laden
ldd OFST-4,s <-- var i in den akku D laden.
lsld <-- ?
ldd d,y <-- arr[i] in akku D laden
lsld ist kommt doch einer division durhc 2 gleich?
Mario Grotschar schrieb:> lsld ist kommt doch einer division durhc 2 gleich?
Fast richtig. Nur an der Richtung musst du noch arbeiten. Links ist da
wo der Daumen rechts ist, wie man gern zu sagen pflegt.
Mario Grotschar schrieb:> Wie macht er hier ein> L3:> ldy OFST+4,s <-- in Y register stack pointer laden
Nein. Er lädt Y aus OFST+4,s. Welche Variable sich dort befindet, habe
ich bereits geschrieben und andere auch (arr).
> ldd OFST-4,s <-- var i in den akku D laden.> lsld <-- ?> ldd d,y <-- arr[i] in akku D laden>> lsld ist kommt doch einer division durhc 2 gleich?
Nein. 1 links schieben ist eine Verdoppelung. Da jedes Element in arr
2 Bytes belegt, muss i verdoppelt werden und dann an diesem Offset vom
Arraybeginn (ldd d,y) abgeholt werden.
Vielen Dank. Bin schon etwas eingerostet :-).
Noch eine weitere Frage. Der CPU12 bietet ja folgende daten typen:
2.3 Data Types
The CPU12 uses these types of data:
• Bits
• 5-bit signed integers
• 8-bit signed and unsigned integers
• 8-bit, 2-digit binary-coded decimal numbers
• 9-bit signed integers
• 16-bit signed and unsigned integers
• 16-bit effective addresses
• 32-bit signed and unsigned integers
Negative integers are represented in two’s complement form.
Five-bit and 9-bit signed integers are used only as offsets for indexed
addressing modes.
Sixteen-bit effective addresses are formed during addressing mode
computations.
Thirty-two-bit integer dividends are used by extended division
instructions. Extended multiply and
extended multiply-and-accumulate instructions produce 32-bit products.
Meine Frage ist warum reserviert der compiler hier genau ein word fürs
int anstatt nur jeweils ein byte? Gibt es dafür einen Grund oder
reserviert er "vorsorglich" mehr?
Mario Grotschar schrieb:> Meine Frage ist warum reserviert der compiler hier genau ein word fürs> int anstatt nur jeweils ein byte? Gibt es dafür einen Grund oder> reserviert er "vorsorglich" mehr?
Compiler sind dumm. Sie tun genau das was man ihnen sagt. Wenn man mit
ihnen höflich und korrekt umgeht, dann tun sie das auch ohne
Widerspruch. Ganz egal ob das sinnvoll ist oder nicht.
Da hast ihm gesagt hast, er solle für die Variablen "int" nehmen. Der
Herr C hat ihm gesagt, er sollte so tun als ob alle Rechnungen
mindestens als "int" abzulaufen haben. Und hat auch gesagt, dass "int"
Daten mindestens 16 Bits haben müssen.
Mario Grotschar schrieb:> Meine Frage ist warum reserviert der compiler hier genau ein word fürs> int anstatt nur jeweils ein byte? Gibt es dafür einen Grund oder> reserviert er "vorsorglich" mehr?
Nein, er reserviert nicht vorsorglich mehr. Nach C-Standard hat eine
int mindestens 16 Bits zu haben, siehe auch die Antwort meines
Vorgängers.
Wenn Du eine 8-bit-int brauchst, sieh mal in <stdint.h> nach und nimm
uint8_t bzw. int8_t (chars tuns meistens auch, haben aber nicht
garantiert 8 Bits).