8086 : Question sur Call Far indirect

Tout ce qui concerne le logiciel original et sa sauvegarde avec entre autre la régénération des disquettes ou autres supports physiques.

Modérateurs : Papy.G, fneck, Carl

gotcha
Messages : 2802
Inscription : 30 mars 2017 11:39
Localisation : Isère
Contact :

8086 : Question sur Call Far indirect

Message par gotcha »

Hello,

Je suis en train de désassembler un bootloader CPM et je suis bloqué sur un call 'far' indirect.

J'ai un CALLF [07AA] situé à l'adresse 3000:0117

J'ai beau regarder dans des bouquins et sur internet, je n'arrive pas à comprendre la signification exacte du champ 07AA de l'instruction.
Ce nombre doit indiquer où est stockée en mémoire l'adresse cible du call (segment et offset)
1/ Est-ce juste la valeur absolue de l'offset dans le segment actuel ?
2/ Est-ce un offset relatif par rapport à l'adresse de l'instruction call ?

Ghidra fait référence à l'adresse 3000:08AC qui ne correspond ni à 1/, ni a 2/ (0117h + 07AAh = 8C1h)
Je suis du coup un peu dubitatif. Est-ce que quelqu'un a une idée de où je peux trouver l'adresse cible du call ?
Pièces jointes
x86-callf.JPG
x86-callf.JPG (11.59 Kio) Consulté 898 fois
Amstrad CPC et Goupil power :mrgreen:
Bénévole à l'association pour un conservatoire de l’informatique et de la télématique (https://www.aconit.org)
Avatar de l’utilisateur
6502man
Messages : 12332
Inscription : 12 avr. 2007 22:46
Localisation : VAR
Contact :

Re: 8086 : Question sur Call Far indirect

Message par 6502man »

Pour le calcul de l'adresse de destination il faut prendre en compte la valeur
des registres de segments au moment du CALLF .

Il faudrait connaitre la valeur des registres de segments pour en faire le calcul,
il me semble que cela utilise aussi la pile (SS).
Phil.

www.6502man.com

To bit or not to bit.
1 or 0.
Avatar de l’utilisateur
hlide
Messages : 3507
Inscription : 29 nov. 2017 10:23

Re: 8086 : Question sur Call Far indirect

Message par hlide »

Mon 8086 (mode réel 16-bit) est un peu rustique mais les segments sont donnés en unité de 16 octets, donc il faut penser à recadrer. DS est le segment par défaut quand on indique un pointeur FAR sans le préfixe segment explicite pour un CALLF.

Adresse physique = segment * 16 + offset.

CALLF DS:[07AA] -> lit l'offset 16-bit OFS stocké à l'adresse DS:07AA puis le segment 16-bit SEG stocké à l'adresse DS:07AC (à déterminer DS) et enfin fait un call à l'adresse SEG:OFS (SEG*16+OFS)

Ainsi si on a les octets à l'adresse $07AA : 30 09 30 00 ou en mot 16-bit : 0930 3000, ça fait CALLF 3000:0930 (soit 30930h).
Dernière modification par hlide le 05 févr. 2024 12:02, modifié 7 fois.
Avatar de l’utilisateur
hlide
Messages : 3507
Inscription : 29 nov. 2017 10:23

Re: 8086 : Question sur Call Far indirect

Message par hlide »

Et de ce que je lis du code que tu as posté :

- modifie la partie segment à l'adresse ds:07ac (qui sert de pointeur de fonction) en mettant la valeur du segment cs qui est ici 3000.
- appelle la fonction depuis le pointeur de fonction et qui se trouve à l'adresse 3000:xxxx (xxxx car le code ne dit pas quelle valeur).
- modifie la partie offset à l'adresse ds:07aa en mettant la nouvelle valeur d'offset à 0903.

Il y a des fortes chances que CS != DS. On sait que CS = 3000h (un segment c'est par unité de 16 octets). Donc si on a CS:08AA sur "call offset" et CS:08AC sur "call segment", c'est que l'on doit avoir DS:07aa == CS:08aa et DS:07ac == CS:08ac soit un décalage de 256 octets (100h). Donc DS = (CS * 16 + 100h) / 16, soit DS = (30000h + 100h) / 16, soit encore DS = 3010h, donc un CALLF [07aa] donne en fait CALLF [3010:07aa] qui est identique à CALLF [3000:08aa].
gotcha
Messages : 2802
Inscription : 30 mars 2017 11:39
Localisation : Isère
Contact :

Re: 8086 : Question sur Call Far indirect

Message par gotcha »

Oui, effectivement DS = 3010 comme tu l'as anticipé.

Le bootloader de la disquette charge les secteurs du bootloader CPM en mémoire au segment 3000, MAIS, je viens de découvrir que quand il fait un jump au bootloader CPM, il fait un JUMP FAR direct à 3010:0000 !

Il change donc de segment et du coup, on passe de 3000 à 3010 dans CS

Ensuite, le code copie CS dans DS et on se retrouve donc avec un DS à 3010. Ghidra a donc bien analysé. Le CALL récupère l'adresse cible à 3010:07AA/3010:07AC donc à 3000:08AA/3000:08AC

Jump au bootloader CPM:
Pièces jointes
Capture d’écran 2024-02-06 082306.jpg
Capture d’écran 2024-02-06 082306.jpg (4.47 Kio) Consulté 755 fois
Amstrad CPC et Goupil power :mrgreen:
Bénévole à l'association pour un conservatoire de l’informatique et de la télématique (https://www.aconit.org)
Répondre