web-dev-qa-db-fra.com

Comment calculer l'adresse de la cible de saut et l'adresse de la branche?

Je suis nouveau dans Langue de l’Assemblée . Je lisais à propos deMIPSarchitecture et je suis coincé avec Adresse cible de saut et Adresse cible de branche et comment calculer chacun d'entre eux.

28
Fahad Uddin

1. Calcul de l'adresse de la succursale

Dans la branche MIPS, l'instruction n'a que 16 bits décalés pour déterminer la prochaine instruction. Nous avons besoin d'un registre ajouté à cette valeur de 16 bits pour déterminer la prochaine instruction et ce registre est en réalité impliqué par l'architecture. Il s’agit d’un registre de PC puisque le PC est mis à jour (PC + 4) pendant le cycle de récupération, de sorte qu’il conserve l’adresse de l’instruction suivante.

(Dans les diagrammes ci-dessous, PC est l'adresse du créneau de délai de branchement, pas l'instruction de branche elle-même. Mais dans le texte, nous dirons PC + 4.)

Nous limitons également la distance de branche à l'instruction -2^15 to +2^15 - 1 à partir de l'instruction (instruction après l'instruction). Cependant, ce n’est pas un réel problème puisque la plupart des agences sont de toute façon locales.

Donc, étape par étape:

  • Sign étend la valeur de décalage de 16 bits pour préserver sa valeur.
  • Multipliez la valeur résultante par 4. La raison en est que si nous allons créer une adresse et que PC est déjà aligné sur Word, la valeur immédiate doit également être alignée sur Word. Cependant, il n’a aucun sens de faire en sorte que le texte immédiat soit aligné sur Word, car nous gaspillerions deux bits bas en les forçant à être 00.
  • Nous avons maintenant une adresse 32 bits. Ajoutez cette valeur à PC + 4 et correspond à l'adresse de votre succursale.

Branch address calculation


2. Calcul d'adresse de saut

Pour l'instruction de saut, Mips n'a que 26 bits pour déterminer l'emplacement du saut. En outre, les sauts sont relatifs au PC dans MIPS. Comme pour les branches, la valeur de saut immédiat doit être alignée sur Word, il est donc nécessaire de multiplier une adresse de 26 bits par quatre. 

Encore une fois étape par étape:

  • Multipliez la valeur 26 bits avec 4.
  • Puisque nous sautons par rapport à la valeur PC + 4, concaténez les quatre premiers bits de la valeur PC + 4 à gauche de notre adresse de saut.
  • L'adresse résultante est la valeur de saut.

En d'autres termes, remplacez les 28 bits inférieurs du PC + 4 par les 26 bits inférieurs de l'instruction recherchée décalés à gauche de 2 bits.

enter image description here

Les sauts sont relatifs à la région par rapport au créneau de retard de branche, pas nécessairement à la branche elle-même. Dans le diagramme ci-dessus, le PC est déjà passé au créneau du délai de branchement avant le calcul du saut. (Dans un pipeline à étapes RISC classique-5, le BD a été récupéré dans le même cycle que le saut est décodé, de sorte que l'adresse d'instruction suivante PC + 4 est déjà disponible pour les sauts ainsi que pour les branches, et le calcul relatif à l'adresse propre du saut serait ont demandé un travail supplémentaire pour enregistrer cette adresse.)

Source: Université de Bilkent CS 224 Diapositives du cours

60
emre nevayeshirazi

Habituellement, vous n'avez pas à vous soucier de les calculer car votre assembleur (ou votre éditeur de liens) aura besoin d'obtenir les bons calculs. Disons que vous avez une petite fonction:


func:
  slti $t0, $a0, 2
  beq $t0, $zero, cont
  ori $v0, $zero, 1
  jr $ra
cont:
  ...
  jal func
  ... 

Lors de la traduction du code ci-dessus en un flux d'instructions binaire, l'assembleur (ou l'éditeur de liens si vous l'avez assemblé dans un fichier objet) détermine l'emplacement de la fonction en mémoire (ignorons le code indépendant de la position pour l'instant). L’emplacement où il réside en mémoire est généralement spécifié dans l’ABI ou vous est donné si vous utilisez un simulateur (comme SPIM qui charge le code sur 0x400000 - notez le lien. contient également une bonne explication du processus). 

En supposant que nous parlions du cas SPIM et que notre fonction soit la première en mémoire, l'instruction slti résidera à 0x400000, la beq à 0x400004 et ainsi de suite. Maintenant nous y sommes presque! Pour l'instruction beq, l'adresse cible branch est celle de cont (0x400010) en regardant un référence d'instruction MIPS , elle est codée comme une signature immédiate de 16 bits par rapport à l'instruction suivante ( divisé par 4 car toutes les instructions doivent de toute façon résider sur une adresse alignée sur 4 octets). 

C'est: 

Current address of instruction + 4 = 0x400004 + 4 = 0x400008
Branch target = 0x400010
Difference = 0x400010 - 0x400008 = 0x8
To encode = Difference / 4 = 0x8 / 4 = 0x2 = 0b10

Encodage de beq $t0, $zero, cont

0001 00ss ssst tttt iiii iiii iiii iiii
---------------------------------------
0001 0001 0000 0000 0000 0000 0000 0010

Comme vous pouvez le constater, vous pouvez vous connecter à -0x1fffc .. 0x20000 octets. Si, pour une raison quelconque, vous devez sauter plus loin, vous pouvez utiliser un trampoline (un saut inconditionnel vers la cible réelle placée dans la limite donnée).

Les adresses de cible Jump, contrairement aux adresses de cible de branche, sont codées à l'aide de l'adresse absolute (à nouveau divisée par 4). Comme le codage de l’instruction utilise 6 bits pour le code opération, il ne reste que 26 bits pour l’adresse (effectivement 28 étant donné que les 2 derniers bits seront 0), les bits les plus significatifs de 4 bits du registre PC sont utilisés lors de la formation de l’adresse ( n’importera pas sauf si vous avez l’intention de franchir les 256 Mo).

Pour revenir à l'exemple ci-dessus, le codage pour jal func est:

Destination address = absolute address of func = 0x400000
Divided by 4 = 0x400000 / 4 = 0x100000
Lower 26 bits = 0x100000 & 0x03ffffff = 0x100000 = 0b100000000000000000000

0000 11ii iiii iiii iiii iiii iiii iiii
---------------------------------------
0000 1100 0001 0000 0000 0000 0000 0000

Vous pouvez le vérifier rapidement et jouer avec différentes instructions, en utilisant cet assembleur MIPS en ligne i couru (notez que cela ne prend pas en charge tous les opcodes, par exemple slti, je l'ai donc changé en slt ici). :

00400000: <func>    ; <input:0> func:
00400000: 0000002a  ; <input:1> slt $t0, $a0, 2
00400004: 11000002  ; <input:2> beq $t0, $zero, cont
00400008: 34020001  ; <input:3> ori $v0, $zero, 1
0040000c: 03e00008  ; <input:4> jr $ra
00400010: <cont>    ; <input:5> cont:
00400010: 0c100000  ; <input:7> jal func
18
user786653

Pour de petites fonctions comme celle-ci, vous pouvez simplement compter à la main le nombre de sauts vers la cible, à partir de l'instruction sous l'instruction de branche. Si elle se ramifie à l’arrière, le nombre de sauts devient négatif. si ce nombre n'exige pas les 16 bits, pour chaque nombre situé à gauche du nombre le plus significatif de votre nombre de sauts, attribuez-leur la valeur 1, si le nombre de sauts est positif, attribuez-leur la valeur 0 cibles, cela vous évite beaucoup d’arithmétique supplémentaire dans la plupart des cas. 

  • chris
0
kiwicomb123