2010-11-06 5 views
1

J'ai déjà posé une question similaire ici, mais j'ai quand même quelques erreurs, alors j'espère que vous pourriez me dire ce que je fais de mal. Il suffit de savoir que je connais assembleur, et j'ai fait plusieurs projets en 8051 assembleur, et même ce n'est pas la même, est proche de x86 asm.Quelques questions de l'assembleur en ligne

Il y a bloc de code que j'ai essayé en VC 2010 Express (je suis en train d'obtenir des informations d'instruction CPUID): `

int main() 
{ 
char a[17]; //containing array for the CPUID string 
a[16] = '\0'; //null termination for the std::cout 
void *b=&a[0]; 
int c=0; //predefined value which need to be loaded into eax before cpuid 

_asm 
{ 
    mov eax,c; 
    cpuid; 
    mov [b],eax; 
    mov [b+4],ebx; 
    mov [b+8],ecx; 
    mov [b+12],edx; 
} 
std::cout<<a; 
}` 

Donc, pour résumer rapidement, j'ai essayé de créer pointeur vide au premier élément de tableau, et que d'utiliser l'adressage indirect juste déplacer des valeurs de registres. Mais cette approche me donne "stack around b variable est une erreur d'exécution corrompue" mais je ne sais pas pourquoi.

Aidez-nous s'il vous plaît. Merci. Et c'est juste à des fins d'étude, je sais qu'il ya des fonctions pour CPUID ....

EDIT: Aussi, comment pouvez-vous utiliser l'adressage direct dans l'assembleur en ligne x86 VC++ 2010? Je veux dire la syntaxe commune pour la charge de nombre immédiate dans 8051 est mov src,#number mais dans VC++ asm son mov dest,number sans # signe. Alors, comment dire au compilateur que vous voulez accéder à l'adresse de la cellule de mémoire x directement?

+1

Vous n'avez pas besoin de c du tout. Utilisez simplement 'xor eax, eax' pour définir eax = 0. – TonyK

Répondre

6

La raison pour laquelle votre pile est endommagée est que vous stockez la valeur de eax dans b. Stocker ensuite la valeur de ebx à l'emplacement de mémoire b+4, etc. La syntaxe de l'assembleur en ligne [b+4] est équivalente à l'expression C++ &(b+4), si b était un pointeur d'octet.

Vous pouvez voir ceci si vous regardez b et en une seule étape. Dès que vous exécutez mov [b],eax, la valeur de b change.

Une façon de résoudre le problème consiste à charger la valeur de b dans un registre d'index et de l'utilisation Repérage indexé:

mov edi,[b] 
mov [edi],eax 
mov [edi+4],ebx 
mov [edi+8],ecx 
mov [edi+12],edx 

Vous avez vraiment pas besoin b du tout, de tenir un pointeur vers a. Vous pouvez charger le registre d'index directement avec la lea (charge adresse effective) instruction:

lea edi,a 
mov [edi],eax 
... etc ... 

Si vous tripoter assembleur en ligne, il est une bonne idée d'ouvrir la fenêtre des registres dans le débogueur et regarder comment les choses changent quand vous êtes célibataire.

Vous pouvez également adresser directement à la mémoire:

mov dword ptr a,eax 
mov dword ptr a+4,ebx 
... etc ... 

Cependant, l'adressage direct comme plus que les octets de code requis que l'adressage indexé dans l'exemple précédent.

Je pense que ce qui précède, avec l'instruction lea (Load Effective Address) et l'adressage direct que j'ai montré répond à votre dernière question.

0

Le conseil d'ouvrir la fenêtre Registres dans le débogueur montre comment les choses ne vont pas fonctionner dans VC++ 2010 Express.

Vous pourriez être tout aussi surpris que moi de découvrir que le VC++ 2010 Express est MISSING la fenêtre des registres. Ceci est particulièrement surprenant depuis le démarrage des travaux de démontage.

La seule solution de contournement que je connaisse est d'ouvrir une fenêtre de surveillance et de taper les noms de registre dans le champ Nom. Saisissez EAX EBX ECX EDX ESI EIP EIP ESP EBP EFL et CS DS ES SS FS GS si vous le souhaitez

ST1 ST2 ST3 ST4 ST5 ST6 ST7 fonctionnent également dans la fenêtre de la montre.

Vous voudrez probablement également définir la valeur hexadécimale en cliquant avec le bouton droit de la souris dans la fenêtre Espion et en vérifiant l'affichage hexadécimal.