7
votes

Lecture du registre RER de Microsoft C ++

Etant donné que l'assembleur en ligne n'est pas disponible dans Microsoft C ++ lors de la compilation de l'architecture X64, je ne peux pas comprendre comment accéder au registre RERS (pointeur de pile). Je sais que je peux le lire à l'aide de RTLCapturecontext, mais cela effectuerait également de nombreuses opérations non désirées. De plus, ce serait quelques milliers de fois plus lents (à mes besoins, pas acceptables). Si j'écris une fonction ASM distincte, le RER changerait évidemment, de sorte que ce n'est pas une alternative non plus non plus.

Alors, comment lisez-vous le contenu du registre X64 RER à l'aide de Microsoft C ++?


9 commentaires

Peut-être qu'il y a une autre façon de faire ce que vous voulez faire que de lire RSP. Quel est votre objectif réel?


@ Joachim: Qu'essayez-vous d'atteindre?


Ne tenez pas compte de ma réponse (maintenant supprimée). La pile Win64 doit être alignée sur une limite de 16 octets. Une fonction distincte ne peut donc pas indiquer correctement RER .


Vous ne devriez pas essayer de lire le registre car il est clairement non portable. Je pense que vous avez mal compris pourquoi l'assembleur en ligne a été tiré.


Notez également que, dans le code optimisé, RER pourrait changer au milieu d'une fonction de fonction si le compilateur décidait que c'est une bonne idée.


@ Steve-O: C'est son ordinateur, pour l'amour du ciel. Pourquoi ne devrait-il pas lire RSP si c'est ce qu'il veut faire?


La position de @Tonky Microsoft sur l'assembleur X64 est faite, elles ont déterminé que la qualité du code s'améliore sans elle.


@ Steve-O Le RSP ne change pas au milieu d'une fonction. Cela ferait de se dérouler des exceptions.


Près de deux ans plus tard, nous avons un message dans le Ancienne nouvelle chose que tout le monde devrait lire lors de la recherche d'une solution pour cette question.


5 Réponses :


1
votes

Il n'y a que deux façons que je puisse penser à faire cela:

1) Créez un fichier ASM avec l'instruction pour déplacer le RSP dans RAX et revenir, puis voir si vous pouvez obtenir le compilateur à l'aligner.

2) Si ce qui précède est un non-go, déclarez une variable de pointeur volatil et utilisez le __ nop () intrinsèque pour vous donner suffisamment d'espace pour corriger l'instruction nécessaire dans la procédure de poste (ou Heck, Il suffit d'attribuer une valeur à votre pointeur volatil plusieurs fois et remplacez-le)


0 commentaires

6
votes

Vous pouvez l'obtenir indirectement à l'aide du _addressofreturnaddress () (voir Référence MSDN ) intrinsèque. Évidemment, vous ne faites pas savoir avec certitude où le cadre de pile actuel s'arrête, mais vous pouvez l'avoir estimer avec toutes les variables de pile que vous avez et en regardant l'assemblage généré.

En combinaison avec la suggestion d'Olipro: Utilisation de _AddressofreturnAddRESS () Dans une fonction autonome, obtenir l'adresse de la pile devient sérieusement facile. Sans parler qu'il existe une forte probabilité pour une fonction écrite en C contenant uniquement un appel à cette intrinsèque à être inline.


4 commentaires

Pas bien. J'ai besoin du RSP comme valeur d'exécution pour traverser la pile d'appels à l'aide de tailles de cadre en cache.


@ Joachim: En fait, je pense que ma réponse est équivalente à celle d'Olipro, sans code de montage.


En fait, je pense que vous avez raison. Je devrais pouvoir utiliser le _Addressofreturnaddress (). Laissez-moi l'essayer et je reviendrai cette question.


Le bien intrinsèque inliné et cela fonctionne bien. Changé la réponse acceptée à celle-ci.



2
votes

Êtes-vous au courant du _Addressofreturnaddress intrinsèque? Ce n'est pas le RSP enregistre lui-même, mais c'est un peu volatilien à part entière.


1 commentaires

Pas bien. J'ai besoin du RSP car je traverse la pile d'appels basée sur des tailles de cadre en cache.



0
votes

__ getcfs , __ getpsp , éventuellement __ getreg ?

Vous pouvez également créer un lien avec un fichier d'objet MINGW-W64 qui fait l'assembleur en ligne.


2 commentaires

@Necrolis ipf est IA64? Allez comprendre.


Les joies de Intel Naming: X86-64 sont toujours raccourcies à x64, les gens supposent que X64 doit être identique à l'IA64, car IA32 est X86, mais IA64 est une architecture totalement différente, c'est pourquoi MSDN utilise IPF pour désigner IA64 (vraiment décevant de trouver un bel intrinsèque, seulement pour voir que c'est pour IPF uniquement).



5
votes

OK, alors, j'ai eu un violon avec elle et je l'ai eu du travail; Vous ne pouvez pas obtenir le compilateur pour l'aligner, mais vous n'avez heureusement pas besoin de cela pour, laissez-le simplement tomber dans un fichier .s ou .asas et compiler avec `ml64 / c guasm.s» et remet le .obj à la Linker. xxx

puis sur le côté C des choses Tout ce dont vous avez besoin est extern "c" __int64 getrsp ();


3 commentaires

L'appel provoque la décrémentation du pointeur de pile de 8 octets; Si vous augmentez 8 octets, vous avez sa valeur initiale.


Bien sûr. Jeter l'adresse de retour d'une fonction appelée révélera les appelants SP. Merci!!


@Olipro j'ai constaté que l'utilisation de _Addressofreturnaddress était un peu plus propre sans la langue de montage et, comme je pouvais éviter un appel. Uppote pour une bonne solution si ...