Purer Assembler, grosse bin

Für allgemeine Fragen zur Programmierung, welche nicht! direkt mit Lazarus zu tun haben.
Mathias
Beiträge: 6209
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Purer Assembler, grosse bin

Beitrag von Mathias »

Ich habe mal die beiden *.s verglichen, zwischen Konsolenaufruf und Lazarus-IDE.
Die Dateien unterscheiden sich recht stark, so das ich mir ein *diff" erspart habe. Einzig was gleich ist, der Dialekt.
Im Anhand die beiden Dateien.

Auf der Konsole habe ich die *.s so generiert:

Code: Alles auswählen

$  fpc project1.lpr -Anasm -a
Das "-a" braucht es da dringen, ansonsten wird keine *.s erzeugt.

In Lazarus hab ich diese beiden Einträge unter "Benutzerdefinierte Einstellungen":

Code: Alles auswählen

-Anasm
-a
Gibt es unter Lazarus nicht irgendwo ein Fenster, wo man nachschauen kann, wie Lazarus das FPC-Kommando aufruft ?
Dateianhänge
unterschied.zip
(2.7 KiB) 53-mal heruntergeladen
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Mathias
Beiträge: 6209
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Purer Assembler, grosse bin

Beitrag von Mathias »

Ich habe mal versucht, wie der Unterschied zwischen den von C und FPC erstellten Assembler ist. Als Beispiel printf, welches varargs verwendet.
Der grösste Unterschied ist mit aufgefallen, wen die Register ausgehen. C befüllt die Parameter mit push und fpc greift direkt auf die Adresse zu.
Und noch ein feiner Unterschied, wen C printf ohne varargs erkennt, macht er ein puts(). Dafür ist in C die Konstante hello doppelt vorhanden, einmal mit LineEnding das andere mal ohne.

Im Anhang die Unterschiede.
Dateianhänge
printf_FPC_vs_C.zip
(3.2 KiB) 50-mal heruntergeladen
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

PascalDragon
Beiträge: 834
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: Purer Assembler, grosse bin

Beitrag von PascalDragon »

Mathias hat geschrieben:
Sa 5. Aug 2023, 08:47
Ich habe noch folgendes durchprobiert, da schein nasm zu funktionieren.
Das ld nicht geht, liegen daran, das man noch irgendeine lib mit "-l" einbinden muss.

Code: Alles auswählen

$ fpc project1.lpr -Anasm -a
Free Pascal Compiler version 3.2.2 [2021/07/09] for x86_64
Copyright (c) 1993-2021 by Florian Klaempfl and others
Target OS: Linux for x86-64
Compiling project1.lpr
Assembling project1
Linking project1
5 lines compiled, 0.0 sec
tux@tux-B660M-DS3H-DDR4:~/Schreibtisch/dragon_test_2$ rm ./project1
tux@tux-B660M-DS3H-DDR4:~/Schreibtisch/dragon_test_2$ rm ./project1.o
tux@tux-B660M-DS3H-DDR4:~/Schreibtisch/dragon_test_2$ nasm -f elf64 project1.s
tux@tux-B660M-DS3H-DDR4:~/Schreibtisch/dragon_test_2$ ld project1.o
ld: warning: cannot find entry symbol _start; defaulting to 0000000000401000
ld: project1.o: in function `..@c5':
project1.s:(.text+0xe): undefined reference to `fpc_initializeunits'
ld: project1.s:(.text+0x13): undefined reference to `fpc_get_output'
ld: project1.s:(.text+0x2d): undefined reference to `fpc_write_text_shortstr'
ld: project1.s:(.text+0x32): undefined reference to `fpc_iocheck'
ld: project1.s:(.text+0x3a): undefined reference to `fpc_writeln_end'
ld: project1.s:(.text+0x3f): undefined reference to `fpc_iocheck'
ld: project1.s:(.text+0x44): undefined reference to `fpc_do_exit'
ld: project1.o: in function `INITFINAL':
project1.s:(.data+0x10): undefined reference to `INIT$_$SYSTEM'
ld: project1.o: in function `FPC_THREADVARTABLES':
project1.s:(.data+0x24): undefined reference to `THREADVARLIST_$SYSTEM$indirect'
tux@tux-B660M-DS3H-DDR4:~/Schreibtisch/dragon_test_2$ 
Ein FPC Programm besteht nicht nur aus dem Hauptprojekt, sondern auch aus allen benötigten Units. Und eine Unit, die immer benötigt wird, ist die System-Unit. Das heißt du musst auch die system.o aus deiner FPC Installation mit rein linken (direkt angegeben, ohne -l). Oder du rufst FPC einfach mit -sh auf, das wird dir ein Skript erzeugen, dass die nötigen Assemblerbefehle und den Linkerbefehl und einen Verweis auf das ebenfalls erstellte Linkerskript enthält.
Mathias hat geschrieben:
Sa 5. Aug 2023, 13:33
Ich habe mal die beiden *.s verglichen, zwischen Konsolenaufruf und Lazarus-IDE.
Die Dateien unterscheiden sich recht stark, so das ich mir ein *diff" erspart habe. Einzig was gleich ist, der Dialekt.
Im Anhand die beiden Dateien.
Das Lazarus Projekt hat noch aktivierte Debuginformationen.
Mathias hat geschrieben:
Sa 5. Aug 2023, 13:33
Auf der Konsole habe ich die *.s so generiert:

Code: Alles auswählen

$  fpc project1.lpr -Anasm -a
Das "-a" braucht es da dringen, ansonsten wird keine *.s erzeugt.
Nicht ganz korrekt. Die Assemblerdateien werden immer erstellt (außer mit dem internen Assembler), der Unterschied ist nur, dass sie ohne -a wieder gelöscht werden.
Mathias hat geschrieben:
Sa 5. Aug 2023, 13:33
Gibt es unter Lazarus nicht irgendwo ein Fenster, wo man nachschauen kann, wie Lazarus das FPC-Kommando aufruft ?
In den Projekteinstellungen unten der Button „Einstellungen anzeigen”.
Mathias hat geschrieben:
So 6. Aug 2023, 08:34
Der grösste Unterschied ist mit aufgefallen, wen die Register ausgehen. C befüllt die Parameter mit push und fpc greift direkt auf die Adresse zu.
FPC nutzt auf x86_64 eine fixierte Stackgröße, GCC nicht. Bei ersterem wird demnach kein PUSH/POP genutzt, da dies die Stackgröße ändern würde.
Mathias hat geschrieben:
So 6. Aug 2023, 08:34
Und noch ein feiner Unterschied, wen C printf ohne varargs erkennt, macht er ein puts(). Dafür ist in C die Konstante hello doppelt vorhanden, einmal mit LineEnding das andere mal ohne.
Im Gegensatz zu FPC hat der C Compiler Wissen über die printf-Funktion, da diese Teil der Standard-C-Bibliothek ist. Dadurch kann der Compiler dann auch entsprechend optimieren (im Fall von printf ohne weitere Parameter eben die Nutzung von puts, da er weiß, dass der erste Parameter eine Stringkonstante ist, bei der er noch dazu weiß, dass diese mit #10 endet, welches für puts entfernt werden muss).
FPC Compiler Entwickler

Mathias
Beiträge: 6209
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Purer Assembler, grosse bin

Beitrag von Mathias »

FPC nutzt auf x86_64 eine fixierte Stackgröße, GCC nicht. Bei ersterem wird demnach kein PUSH/POP genutzt, da dies die Stackgröße ändern würde.
Die würde auch folgen ASM-Code von C erklären.
Wobei der nicht sauber optimiert ist, zuerst addiert er und anschliessend subtrahiert er wieder.

Code: Alles auswählen

	add	rsp, 32
	sub	rsp, 8
Im Gegensatz zu FPC hat der C Compiler Wissen über die printf-Funktion, da diese Teil der Standard-C-Bibliothek ist. Dadurch kann der Compiler dann auch entsprechend optimieren (im Fall von printf ohne weitere Parameter eben die Nutzung von puts, da er weiß, dass der erste Parameter eine Stringkonstante ist, bei der er noch dazu weiß, dass diese mit #10 endet, welches für puts entfernt werden muss).
Das mit dem doppelten String wird in der Praxis kaum vorkommen. Wen der Compiler printf nehmen muss, dann wir im String sicher ein %x vorhanden sein.
In den Projekteinstellungen unten der Button „Einstellungen anzeigen”.
Danke, gut versteck. Aber man sieht da schon einige Parameter mehr als bei meinem Konsolenaufruf.
Oder du rufst FPC einfach mit -sh auf, das wird dir ein Skript erzeugen,
Krass, was fpc alles kann. Nur mit nasm oder Intel-Code hat er Probleme.

Code: Alles auswählen

$ fpc project1.lpr -a -sh
Free Pascal Compiler version 3.2.2 [2021/07/09] for x86_64
Copyright (c) 1993-2021 by Florian Klaempfl and others
Note: Switching assembler to default source writing assembler
Target OS: Linux for x86-64
Compiling project1.lpr
Closing script ppas.sh
27 lines compiled, 0.0 sec
1 note(s) issued
$ ./ppas.sh 
Assembling project1
Linking project1


$ fpc project1.lpr -Anasm -a -sh
Free Pascal Compiler version 3.2.2 [2021/07/09] for x86_64
Copyright (c) 1993-2021 by Florian Klaempfl and others
Target OS: Linux for x86-64
Compiling project1.lpr
Closing script ppas.sh
27 lines compiled, 0.0 sec
$ ./ppas.sh 
Assembling project1
Linking project1
/usr/bin/ld: project1: error: PHDR segment not covered by LOAD segment
An error occurred while linking project1

Zum Schluss, habe ich es richtig verstanden, FPC erzeugt per Standard, eine *.s im AT&T-Code, ruft as und ld und löscht anschliessend die *.s ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Antworten