Forum: Mikrocontroller und Digitale Elektronik Assembler code 68HCS12 (CPU12)


von Eisen H. (eisenhorn)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

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.

von Hc Z. (mizch)


Lesenswert?

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.

von Eisen H. (eisenhorn)


Lesenswert?

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?

von (prx) A. K. (prx)


Lesenswert?

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.

von Hc Z. (mizch)


Lesenswert?

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.

von Eisen H. (eisenhorn)


Lesenswert?

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?

von (prx) A. K. (prx)


Lesenswert?

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.

von Hc Z. (mizch)


Lesenswert?

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).

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.