Forum: Mikrocontroller und Digitale Elektronik Assembler Funktion absolut


von Sebastian__ (Gast)


Lesenswert?

Hallo,
ich habe im Bootloader ein paar Funktionen an absoluten Adressen.
zb.:
1
function1:
2
    nop
3
    nop
4
    ret
5
function2:
6
    nop
7
    nop
8
    ret

Diese Funktionen liegen zb. an der Adresse 0x1000 und 0x2000.

Ich habe nun in einem *.S in meiner Application die gleichen Funktinonen 
noch einmal.

Wie kann ich function1 und function2 im .S file definieren damit der 
Compiler (GCC) direkt function1 aus 0x1000 verwendet.

In meinem .S File habe ich eine Funktion die mit rcall function1 und 
function2 aufruft.
1
test:
2
    rcall function1
3
    rcall function1
4
    ret

Kann man diese Beiden Funktionen iregendwie Symbolisch definieren?

Gruß
Sebastian

von Karl H. (kbuchegg)


Lesenswert?

Letzten Endes interessiert den Assembler an einem
1
    rcall function1
die Bezeichnung 'function1' nur insofern, als er sie benutzt um in 
seinen Tabellen nachzusehen, welche Adresse sich dahinter verbirgt. Wenn 
der Prozessor den Code ausführt, dann hat er da sowieso eine Zahl 
stehen.

D.h. die Frage lautet eigentlich: muss ich hier einen symbolischen Namen 
benutzen, der sich aus dem Code heraus zu einer Zahl umsetzen lässt, 
oder kann ich selbst da auch eine Zahl benutzen.
Und die Antwort lautet: Selbstverständlich kannst du hier auch eine Zahl 
benutzen! Das ist sogar die viel grundlegendere Form
1
   rcall 0x1000
alles darüber hinausgehende, wie zb die Verwendung von symbolischen 
Namen, um eine Stelle im Code zu kennzeichnen, ist ja nur ein 'Service', 
den dir der Assembler anbietet.


Du wirst aber wahrscheinlich die Zahl nicht direkt im Code benutzen, 
sondern dir selber einen symbolischen Namen dafür definieren, zb mit den 
MItteln, die dir der Assembler dafür anbietet. Eine davon ist es, ein 
Label zu benutzen. Eine andere ist ein .equ
1
.equ function1 = 0x1000
2
3
...
4
5
  rcall function1

von Oliver (Gast)


Lesenswert?

rcall springt relativ zum Programmcounter, da wird ein rcall 0x1000 
nicht das gewünschte Ergebnis liefern. EIn call 0x1000 dagegen geht, 
wenn der Prozessor das kennt.

Oliver

von Markus W. (Firma: guloshop.de) (m-w)


Lesenswert?

Oliver schrieb:
> rcall springt relativ zum Programmcounter, da wird ein rcall 0x1000
> nicht das gewünschte Ergebnis liefern.

Sicher?
Der Assembler übersetzt normalerweise die absolute Adresse in eine 
relative. Ich habs für rcall nicht getestet, aber bei rjmp läuft das so.

Wenn an Word-Adresse 123 der Befehl
  rjmp 123
steht, dann macht der Assembler ein "rjmp -1" draus, jedenfalls was den 
Maschinencode angeht. Im Quelltext entspricht das einem
  rjmp PC

von Sebastian__ (Gast)


Lesenswert?

Hallo,
danke für eure Antworten.
1
.equ function1, 0x1000

Das war es. Manchmal sieht man den die einfachsten Sachen nicht ;).

Ich nehme rcall weil es nur ein kleiner Mega8 ist. (da muss man auch 
etwas am Speicher sparen).

Gruß
Sebastian

von Oliver (Gast)


Lesenswert?

Markus Weber schrieb:
> Sicher?
> Der Assembler übersetzt normalerweise die absolute Adresse in eine
> relative. Ich habs für rcall nicht getestet, aber bei rjmp läuft das so.

Ich hatte es getestet, weil ich mir auch nicht sicher war, ob der 
Asssembler bei direkten Adressangaben auch umrechnet. Das Ergebnis habe 
ich allerdings falsch interpretiert.
Meine Assembler-Funktion wird von einer C-Funktion aus aufgerufen.
Das hier ist der Assembler-Code:
1
#include <avr/io.h>
2
3
.global myfunc
4
myfunc:
5
6
  push  r18
7
  push  r19
8
  push  r20
9
  push  r21
10
  call 0x1000
11
  rcall 0x1000
12
  pop  r21
13
  pop  r20
14
  pop  r19
15
  pop  r18
16
  ret
17
  
18
  .org 0x100
19
function3:
20
  rcall 0x1000
21
  ret
22
  
23
  .org 0x1000
24
func:
25
ret;

Und das wird da draus:
1
00000076 <myfunc>:
2
#include <avr/io.h>
3
4
.global myfunc
5
myfunc:
6
7
  push  r18
8
      76:  2f 93         push  r18
9
  push  r19
10
      78:  3f 93         push  r19
11
  push  r20
12
      7a:  4f 93         push  r20
13
  push  r21
14
      7c:  5f 93         push  r21
15
  call 0x1000
16
      7e:  0e 94 00 08   call  0x1000  ; 0x1000 <__stack+0xba1>
17
  rcall 0x1000
18
      82:  f9 d7         rcall  .+4082     ; 0x1076 <func>
19
  pop  r21
20
      84:  5f 91         pop  r21
21
  pop  r20
22
      86:  4f 91         pop  r20
23
  pop  r19
24
      88:  3f 91         pop  r19
25
  pop  r18
26
      8a:  2f 91         pop  r18
27
  ret
28
      8c:  08 95         ret

Wie man sieht rechnet der Assembler zwar um, aber bezogen auf das 
aktuelle Segment. Der rcall-Sprung geht also nicht nach 0x1000, sondern 
nach 0x1076.

Oliver

von spess53 (Gast)


Lesenswert?

Hi

>Wie man sieht rechnet der Assembler zwar um, aber bezogen auf das
>aktuelle Segment. Der rcall-Sprung geht also nicht nach 0x1000, sondern
>nach 0x1076.

Kann er gar nicht. rcall kann keine fast 4k entfernte Ziele anspringen. 
Das Ziel von rcall muss im Bereich -2k<=PC<+2k liegen. Der Assembler 
müsste hier eine Fehlermeldung abgeben.

MfG Spess

von Oliver (Gast)


Lesenswert?

spess53 schrieb:
> Kann er gar nicht.

Doch, avr-as kann ;)
Bei 0x1001 meckert er, 0x1000 geht. Das ist das übliche Wirrwar mit 
Bytes und Words.

Oliver

von Oliver (Gast)


Lesenswert?

Oliver schrieb:
> Bei 0x1001 meckert er,

grr, Tippfehler. Ab 0x1010 meckert er.

Oliver

von Peter D. (peda)


Lesenswert?

Beim ATmega8 gibt es nur rcall/rjmp und damit läßt sich jede Adresse 
anspringen.
Der Trick ist, der Compiler springt einfach über 0x0000, sucht sich also 
selber den kürzesten Weg.
Es gibt also keinen Error.

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.