AVR Assembler relative jump

Gast #5296390
Lesenswert?

Hi,
ist es möglich, in Assembler für z.B. den ATtiny13a einen relative jump 
mit einem Wert aus einem Register auszuführen?
Bzw. was ist die schnellste Methode, also die mit der geringsten Anzahl 
benötigter Taktzyklen, um abhängig von einem Wert aus dem RAM oder einem 
Register jeweils einen anderen Code auszuführen?
Also sowas ähnlich dem Befehl
switch (var) {
    case 1:
      //do something when var equals 1, for example jumping to another 
function
      break;
    case 2:
      //when var equals 2, jump to another function
      break;
}
in C.
Ziel ist es, Code, der NICHT im Flash-Speicher des AVR-RISC-uCs ist, 
auszuführen.
Sofern das möglich ist, ohne nacheinander jeden möglichen Wert mit den 
entsprechenden Befehlen zu vergleichen, was sehr ineffizient wäre und 
sehr viel Zeit kostet, dann würde das mir einige neue Möglichkeiten 
bieten:
 - Ausführen von Code aus dem RAM: Ich könnte Code testen, ohne immer 
neu zu flashen
- Programmieren (und deutlich mehr Speicher für das Programm) durch das 
Speichern eines Hexfiles auf einer uSD-Karte. Die Firmware könnte den 
Code auf der uSD-Karte auslesen, in den RAM laden und ausführen. -> 
Programmieren ohne nötigen Programmer und:
      - die Firmware könnte ein Tool bereitstellen, das eine 
Programmierung ohne zusätzlichen Computer ermöglicht!!! Ohne eine zweite 
MCU zu brauchen, die die andere über isp flasht.

Noch eine zweite Frage:
Wie greift man in Assembler (ich nutze avra auf einem Linux-Desktop-PC 
zum Assemblieren im Terminal und avrdude, kompatibel mit 
Atmel-/AVR-Studio) auf den RAM zu?
Ich meine damit nicht, einer Variable einen Wert zuzuordnen, sondern an 
einer festen Adresse ein Byte zu speichern. War das nicht irgendwie so, 
dass nach dem SREG usw. ab 0x60 oder so einfach der RAM losging?

Danke für eure Hilfe schonmal jetzt von mir.
Ich habe vor, AVRs in richtige Computer zu verwandeln. Sie haben zwar 
wenig Leistung, sind aber sparsam in Sachen Energieverbrauch. Ich 
überlege sogar, das Prinzip von BIOS, Bootloader (Bootstrapping) und 
Kernel auf AVRs anzuwenden (ungeachtet des Boot-ROM und dessen, dass 
Code normalerweise aus dem RAM ausgeführt wird)
So könnte jeder, der gerne mal ein Betriebssystem schreiben würde, klein 
anfangen, da x86 Assembler ja ganz schön komplex ist. Vielleicht auch 
ein C-Compiler onboard?

Das würde ich dann auf Github veröffentlichen ;)
Thanks!
Gast #5296398
Lesenswert?

Auch wichtig:
was haltet ihr davon?
Hätte jemand Interesse, egal ob in C oder Assembler mit mir zusammen 
daran zu arbeiten?
Assembler wäre v.a. bei den zeitkritischen Stellen wichtig (vielleicht 
als inline-assembler?)

Was auch cool wäre, wäre ein leichtes Programmieren von GUIs (graphic 
user interface)

Die Ein-/Ausgabe könnte sowohl mit Tastern/LEDs -> ähnlich TPS 
(tastenprogrammierbare Steuerung) als auch über ein serielles Signal (-> 
PC) oder über einen weiteren Mikrocontroller, der als GPU fungiert, an 
ein SPI/i2c Display-Modul sein. An dieser Stelle wäre auch eine 
Implementation von "Treibern" cool
So könnte man auch EEPROM ICs über Treiber andprechen / von denen 
booten, Multiboot, externer RAM -> erweitern,.......
Ihr seht schon, ich bin da sehr kreativ, aber vor allem auch offen für 
Vorschläge anderer (außer solche wie "Lass den Quatsch doch einfach. Was 
bringt's dir denn?! Zweckentfremdhng einer MCU und Zeitverschwendung..."
Gast #5296434
Lesenswert?

Hmmm schrieb:
> Pascal schrieb:
>> Ziel ist es, Code, der NICHT im Flash-Speicher des AVR-RISC-uCs ist,
>> auszuführen.
>
> Genau daran scheitert Deine Idee.

Das denke ich nicht. Der Flashspeicher bekommt eine Firmware, die dann 
vergleichbar mit einer Virtual Machine ein OS auf einem OS laufen lässt. 
Ein Code, der zur Firmware gehört, ist erforderlich, um die Befehle zu 
laden und auszuführen. Die Zeitverluste sind je nach Antwort auf die 
Frage entweder tolierierbar oder eben etwas schlechter.
Gast #5296436
Lesenswert?

Dann ist das aber keine Codeausführung aus dem RAM mehr, sondern die 
Emulation einer kompletten CPU mit allen damit verbundenen Nachteilen, 
und das auf einem ATtiny13A?

Das Ziel, AVR-Code schnell testen zu können, erreichst Du schneller und 
besser mit einem Bootloader oder einem PC-basierten Simulator.
Gast #5296440
Lesenswert?

Hmmm schrieb:
> die Emulation einer kompletten CPU mit allen damit verbundenen
> Nachteilen, und das auf einem ATtiny13A?

Naja, genau genommen die Emulation eines ATtiny13a der Code aus dem RAM 
ausführt auf einem ATtiny13a der Code aus dem Flash ausführt. Vielmehr 
ist es allgemein für AVRs gedacht, war nur ein Beispiel, der kleine 
Flashspeicher könnte mit einer mikroSD Karte von 1KB auf 32GB erweitert 
werden, und eine Programmierung ohne PC ohne die Opcodes auswendig zu 
lernen wäre möglich, wobei der Code im Flash (Firmware) sich nicht 
ändert
Gast #5296457
Lesenswert?

Pascal schrieb:

> Naja, genau genommen die Emulation eines ATtiny13a der Code aus dem RAM
> ausführt auf einem ATtiny13a der Code aus dem Flash ausführt.

Und genau deshalb wirst du scheitern. Man braucht sich einfach nur die 
Größen von RAM und Flash anzuschauen. Der RAM ist immer deutlich 
kleiner.

Außerdem wird die Emulation immer ganz erheblich langsamer sein als die 
Ausführung von Code aus dem Flash. RAM lesen ist teuer, zwei Takte pro 
Byte und das zusätzlich zur eigentlichen Arbeit der Instruktion. Zum 
Vergleich: bei der Ausführung aus dem Flash werden die Befehlsworte 
parallel zu ihrer Ausführung gelesen und zwar ein Wort (also zwei Bytes) 
pro Takt. Allein nur das Lesen der Instruktionen wird also vier mal 
langsamer erfolgen.

> Vielmehr
> ist es allgemein für AVRs gedacht, war nur ein Beispiel, der kleine
> Flashspeicher könnte mit einer mikroSD Karte von 1KB auf 32GB erweitert
> werden

Damit könnte man zwar die Begrenzung der RAM-Größe umgehen. Der dazu 
nötige Layer für virtuellen Codespace würde aber die Sache nochmals 
erheblich weiter ausbremsen und vor allem auch die Laufzeiten des Codes 
völlig irregulär machen. Adé Echtzeit...

> und eine Programmierung ohne PC ohne die Opcodes auswendig zu
> lernen wäre möglich, wobei der Code im Flash (Firmware) sich nicht
> ändert

Du willst also nicht wirklich eine Emulation, sondern schlicht nur eine 
Interpretersprache realisieren. Das haben schon mehrere Leute gemacht. 
Mindestens ein solches Projekt findest du im Forum "Projekte und Code". 
Da ging es um einen Basic-Interpreter.
Gast #5296463
Lesenswert?

> Mindestens ein solches Projekt findest du im Forum "Projekte und Code".
> Da ging es um einen Basic-Interpreter.

Er könnte ja einen p-code Interpreter schreiben. Wenn UCSD-Pascal auf 
dem AVR läuft dann kauf ich mir auch mal wieder einen um die coole 
Nostalgie der 80er in Turbospeed zu geniessen. :-)

Ansonsten würde ich sagen, wenn man so etwas will dann ganz bestimmt 
nicht auf einem AVR. Da nimmt man einen Controller der viel internen Ram 
hat und auch noch die Faehigkeit Code darin ablaufen zu lassen. In allen 
anderen Faellen begnuegt man sich mit einem guten Debugger...

Olaf
Gast #5296467
Lesenswert?

Pascal schrieb:
> Auch wichtig:
> was haltet ihr davon?

Super umständlich, wenn's auch viel einfacher ginge! Es gibt Controller 
die Code direkt aus dem RAM ausführen können, wie MSP430 und ARM. Da 
gibt's auch sehr Energie Sparende (zB EFM32) und günstige (zB STM32F0). 
Insbesondere ARM ist sogar dafür/ausgelegt/, dass man dafür 
Betriebssysteme  schreibt, denn es unterstützt unprivilegierte Modi, 
Speicherschutz, und effiziente Kontextwechsel. Also ausgerechnet AVR 
dafür zu nehmen ist nur unnötige Arbeit mit zwangsweise mäßig gutem 
Ergebnis. Relative indirekte Sprünge sehen IIRC bei ARM z.B. so aus:
add pc, r0
Es gibt sogar auch eine Anweisung welche Sprungtabellen direkt 
unterstützt. Viel einfacher als beim AVR... ;-)
#5296572
Lesenswert?

Pascal schrieb:
> ist es möglich, in Assembler für z.B. den ATtiny13a einen relative jump
> mit einem Wert aus einem Register auszuführen?

Du addierst den PC dazu und machst einen IJMP.

Pascal schrieb:
> Ziel ist es, Code, der NICHT im Flash-Speicher des AVR-RISC-uCs ist,
> auszuführen.

Also einen Interpreter + SD-Reader in nur 512 Worten, das ist sportlich.
Ein ATmega2560 dürfte geeigneter sein.

Pascal schrieb:
> Ohne eine zweite
> MCU zu brauchen, die die andere über isp flasht.

Das dürfte erheblich schneller sein, als ein schnarchlahmer Interpreter.
Du brauchst auch keinen 2. AVR, der AVR kann sich selber programmieren 
(SPM-Befehl).
(Firma: RUB) #5296600
Lesenswert?

Peter D. schrieb:
> Ein ATmega2560 dürfte geeigneter sein.
Oder ein ATMega1284. Hat zwar weniger Flash als der 2560 (128k statt 
256k), aber dafuer mehr RAM, 16k statt 8k. Und es gibt ihn im 
DIP-Gehaeuse. Und er kann bis 20MHz :)
EEPROM haben beide 4k.

Der TO sollte sich aber auch ueberlegen, was er alles an Peripherie 
braucht:
- Anzahl der Timer
- Anzahl der Schnittstellen nach aussen (U(S)ART/I2C/SPI)

Waere ja doof wenn er Anfaengt, und dann irgendwann feststellt das sein 
uC nicht genug Timer, etc. hat.
Gast #5296685
Lesenswert?

Mit Tiny13? Illusorisch. Ein Mega128 sollte es da mindestens sein. 
Maschinencode aus dem SRAM auszuführen ist aber auch dort unmöglich. 
Eine Interpretersprache schon viel eher. Die Programme kann man gleich 
auf der angeschlossenen SD Karte belassen. Ich hab sowas mal mit einem 
Z80 gemacht. Programme befanden sich da noch auf einem EEPROM. Mehrere 
davon konnten gleichzeitig abgearbeitet werden- so ein Multitasking ist 
nicht allzu schwer zu realisieren.

Kaj G. schrieb:
> Da faellt mir ein:
> Linux on an 8-bit micro

Krass. Krass kastriert. Ein OS belastet auf 8er MCs mehr als daß es 
nützt.
#5296697
Lesenswert?

Pascal schrieb:
> Ich meine damit nicht, einer Variable einen Wert zuzuordnen, sondern an
> einer festen Adresse ein Byte zu speichern. War das nicht irgendwie so,
> dass nach dem SREG usw. ab 0x60 oder so einfach der RAM losging?

Hi,
hab's gerade ausprobiert.
Meistens arbeitet man aber mit Predecrement oder Postincrement.
(Das Listing wird sonst sehr schnell unübersichtlich.)

Stichwort für ATMEL Doku: Indirect addressing (ist nicht ganz so 
trivial, wie es zunächst den Anschein hat.)

ciao
gustav
Angehängte Dateien:
Gast #5296702
Lesenswert?

Pascal schrieb:
> Noch eine zweite Frage:
> Wie greift man in Assembler ... auf den RAM zu?
> Ich meine damit nicht, einer Variable einen Wert zuzuordnen, sondern an
> einer festen Adresse ein Byte zu speichern.

Naja easy mit lds/sts oder indexiert mit ST/STD.

c-hater schrieb:
> Damit (SD Card Erweiterung) könnte man zwar die Begrenzung der RAM-Größe 
umgehen. Der dazu
> nötige Layer für virtuellen Codespace würde aber die Sache nochmals
> erheblich weiter ausbremsen und vor allem auch die Laufzeiten des Codes
> völlig irregulär machen.

Das ist auch total relativ. Für sehr vieles ist das immer noch mehr als 
schnell genug.
#5296711
Lesenswert?

Karl B. schrieb:
> Stichwort für ATMEL Doku: Indirect addressing (ist nicht ganz so
> trivial, wie es zunächst den Anschein hat.)

Hi,
noch der Link:

http://web.csulb.edu/~hill/ee346/Lectures/13-1%20AVR%20Addressing%20Indirect.pdf

Seite 15 ist interessant.

"...Each table entry (.DB) contains one byte.
If we look at the first table entry we  see 0b00111111
which corresponds to 3f in hexadecimal.
Comparing this with the corresponding address and data fields
on the left... Wait a minute - where did 06 come from?..."

ciao
gustav
#5296791
Lesenswert?

G.M. schrieb:
> Das ist auch total relativ. Für sehr vieles ist das immer noch mehr als
> schnell genug.

Aus:

Kaj G. schrieb:
> Linux on an 8-bit micro
> http://dmitry.gr/index.php?r=05.Projects&proj=07.%...

„It takes about 2 hours to boot to bash prompt ("init=/bin/bash" kernel 
command line). Then 4 more hours to boot up the entire Ubuntu ("exec 
init" and then login)... Curiously enough, once booted, the system is 
somewhat usable. You can type a command and get a reply within a minute“

Relativ ist wirklich total relativ...

Oliver
Gast #5296915
Lesenswert?

Oliver S. schrieb:
> Kaj G. schrieb:
> Linux..
> Relativ ist wirklich total relativ...

Meine Bemerkung bezog sich nicht auf diese Linux Installation sondern 
darauf, daß ein AVR für sehr viele Anwendungsfälle auch dann noch 
schnell genug ist, wenn er ein Interpretersprach-Programm fortlaufend 
von einer SD Karte bezieht. Dieses Linux auf einem AVR ist 
allerhöchstens eine Machbarkeitsstudie, fern jeder sinnvollen Anwendung.
#5297041
Lesenswert?

Auf die Schnelle habe ich im "Instruction Set Manual" zwei Befehle 
gefunden.
IJMP
und
ICALL

Diese Hüpfen abhängig von Inhalt eines Registers. Kein Problem, dies aus 
einer Tabelle zu laden, irgendwie zu "berechnen" oder mittels Random 
vorzugeben;-)

Habe aber keine Lust, mir den Befehlssatz des ATtiny13a reinzuziehen. 
Möglicherweise wird dieser Befehl ja nicht unterstützt.
Persönliche Seite #5297123
Lesenswert?

Sebastian S. schrieb:
> IJMP

Das ist zwar ein indirekter Sprung, allerdings ein absoluter und kein 
relativer wie vom TO gewünscht, d.h. der Sprung ist nicht PC-relativ. 
(Wobei der TO nicht wirklich zu wissen scheint was er will oder braucht, 
und auch nicht zwischen ausgeführtem und interpretiertem Code zu 
unterscheiden weiß).

Eine weiter Möglichkeit für einen indirekten Sprung ist

PUSH
PUSH
RET

was aber auch eine absolute Adresse erfordert.  Je nach 
Registerverwendung kann es allerdings günstiger sein, da man nicht ans 
Z-Register gebunden ist wie bei IJMP.
Gast #5297267
Lesenswert?

georg schrieb:

> Fast alle Prozessoren haben so einen Befehl. I.A. braucht man dazu eine
> Tabelle, z.B. aus Sprungbefehlen, und das Register liefert den Index für
> die Tabelle.

Beim AVR8 hat man tatsächlich Instruktionen, die Indirektion für Sprünge 
und Unterprogrammaufrufe auch ohne den realtiv teuren Umweg über den RAM 
hinbekommen. Geile Architektur (in ihrer Klasse).

Naja, der Fairness halber sollte man zumindest erwähnen, dass bei 
anderen Archtekturen der Umweg über den RAM, relativ gesehen, nicht ganz 
so teuer ist. Die sind einfach immer nur Scheisse-langsam. Auch wieder: 
relativ gesehen...
Persönliche Seite #5297350
Lesenswert?

Vermutlich meint der TO einfach eine Sprungtabelle.  Im einfachsten Fall 
erzeugt avr-gcc dafür folgenden Code, wobei die Tabelle für Werte von 
R24/25 = 1...9 verwendet wird:
1
  ;; R24/25 = 16-Bit Index
2
  movw r30,r24
3
  ;; Index in [1..9] ?
4
  sbiw r30,1
5
  cpi r30,9
6
  cpc r31,__zero_reg__
7
  ;; Falls nicht, die Sprungtabelle NICHT verwenden
8
  brsh .Ldefault
9
  ;; Word-Adresse der Tabbelle zum Index hinzuaddieren...
10
  subi r30,lo8(-(gs(.LTable)))
11
  sbci r31,hi8(-(gs(.LTable)))
12
  ;; ...und springen
13
  ijmp
14
.pushsection .jumptables.gcc,"ax",@progbits
15
.p2align 1
16
.LTable:
17
  rjmp .L1
18
  rjmp .L2
19
  rjmp .L3
20
  rjmp .L4
21
  rjmp .L5
22
  rjmp .L6
23
  rjmp .L7
24
  rjmp .L8
25
  rjmp .L9
26
.popsection
27
.L1:
28
  ;; Code fuer case 1:
29
.L2:
30
  ;; Code fuer case 2:
31
...
Falls die Indices nicht in [1..9] sind sondern in [0..8], dann entfällt 
das "SBIW 1".

Natürlich kann man auch die Labels anstatt die RJMPs in die Tabelle 
schreiben, was dann etwas anderen Code ergibt und z.B. dann erforderlich 
ist, wenn nicht alle Labels per RJMP erreichbar sind, hier für 16-Bit 
Index in X und ohne vorherige Bereichsprüfung:
1
  ;; X += WordAddr (.LTable)
2
  subi XL,lo8(-(gs(.LTable)))
3
  sbci XH,hi8(-(gs(.LTable)))
4
  ;; X *= 2
5
  rol XL
6
  lsl XH
7
  ;; Z = *X++
8
  ld ZL, X+
9
  ld ZH, X+
10
  ;; PC = Z
11
  ijmp
12
.pushsection .data.gcc,"a",@progbits
13
.LTable:
14
  .word gs(.L0)
15
  .word gs(.L1)
16
  ...
17
.popsection
18
.L0:
19
  ;; Code fuer case 0:
20
...
Gast #5298023
Lesenswert?

Idee war es, von bspw. der SD-Karte oder dem RAM einen Wert in ein 
Register zu laden, der bestimmt, wie weit gesprungen wird.

Warum?

Um den Code, der nicht im Flash ist, schneller auszuführen

1. Code (Befehl enthaltend) laden
2. Sprung abhängig vom Code durchführen
3. Code (Daten enthaltend) nachladen
4. Code ausführen
#5298116
Lesenswert?

c-hater schrieb:
> Beim AVR8 hat man tatsächlich Instruktionen, die Indirektion für Sprünge
> und Unterprogrammaufrufe auch ohne den realtiv teuren Umweg über den RAM
> hinbekommen. Geile Architektur (in ihrer Klasse).

Sowas ist doch selbstverständlich. Schon der alte 8051 von 1980 konnte 
mit "JMP @A+DPTR" und "MOVC A, @A+DPTR" bequem Sprungtabellen und 
Datentabellen adressieren.
Ich hab mich immer gewundert, warum manche hinter einen MC noch 
7-Segment Dekoder gesetzt haben. Die 10 Byte Tabelle kostet doch nix.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren