Gibt es irgendwo ein Repositorium, wo man ältere gnu-arm-tools finden
kann? Ich muß eine ältere Programmierumgebung (Windows) mit dem
vergleichen, was ich davon jetzt nach Unix (macOS) portiert habe. Beim
Vergleich der Kompilate (Assembler Listing) stelle ich fest, daß der
generierte Code ab einer bestimmten Stelle auseinanderläuft.
Der ältere Assmbler ist:
1
GNU assembler (GNU Tools for ARM Embedded Processors) 2.24.0.20150304
2
Copyright 2013 Free Software Foundation, Inc.
3
This program is free software; you may redistribute it under the terms of
4
the GNU General Public License version 3 or later.
5
This program has absolutely no warranty.
6
This assembler was configured for a target of `arm-none-eabi'.
Der neuere:
1
GNU assembler (GNU Tools for Arm Embedded Processors 8-2018-q4-major) 2.31.51.20181213
2
Copyright (C) 2018 Free Software Foundation, Inc.
3
This program is free software; you may redistribute it under the terms of
4
the GNU General Public License version 3 or later.
5
This program has absolutely no warranty.
6
This assembler was configured for a target of `arm-none-eabi'.
Alte Binutils selbst compilieren?
Muss es denn unbedingt die Windows-Version sein, oder ist nur die genaue
Assemblerversion wichtig? Ansonsten würde ich das an deiner Stelle unter
FreeBSD oder Linux machen.
Jörg W. schrieb:> Alte Binutils selbst compilieren?>
Wäre die letzte Möglichkeit. Vielleicht auch der Weg, den ich letztliich
gehen muß.
> Muss es denn unbedingt die Windows-Version sein, oder ist nur die genaue> Assemblerversion wichtig? Ansonsten würde ich das an deiner Stelle unter> FreeBSD oder Linux machen.
Ich will ja von der Windows-Version runter. D.h., das ist die Referenz,
die ich unangetastet lasse. Jetzt ziehe ich mit den Sourcen um und
kompiliere gerade, um anschließend das generierte Binary mit dem Windows
Binary zu vergleichen, bevor ich auf .elf umstelle.
Aber beim Vergleich stelle ich Abweichungen fest, die ich natürlich
vermeiden will, einfach um erst mal formal sicherzustellen, daß ich in
der Lage bin, ein exaktes Abbild des Zielsystems auch außerhalb der
ursprünglichen Entwicklungsumgebung generieren zu können.
Naja, die Binutils bauen auf heutigen Maschinen in ein paar Minuten.
Setz den --prefix beim ./configure so, dass das Resultat dann außerhalb
der normalen Verzeichnisse liegt, damit hast du dann Assembler und
Linker auf exakt dem Stand, der seinerzeit auf Windows benutzt worden
ist.
Jörg W. schrieb:> Naja, die Binutils bauen auf heutigen Maschinen in ein paar Minuten.> Setz den --prefix beim ./configure so, dass das Resultat dann außerhalb> der normalen Verzeichnisse liegt, damit hast du dann Assembler und> Linker auf exakt dem Stand, der seinerzeit auf Windows benutzt worden> ist.
Werde mal einen Versuch unternehmen...
Christoph K. schrieb:> um anschließend das generierte Binary mit dem Windows> Binary zu vergleichen, bevor ich auf .elf umstelle.
Hä?
Also sowohl der GCC als auch der Keil erzeugen zu allererst ein ELF File
(egal wie die konkrete Endung auch sein mag) und man muß daraus mit
FromElf oder dem GCC-Pendant dazu das .bin oder .hex oder .s19 erzeugen.
So herum geht das.
W.S.
W.S. schrieb:> Also sowohl der GCC als auch der Keil erzeugen zu allererst ein ELF File
Erstens hat er gar keinen C-Compiler, zweitens hast du im Prinzip Recht:
der Linker wirft ein ELF-File raus.
Aber: Chris will einen existierenden, bislang unter Windows arbeitenden
Flow, der am Ende ein Hexfile erzeugt hat, durch einen auf einem
aktuellen Unix ersetzen mit aktuellen Tools, der es am Ende bei einem
ELF-File belassen soll (das Hexfile braucht keiner). Er will aber dabei
sicherstellen, dass bei der Transformation tatsächlich auch das gleiche
Resultat entsteht wie dazumals unter der Windows-Toolchain.
W.S. schrieb:> Christoph K. schrieb:>> um anschließend das generierte Binary mit dem Windows>> Binary zu vergleichen, bevor ich auf .elf umstelle.>> Hä?> Also sowohl der GCC als auch der Keil erzeugen zu allererst ein ELF File> (egal wie die konkrete Endung auch sein mag) und man muß daraus mit> FromElf oder dem GCC-Pendant dazu das .bin oder .hex oder .s19 erzeugen.>> So herum geht das.>> W.S.
Das ist zwar richtig, daß das erste Zwischenprodukt ein .elf file ist,
aber die Situation - und das kannst Du nicht wissen - ist die, daß der
Build-Prozeß unter Windows bei dem System, das ich so vorgefunden habe,
so ist, daß ein absolutes Binary erzeugt wird und diesem Binary per
Script (Clisp), gewonnen aus der Symbol-Tabelle, noch ein weiterer
binärer Block von Pseudo-Code (Threaded Code tokens) angehängt wird. Um
diese Codes zu kennen, muß zuerst das Compilat erzeugt werden (kernel).
Ja, das klingt umständlich und blöd und getrickst, aber es ist halt so.
User schrieb:> Du könntest hier schauen ob der da dabei ist:> https://launchpad.net/gcc-arm-embedded/+series
Das sieht auf den ersten Blick ganz gut aus. Habe mal eine Version aus
2014 installiert, die aber noch nicht den gleichen Code erzeugt - wir
reden hier von Assembler und nicht C. Da sollte man meinen Assembler,
der Programmierer selbst codiert hat, sollte immer den gleichen
Binärcode erzeugen.
Ich poste mal die Stelle, wo es das erste mal auseinanderläuft.
(siehe Screenshot aus einem Beyond-Compare Vergleich).
Vielleicht sieht jemand daran, was der Assembler hier "meint", gegenüber
seinem 2.24-"Kollegen" anders machen zu müssen.
Vielleicht gibt es ja einen Schalter, der gewisse Optimierungen steuert?
Habe mich jetzt an die Version herangetastet:
GNU assembler (GNU Tools for ARM Embedded Processors) 2.24.0.20150604
Copyright 2013 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms
of
the GNU General Public License version 3 or later.
This program has absolutely no warranty.
This assembler was configured for a target of `arm-none-eabi'.
Die erste Differenz zum Original ist weg. Aber weiter im File gibt es
weitere Unterschiede.
Ich weiß nicht, ob ich überhaupt zu einer Übereinstimmung kommen kann.
Diesmal sind es branches, die anders assembliert werden.
> Vielleicht sieht jemand daran, was der Assembler hier "meint",> gegenüber seinem 2.24-"Kollegen" anders machen zu müssen.
Anscheinend passiert das hier: LDR R0, = ACRCONF kann als MOV R0,
#ACRCONF übersetzt werden -- falls die Konstante klein genug ist.
Ansonsten braucht man ein LDR mit der Konstanten im Pool. Leider
unterscheiden sich die Assembler-Versionen an der Stelle nicht
(zumindest offiziell):
https://sourceware.org/binutils/docs-2.24/as/ARM-Opcodes.html#ARM-Opcodeshttps://sourceware.org/binutils/docs-2.31/as/ARM-Opcodes.html#ARM-Opcodes
Allerdings muss ein LDR auch dann erzeugt werden, wenn die CPU den
MOV-Befehl nicht kennt. Der neuere Assembler unterscheidet sicher mehr
Varianten, vielleicht kann man mit -march, -mcpu, -mtune, -mcompat? o.ä.
etwas erreichen.
Noch eine Quelle für alte Quellen:
ftp://sourceware.org/pub/binutils/snapshots/
Habe jetzt die passende Version gefunden, die exakt den gleichen Code
erzeugt.
Nur die Darstellung der Symbole am Ende des Listings (long in der
Unix-Version vs. Word unter Windows). Wahrscheinlich liegt es an der
Plattform.
Das Windows-Binary des toolchain-as ist eine 32-bit App, die neue
Plattform ist 64bit. Aber praktisch habe ich Identität im Binary
erzielt.
Danke allen für die Mithilfe.
Grüße und ein schönes Wochenende
Christoph
Christoph K. schrieb:> Das Windows-Binary des toolchain-as ist eine 32-bit App, die neue> Plattform ist 64bit.
Ja, die 64er zeigt die Zahlen länger an.
Noch ein Gedanke zum weiteren Vorgehen, jetzt, nachdem ich 1:1
Übereinstimmung gewährleistet habe:
Die Erzeugung des Target-Binaries geschieht ja in der Weise, daß
zunächst ein Kernel gebaut wird:
und anschließend, mit Hilfe der Symboltabelle ein weiteres Kompilat aus
High-Level FORTH Worten hinten angehängt wird auf eine geraden Adresse
beginnend. Das erzeugte image.bin wird dann geflasht.
Wenn ich das nun mittels gdb und openOCD debuggen wollte (.elf), müßte
ich den Prozeß derart ändern, daß ich einmal die Symboltabelle erstelle,
das FORTH Kompilat baue und dieses binäre Paket in den ld-Schritt
einbaue - weiß im Moment nicht, wie ein man ein raw-binary dazulinken
kann. Könnte es höchstens wieder in die Source als Datenworte einbauen
und in einem zweiten Schritt noch mal assemblieren.
Anderer Gedanke ist jetzt der:
Das raw-Binary komplett mit st-flash erase, st-flash write in das Target
zu laden und dem openOCD/gdb zu sagen, er solle nicht flashen.
Dann könnte ich das .elf-Image zum Debuggen benutzen, denn das
entspricht ja dem geladenen Binärcode.
Meinungen dazu? Wie muß ich openOCD/gdb konfigurieren, daß es nicht
flasht?
Christoph K. schrieb:> Meinungen dazu? Wie muß ich openOCD/gdb konfigurieren, daß es nicht> flasht?
OpenOCD flasht erstmal nichts von sich aus. Es ist nur ein GDB-Server
(ok, und ein Telnet-Server), der macht, was du ihm sagst. Solange du ihm
also nicht sagst, er solle was flashen, tut er das nicht.
OpenOCD kann direkt (also über das telnet-Interface oder auch gleich
über die Kommandozeile) flashen, da brauchst du nicht unbedingt noch die
ST-Software, oder aber es kann natürlich auch vom GDB aus flashen.
>
Aus einem (verschieblichen) .o ein .bin zu extrahieren, erscheint mir,
nun, sehr seltsam.
> und anschließend, mit Hilfe der Symboltabelle ein weiteres Kompilat aus> High-Level FORTH Worten hinten angehängt wird auf eine geraden Adresse> beginnend. Das erzeugte image.bin wird dann geflasht.
Wie erfolgt die Einbindung in den Kernel? Vermutlich wird doch da die
Adresse einer Liste irgendwo eingetragen, ab der er die FORTH-Worte dann
sucht, oder?
Ich würde die FORTH-Worte stattdessen wohl in einen "binary blob"
umwandeln, deren Anfang ein Symbol geben, und das alles zusammen linken.
> weiß im Moment nicht, wie ein man ein raw-binary dazulinken> kann.
Wenn du mit [arm-none-eabi-]objcopy aus einem Binärklumpen eine
Objektdatei kopierst, generiert er automatisch ein paar Symbole, die aus
dem Dateinamen abgeleitet werden:
1
$ # Erzeugen von Dummy-Daten
2
$ dd if=/dev/urandom of=test.bin bs=20 count=1
3
1+0 records in
4
1+0 records out
5
20 bytes transferred in 0.000121 secs (164989 bytes/sec)
Jörg W. schrieb:> Wie erfolgt die Einbindung in den Kernel? Vermutlich wird doch da die> Adresse einer Liste irgendwo eingetragen, ab der er die FORTH-Worte dann> sucht, oder?
Der kernel endet auf
@--------------------------------------------------------------------
.global primitives_cutoff, endOfDictionary
primitives_cutoff:
endOfDictionary:
Ab hier werden 16-Bit FORTH tokens aneinandergereiht. Ein FORTH Programm
ist eine Aneinanderreihung von Pseudocode-Worten. Dieser Pseudocode
besteht aus Adressen aus dem Kernel-Binary. Der "Klumpen" wird da
einfach angeklebt, word-aligned.
Die Einbindung in den Kernel erfolgt durch ein Common Lisp Programm, das
das FORTH-System kompiliert, und das Kompilat an den kernel.bin anklebt.
Dazu muß der FORTH-Compiler die Symbole des Kernels kennen.
Werde mir Deine Vorschläge mal zu Gemüte führen.
Grüße
Christoph