Obligement - L'Amiga au maximum

Lundi 27 juin 2022 - 16:53  

Translate

En De Nl Nl
Es Pt It Nl


Rubriques

Actualité (récente)
Actualité (archive)
Comparatifs
Dossiers
Entrevues
Matériel (tests)
Matériel (bidouilles)
Points de vue
En pratique
Programmation
Reportages
Quizz
Tests de jeux
Tests de logiciels
Tests de compilations
Trucs et astuces
Articles divers

Articles in english


Twitter

Suivez-nous sur Twitter




Liste des jeux Amiga

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z,
ALL


Trucs et astuces

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Glossaire

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Galeries

Menu des galeries

BD d'Amiga Spécial
Caricatures Dudai
Caricatures Jet d'ail
Diagrammes de Jay Miner
Images insolites
Fin de jeux (de A à E)
Fin de Jeux (de F à O)
Fin de jeux (de P à Z)
Galerie de Mike Dafunk
Logos d'Obligement
Pubs pour matériels
Systèmes d'exploitation
Trombinoscope Alchimie 7
Vidéos


Téléchargement

Documents
Jeux
Logiciels
Magazines
Divers


Liens

Sites de téléchargements
Associations
Pages Personnelles
Matériel
Réparateurs
Revendeurs
Presse et médias
Programmation
Logiciels
Jeux
Scène démo
Divers


Partenaires

Annuaire Amiga

Amedia Computer

Relec


A Propos

A propos d'Obligement

A Propos


Contact

David Brunet

Courriel

 


Programmation : Une introduction à l'assembleur PowerPC sur MorphOS
(Article écrit par Matthew Gundry et extrait de MorphOS Library - février 2011)


Note : traduction par David Brunet.

Sautez dans le grand bain et compilez quelque chose sans attendre

Vous pouvez copier et coller ce qui suit, mais il est probablement plus rapide d'entrer ces deux lignes ci-dessous dans un éditeur de texte :

.text
	blr

Enregistrer le fichier sous le nom "shorty.s".

.text est une directive de l'assembleur, nous en reparlerons plus tard. blr est une des nombreuses instructions de branchement. Celle-ci signifie "branch to link register" (branchement au registre de lien). Lorsqu'un programme se termine, c'est la dernière instruction à être exécutée et elle provoque le retour de la séquence d'exécution des instructions au programme ou à l'environnement appelant (Shell, Ambient, etc.). Les sous-programmes peuvent également se terminer avec cette instruction, mais nous en reparlerons plus tard.

C'est le moment idéal pour vous demander si vous avez déjà installé vbcc. Si ce n'est pas le cas, faites-le, téléchargez vbcc sur sun.hasenbraten.de/vbcc/.

Une fois vbcc installé, ouvrez une fenêtre Shell et changez le répertoire où "shorty.s" a été sauvegardé. Ensuite, entrez :

vasmppc_std -Felf -o ram:shorty.o shorty.s

Ceci indique à vasm de générer un fichier objet au format ELF appelé "shorty.o" dans "ram:" à partir du fichier source "shorty.s".

Hello ? Le programme MorphOS le plus court du monde - ou pas ?

Il y a des fois où un éditeur de liens est nécessaire pour traiter un fichier objet afin de générer un exécutable - ce n'est pas le cas dans cet exemple.

Entrez ceci dans la fenêtre Shell :

ram:shorty.o

Vous aurez l'impression que rien ne se passe - mais au moins, cela se passe très vite. Cependant, quelque chose s'est passé. "shorty.o" a été identifié comme un programme exécutable et chargé en mémoire où la séquence d'exécution des instructions du processeur lui a été transmise. Comme nous l'avons mentionné plus haut, l'unique instruction "blr" de ce programme a fait en sorte que la séquence d'exécution des instructions soit renvoyée directement à l'endroit d'où elle a été appelée - dans ce cas, le Shell.

Il peut être intéressant de savoir que toutes les instructions PowerPC sont longues de quatre octets. Dans la nomenclature PowerPC, cette longueur est appelée un "word" (mot). Mais prenons un moment pour jeter un coup d'oeil à la taille de "shorty.o". Entrez ceci dans la fenêtre Shell :

list ram:shorty.o

2664 octets ! Mais ceci est typique pour les fichiers objets car ils contiennent beaucoup d'informations supplémentaires qui sont utilisées dans le processus de débogage et de lien. L'édition de liens, en particulier avec l'option "-s" (suppression de tous les symboles), génère un exécutable sensiblement plus petit. Entrez ceci dans la fenêtre Shell :

vlink -s -o ram:shorty ram:shorty.o

list ram:shorty

L'exécutable nouvellement généré fait 328 octets. C'est beaucoup plus petit que son fichier objet, mais que font ces 324 autres octets ? Ils constituent le "conteneur" ELF qui contient l'instruction unique de quatre octets de shorty. "ELF" signifie "Executable and Linkable Format" (format exécutable et liable) et est utilisé par MorphOS, AmigaOS 4 et AROS - sans oublier Linux, Unix, BSD et même des consoles de jeux. Il existe de nombreuses informations sur ce format de fichier en ligne mais ce sujet sera abordé un peu plus loin dans cet article, lorsque l'utilisation du programme objdump sera abordée.

Le nouveau et l'ancien

En général, pour créer un programme qui fait quelque chose d'utile ou qui produit au moins un résultat observable, il est nécessaire d'utiliser les fonctions des bibliothèques du système d'exploitation. Malgré la famille de processeurs nettement différente sur laquelle tourne MorphOS par rapport à la famille 68k utilisée par AmigaOS Classic, MorphOS demeure largement compatible avec AmigaOS. Cette compatibilité se reflète dans une API très similaire partagée avec AmigaOS et étendue à l'utilisation d'une structure de système MorphOS comme s'il s'agissait des registres de données et d'adresses internes d'un processeur 68k réel. Cette structure s'appelle EmulHandle et elle est toujours disponible via le registre PowerPC GPR2. De même, comme pour AmigaOS 68k, l'adresse de la base de la bibliothèque Exec se trouve toujours à l'emplacement mémoire 4. De nombreux aspects de l'API d'AmigaOS correspondent fidèlement aux caractéristiques disponibles dans le processeur 68k et la comparaison de code suivante devrait illustrer la façon dont elle est reprise dans l'API de MorphOS PowerPC.

Voici une tâche courante effectuée lors de l'initialisation de nombreux programmes : l'ouverture de la bibliothèque DOS. Il s'agit d'un exemple particulièrement simple d'utilisation de cette bibliothèque, mais la plupart des fonctions suivent cette forme.

68k

lea 	dosName,a1		;load affective adress (charge l'adresse effective). Résultat: a1 = l'adresse
				;de départ de la chaîne dosName.
moveq 	#0,d0			;move quick (déplacement rapide). Résultat: d0 = 0 (cela indique à OpenLibrary que
				;n'importe quelle version de la bibliothèque est acceptée.
move.l 	4,a6			;move longword (déplacement mot long). Résultat: a6 = la valeur 32 bits stockée
				;à l'adresse mémoire 4 = ExecBase.
jsr	_LVOOpenLibrary(a6)	;jump to subroutine (saut à la sous-routine). Résultat: compteur de programme =
				;adresse dans a6 + _LVOOpenLibrary et une adresse de retour est placée sur la pile.
dosName: dc.b "dos.library",0	;le résultat de cette fonction est le pointeur de base dos.library retourné
				;dans d0 ou un zéro retourné dans d0 si la bibliothèque n'a pas pu être ouverte.

PowerPC

lis 	r3,dosName@ha		#load immediate and shift (chargement immédiat et décalage). Résultat: le demi-mot
				#supérieur de l'adresse dosName est chargé dans r3 et décalé à la position du
				#demi-mot supérieur.
addi 	r3,r3,dosName@l		#add immediate (addition immédiate). Résultat: r3 = l'adresse 32 bits complète de dosName
				#car les 16 bits inférieurs de l'adresse de dosName lui ont été ajoutés.
				#Voir ci-dessous concernant @ha, @l...
stw 	r3,reg_a1(r2)		#store word (stockage de mot). Résultat: r3 est stocké à l'adresse r2 + reg_a1.
				#reg_ax et reg_dx sont des offsets dans la structure EmulHandle qui
				#sont traités comme les registres d'adresse et de données 68k.
li 	r3,0			#load immediate (chargement immédiat). Résultat: r3 = 0.
stw 	r3,reg_d0(r2)		#Résultat: r3 est stocké à l'adresse r2 + reg_d0. Rappelez-vous : la structure
				#MorphOS EmulHandle est toujours pointée par r2.
li 	r3,4			#Résultat: r3 = 4.
lwz 	r3,0(r3)		#load word and zero (chargement du mot et zéro).
				#Résultat: r3 = la valeur 32 bits stockée à l'adresse r3 + 0 = ExecBase.
stw 	r3,reg_a6(r2)		#Résultat: r3 est stocké à l'adresse r2 + reg_a6.
li 	r3,_LVOOpenLibrary	#Résultat: r3 = _LVOOpenLibrary (_LVOOpenLibrary est un nombre de 16 bits qui a
				#été défini ailleurs).
lwz 	r0,EmulCallDirectOS(r2)	#Résultat: rO = contenu de l'adresse r2 + EmulCallDirectOS (EmulCallDirecOS
				#est un autre nombre de 16 bits qui a été défini ailleurs. C'est aussi une partie
				#de la structure EmulHandle).
mtctr 	r0			#move to count register (déplacement vers le registre compteur). Résultat: r0
				#est copié dans le registre compteur.
bctrl				#branch to count register and link (branchement au registre compteur et lien).
				#Résultat: la séquence d'exécution des instructions passe à l'adresse stockée dans
				#le registre compteur et une adresse de retour est placée dans le registre de lien.
dosName:			#Le résultat de cette fonction est le pointeur de base de dos.library retourné dans r3
				#ou un zéro retourné dans r3 si la bibliothèque n'a pas pu être ouverte.
.string "dos.library",0  	#La directive .string ajoute automatiquement un zéro à la fin de "dos.library" qui
				#est nécessaire pour marquer la fin d'une chaîne.

Les attributs @h, @ha et @l sont nécessaires pour spécifier les demi-mots de poids fort et de poids faible des valeurs 32 bits immédiates, car la taille fixe de 32 bits des instructions PowerPC ne laisse pas suffisamment d'espace pour un code opération d'instruction et 32 bits supplémentaires de données. La différence entre @h et @ha est due à l'utilisation courante de l'instruction addi (add immediate - addition immédiate), qui ne prend qu'une valeur immédiate signée, pour fournir les 16 bits inférieurs d'une constante de 32 bits - telle qu'une adresse. Parfois, ces 16 bits inférieurs correspondent à une valeur négative et c'est alors que l'utilisation préalable de l'attribut @ha entraîne l'ajustement de sa valeur immédiate pour compenser. Ces détails ne sont résolus qu'avant l'exécution, lorsque le programme est chargé. L'attribut @h spécifie simplement le demi-mot supérieur d'une constante 32 bits sans tenir compte de ce qui suit. Pendant que je m'attarde sur de telles subtilités, la signification de zéro dans "load word" et de zéro dans l'instruction lwz est que sur les processeurs PowerPC 64 bits, cette instruction chargera une valeur 32 bits de la mémoire dans le mot inférieur d'un GPR 64 bits, puis effacera (ou mettra à zéro) son mot supérieur. C'est quelque chose à considérer pour MorphOS tournant sur les ordinateurs de la classe PowerPC G5.

On pourrait être excusé de penser que l'extrait de code PowerPC a l'air un peu disgracieux comparé au premier. Alors que chaque instruction PowerPC fait quatre octets, les instructions 68k peuvent faire de deux à dix octets. Une seule instruction 68k peut charger une valeur à partir d'une adresse mémoire 32 bits spécifiée par un opérande d'instruction et la stocker à une autre adresse mémoire 32 bits spécifiée par le second opérande d'instruction. Le 68k peut également effectuer d'autres opérations que de simples chargements et stockages directement sur la mémoire. Ou du moins le laisser croire... En réalité, la mémoire d'un ordinateur ne fait qu'envoyer et recevoir des données, aucun autre traitement de données (comme l'addition, la soustraction, etc.) ne se produit en mémoire. Alors que l'instruction 68k add.l #$12345678,(a0) semble ajouter la valeur immédiate de son premier opérande à ce qui peut déjà être stocké à l'adresse indiquée par a0, le contenu de cette adresse est en fait chargé depuis la mémoire dans un registre de travail privé, l'addition est effectuée et le résultat est ensuite stocké à nouveau au même emplacement mémoire. Cette instruction effectue donc deux accès à la mémoire alors qu'il pourrait sembler qu'il n'y en ait qu'un seul. Comparez cela à la programmation en assembleur PowerPC où les chargements et les stockages en mémoire sont tous effectués de manière explicite. Avant que les données puissent être utilisées, elles doivent être chargées de la mémoire dans un GPR (General Purpose Register), zéro (dans le cas d'une simple copie de la mémoire) ou plusieurs opérations peuvent alors être effectuées et les données peuvent être stockées en mémoire.

A moins que vous ne soyez tout à fait nouveau en assembleur PowerPC, vous savez déjà que le PowerPC possède 32 GPR - r0 à r31. Mais saviez-vous que l'utilisation souhaitée de ces registres est définie dans un document appelé ABI System V.4 auquel MorphOS adhère ?
  • r0 - volatile.
  • r1 - pointeur de pile.
  • r2 - pour l'utilisation du système (avec MorphOS, r2 pointe vers la structure EmulHandle).
  • r3 - initialisé avec un pointeur vers un tampon de commande DOS.
  • r4 - initialisé avec la longueur du tampon de commande DOS.
  • r5 - initialisé avec un pointeur vers une structure ELF.
  • r3 à r10 - volatile et peut être utilisé pour passer des arguments de fonction. Si plusieurs arguments sont nécessaires, la pile est utilisée.
  • r11 et r12 - volatiles.
  • r13 - pointeur de petite zone de données. Si ce registre est utilisé par une fonction ou une sous-routine, il doit d'abord être sauvegardé puis restauré avant de retourner à l'endroit d'où il a été appelé.
  • r14 à r31 - pas de but prédéfini. Si ces registres sont utilisés par une fonction ou une sous-routine, ils doivent d'abord être sauvegardés et ensuite restaurés avant de retourner à l'endroit d'où elle a été appelée.
L'utilisation du mot "volatile" ci-dessus signifie que les fonctions ne sont pas censées conserver le contenu de ces registres. r1 et r2 sont les seuls registres qui doivent être restaurés à leur valeur initiale par un programme qui se termine. Cependant, alors que la plupart des programmes modifieront r1 et le restaureront plus tard, il est préférable de ne pas avoir modifié r2 en premier lieu.

L'ABI System V.4 définit également une manière particulière pour les programmes et les sous-routines d'organiser leurs cadres de pile. Lorsqu'un programme est chargé en mémoire et que la séquence d'exécution des instructions lui est transmise, le pointeur de pile pointe toujours vers le cadre de pile du programme appelant et il y a également une adresse importante stockée dans le registre de lien à ce moment-là. À moins que ce programme ne soit très simple (comme shorty), il doit enregistrer l'adresse du registre de lien et, très probablement, créer son propre cadre de pile. De manière assez pratique, il existe une position spéciale dans la pile de l'appelant dans laquelle un programme appelé peut sauvegarder le contenu du registre de lien. Voici un exemple assez courant des toutes premières instructions d'un programme ou d'une sous-routine :

mflr r0				#move from link registrer (déplacement vers le registre de lien).
				#Résultat: r0 = adresse de retour du programme/environnement appelant.
stwu r1,-(pick-a-number*4)(r1)	#store word and update (stockage du mot et mise à jour). Résultat: la valeur
				#initiale de r1 (pointeur du cadre de la pile de l'appelant) est stockée à un
				#emplacement mémoire situé en dessous de sa valeur actuelle. Cette valeur inférieure
				#est ensuite écrite dans r1.
stw r0,((pick-a-number*4)+4)(r1)#store word (stockage du mot). Résultat: r0 est stocké à l'emplacement mémoire qui
				#est un mot au-delà de la pile du programme appelant... Euh ?

"Euh ?" en effet... Essayons de visualiser la mémoire utilisée comme espace de pile.

Adresse Contenu
0x2f83e4b8 0x........ Autres valeurs stockées par le programme de l'appelant dans le cadre de la pile trs - en général, l'appelant ne doit pas charger ou stocker quoi que ce soit ici.
0x2f83e4b4 0x........ Emplacement spécial réservé au programme de l'appelant pour stocker l'adresse de retour de l'appelant. Il se trouve dans le registre de lien après que l'appelant se branche sur un programme ou une sous-routine de l'appelé.
0x2f83e4b0 0x2f83e8b0 Initialement, r1 pointe ici. C'est le début de la pile de l'appelant. Le contenu représente un pointeur vers le cadre de pile de l'appelant. Ceci est appelé chaînage arrière.
0x2f83e4ac 0x........ Encore une fois, cet emplacement, un mot au-delà du cadre de pile nouvellement créé, est réservé pour une adresse de retour à utiliser à la fin d'une sous-routine ou d'un appel de fonction de bibliothèque, etc.
0x2f83e4a8 0x2f83e4b0 Après stwu r1,-8(r1), r1 pointe vers cette adresse et ce contenu (l'adresse du cadre de pile de l'appelant). est créé ici.
0x2f83e4a4 0x........ Espace de pile pour les programmes ou les sous-routines qui doivent encore être appelés.

Notez que stwu r1,-8(r1) crée un cadre de pile de deux mots qui est la plus petite pile qu'un programme ou une sous-routine peut avoir si, à son tour, il appelle un autre programme, une sous-routine ou une fonction de bibliothèque. Le plus souvent, un cadre de pile plus grand est créé, bien que stwu r1,-4(r1) puisse être utilisé par un programme ou un sous-programme pour créer un cadre de pile d'un mot, mais cela serait redondant et un tel programme ne doit appeler aucun autre programme, sous-programme ou fonction de bibliothèque. Un tel programme n'a pas besoin de stocker la valeur dans le registre de lien pour éviter qu'elle ne soit écrasée par des appels ultérieurs et peut se terminer et retourner à son appelant avec une simple instruction blr, tout comme le fait shorty.

Une autre remarque concernant les cadres de pile plus grands et les tailles de pile appropriées : pour des raisons liées à l'architecture PowerPC, il est judicieux de choisir des tailles de cadre de pile multiples de 16 octets.

Voici un exemple moins courant des premières instructions d'un programme, mais il peut mieux illustrer la façon d'utiliser les cadres de pile :

mflr r0 			#Résultat: r0 = l'adresse de la pile de l'appelant.
stw r0,4(r1)			#Résultat: 4(r1) = r0  A ce stade, r1 pointe toujours vers le cadre de la pile de
				#l'appelant et 4(r1) est l'adresse mentionnée ci-dessus comme étant "un mot au-delà
				#de la pile de l'appelant".
stwu r1,-16(r1)			#Résultat: r1 = adresse de départ du nouveau cadre de pile de quatre mots à utiliser
				#par ce programme ou cette sous-routine.
				#0(r1) = le contenu précédent de r1 qui était un pointeur vers le cadre de pile de l'appelant.

Examinons maintenant les dernières instructions impliquées dans la fin du programme, qui annuleraient les instructions précédentes :

addi r1,r1,16			#Résultat: r1 = r1+16 = adresse de départ de la trame de pile de l'appelant.
				#Notez que lwz r1,0(r1) restaurerait également le pointeur de pile de l'appelant
				#à r1 mais cela impliquerait un accès mémoire supplémentaire.
lwz r0,4(r1)			#Résultat: r0 = valeur stockée à 4(r1) = adresse de retour de l'appelant.
mtlr r0				#move to link registrer (déplacement vers le registre de lien).
				#Résultat: registre de lien = r0.
blr				#branch to link register (branchement vers le registre de lien). Résultat: après la
				#précédente instruction, la séquence d'exécution de l'instruction repasse à l'appelant.
				#Ce programme est maintenant terminé.

Moins de parole, plus d'action s'il vous plaît

Il est temps de compiler un autre programme : celui-ci fera vraiment quelque chose. Mais attendez... Pas un autre programme "Hello World"... J'en ai bien peur. Cette fois, le copier-coller est probablement plus rapide. Vous pouvez également télécharger cette archive source entièrement commentée.

Notez que cet exemple n'utilise pas la trousse de développement de MorphOS. Au lieu de cela, quelques méthodes "rapides et grossières" sont utilisées pour des raisons de simplicité et de lisibilité :

!# Divers offsets des fonctions de la bibliothèque
.set	_LVOOpenLibrary,-552
.set	_LVOCloseLibrary,-414
.set	_LVOVPrintf,-954

.set	_AbsExecBase,4

# structure EmulHandle (toujours pointée par r2)
.set	reg_d0,0
.set	reg_d1,4
.set	reg_d2,8
.set	reg_d3,12
.set	reg_d4,16
.set	reg_d5,20
.set	reg_d6,24
.set	reg_d7,28
.set	reg_a0,32
.set	reg_a1,36
.set	reg_a2,40
.set	reg_a3,44
.set	reg_a4,48
.set	reg_a5,52
.set	reg_a6,56
.set	reg_a7,60
.set	EmulCallDirectOS,100

# Offsets des cadres de la pile
.set	stack_pos0_caller_stack,0
.set	stack_pos1_callerLR,4
.set	stack_pos2_ExecBase,8
.set	stack_pos3_DosBase,12
.set	new_4_word_stack,16

.text

	mflr	r0
	stw	r0,stack_pos1_callerLR(r1)
	stwu	r1,-new_4_word_stack(r1)

	lis	r3,dosName@ha
	addi	r3,r3,dosName@l
	stw	r3,reg_a1(r2)
	li	r3,0
	stw	r3,reg_d0(r2)
	li	r3,_AbsExecBase
	lwz	r3,0(r3)
	stw	r3,stack_pos2_ExecBase(r1)
	stw	r3,reg_a6(r2)
	li	r3,_LVOOpenLibrary
	lwz	r0,EmulCallDirectOS(r2)
	mtctr	r0
	bctrl

	cmpwi	r3,0
	beq	exit

	stw	r3,stack_pos3_DosBase(r1)

	lis	r4,string1@ha
	addi	r4,r4,string1@l
	stw	r4,reg_d1(r2)
	li	r4,0
	stw	r4,reg_d2(r2)
	stw	r3,reg_a6(r2)
	li	r3,_LVOVPrintf
	lwz	r0,EmulCallDirectOS(r2)
	mtctr	r0
	bctrl

	lwz	r3,stack_pos3_DosBase(r1)
	stw	r3,reg_a1(r2)
	lwz	r3,stack_pos2_ExecBase(r1)
	stw	r3,reg_a6(r2)
	li	r3,_LVOCloseLibrary
	lwz	r0,EmulCallDirectOS(r2)
	mtctr	r0
	bctrl

	li	r3,0

exit:	addi	r1,r1,new_4_word_stack
	lwz	r0,stack_pos1_callerLR(r1)
	mtlr	r0
	blr

.rodata

.global	__abox__		#__abox__ est un symbole MorphOS spécial qui permet de
__abox__:			#différencier ce programme des autres programmes PowerPC
.word	1			#qui peuvent fonctionner sous MorphOS...
.type	__abox__,@object	#Lors de l'édition de liens, il faut faire attention
.size	__abox__,4		#à ne pas supprimer ce symbole.  

dosName:
.string	"dos.library"
	
string1:
.string "Hello World\n"

Enregistrez ce fichier source sous le nom de "HelloWorld.s" et ouvrez une fenêtre Shell. Changez de répertoire pour aller là où HelloWorld.s vient d'être sauvegardé et entrez :

vasmppc_std -Felf -o ram:hw.o HelloWorld.s

Une fois de plus, en raison de la simplicité de ce programme, l'édition de liens n'est pas nécessaire, il suffit donc d'entrer ce qui suit dans la fenêtre Shell :

ram:hw.o

Êtes-vous impressionné ? N'hésitez pas à modifier, expérimenter et améliorer ce code source. Un défi pas trop difficile pourrait être de changer ce programme pour qu'il affiche les arguments qui lui sont donnés dans la fenêtre Shell - un certain nombre de petits changements, mais significatifs, seraient nécessaires pour y parvenir. Conseil : regardez à nouveau l'utilisation des registres de l'ABI System V.4 ci-dessus.

La version commentée de HelloWorld.s dans l'archive source donne une brève description de la raison pour laquelle la paire d'instructions mtctr (move to count register - déplacement vers le registre compteur) et bctrl (branch to count register and link - branchement au registre compteur et lien) est utilisée de préférence à mtlr (move to link register - déplacement vers le registre de lien) et blrl (branch to link register and link - branchement au registre de lien et lien) étant donné que cette dernière paire peut dégrader les optimisations de performance de certains processeurs PowerPC. Cependant, l'utilisation principale du registre compteur est un compteur de boucle 32 bits qui peut être automatiquement décrémenté par certaines instructions de branchement.

Lorsque vous choisissez les registres à utiliser dans vos propres programmes, sachez que l'utilisation de r0 dans les opérandes de certaines instructions ne fonctionnera pas toujours comme prévu. Dans ces instructions, le contenu réel de r0 est ignoré et le résultat est basé, à la place, sur la valeur constante zéro. Par exemple, imaginez que r0 contient la valeur 100 lorsque cette instruction est exécutée : addi r0,r0,50. Il semble que le résultat devrait être r0 = r0 + 50 = 150. Le résultat sera en fait r0 = 0 + 50 = 50. Cela peut sembler étrange mais, tant que le programmeur en est conscient, ce comportement peut être utile. Un bon manuel de référence des instructions PowerPC expliquera cela, et bien d'autres choses, de manière beaucoup plus détaillée. Il y a beaucoup de ces documents de référence disponibles en ligne - celui-ci est l'un d'entre eux : MPCFPE32B.pdf.

Trousse de développement de MorphOS, Objdump, ELF et Sections

En plus d'installer vbcc, il est également recommandé d'installer la
trousse de développement de MorphOS et le compilateur MorphOS vbcc. Le script d'installation de ce dernier s'attend à ce qu'il y ait une assignation préexistante pour include:. Si votre système assigne déjà include: quelque part, veuillez passer la partie suivante.

Ce qui suit est mon fichier S:user-startup après l'installation de vbcc, de sa cible de compilateur MorphOS et d'une assignation supplémentaire que j'ai faite précédere de ce commentaire :

;La cible MorphOS de vbcc nécessite que include: doit être assigné quelque part

;
; MorphOS user-startup
;
; Ce script est exécuté au démarrage du système par
; la startup-sequence. Vous pouvez y apporter changements
; personnels ici.
;
; $VER: user-startup 1.1
;

;Activez les éléments suivants pour monter inet-handler. Notez que TCP: permet
;un accès facile à Internet, et permet aux scripts de rechercher les connexions entrantes.
;Certains logiciels malveillants pourraient en abuser.
;Mount TCP:
;BEGIN vbcc
assign >NIL: vbcc: SYS:vbcc
assign >NIL: C: vbcc:bin ADD
setenv VBCC vbcc:
;END vbcc

;La cible MorphOS de vbcc nécessite que include: doit être assigné quelque part
assign include: SDK:GG/os-include

;BEGIN vbcc-ppc-morphos
assign >NIL: vincludemos: vbcc:targets/ppc-morphos/include
assign >NIL: vincludemos: include: add
assign >NIL: vlibmos: vbcc:targets/ppc-morphos/lib
;END vbcc-ppc-morphos

A ce stade, il serait utile d'avoir un certain nombre de fichiers objets et d'exécutables fraîchement générés à regarder avec objdump bien que n'importe quel ELF puisse être utilisé dans ce but. Notez que si les fichiers système de MorphOS 2.x/3.x sont compilés en tant que ELF, ils sont également signés pour empêcher leur utilisation sur MorphOS 1.x où ils pourraient ne pas fonctionner. Cette signature a également pour effet que objdump ne les reconnaît pas comme des ELF.

objdump peut être utilisé pour révéler beaucoup d'informations intéressantes sur un ELF, dont la liste de tous les symboles et sections présents, ainsi que le désassemblage. Soyez conscient que, lorsqu'ils sont désassemblés, des programmes apparemment petits peuvent produire plus d'informations que le tampon d'historique de la fenêtre Shell ne peut en contenir ; redirigez donc la sortie vers un fichier ou spécifiez des adresses de début et de fin pour limiter la sortie. Cela dit, aucun des fichiers générés jusqu'à présent dans ce tutoriel ne risque de submerger le tampon d'historique de l'interpréteur de commandes lorsqu'il est désassemblé.

Comme nous l'avons mentionné juste avant l'exemple de code source précédent, certaines méthodes rapides et grossières ont été utilisées pour des raisons de simplicité et de lisibilité, et cela concerne la manière dont les offsets des fonctions de bibliothèque ont été établis. L'approche utilisée deviendra rapidement préjudiciable à mesure que d'autres offsets seront ajoutés. Il existe un certain nombre de solutions à ce problème, mais nous n'en présenterons qu'une seule ici. Elle consiste à supprimer le caractère de soulignement (_) en tête des noms de fonctions, de sorte que, par exemple, li r3,_LVOOpenLibrary devienne li r3,LVOOpenLibrary. Supprimez ou commentez les trois premières directives .set qui définissent les offsets des fonctions de la bibliothèque et assemblez avec vasm comme précédemment mais notez que le fichier objet résultant n'est plus exécutable. Pour rendre cet objet exécutable, vlink est nécessaire.

vlink -o <nom de l'exécutable souhaité> <nom de l'objet existant> -lamiga

Dans la commande Shell ci-dessus, -lamiga fait référence au fichier libamiga.a que vlink sait rechercher dans vlibmos: Ce fichier contient des informations utilisées pour résoudre de nombreux noms de fonctions de bibliothèque en valeurs numériques. Notez que tout exécutable généré par la commande vlink ci-dessus contiendra beaucoup d'informations sur les symboles qui, bien que potentiellement utiles, augmentent la taille de l'exécutable. Ceci peut être évité avec quelques ajouts à la commande ci-dessus.

vlink -s -P__abox__ -o <nom de l'exécutable souhaité> <nom de l'objet existant> -lamiga

-s supprime tous les symboles du fichier de sortie.
-P<symbole> préserve ce symbole.

Pour plus d'informations, veuillez vous reporter à la documentation de vlink et des autres programmes installés avec vbcc.


[Retour en haut] / [Retour aux articles]