0

Je suis en train de me enseigner x86, et j'ai couru à travers la nécessité de retourner un immédiat, nombre négatif:Puis-je encoder un négatif 64 bits immédiat en x86?

.text 
.align 4,0x90 
.globl _scheme_entry 
_scheme_entry: 
movl $-42, %eax 
ret 

Lorsque j'imprime la valeur de retour de cette fonction (printf("%" PRIdPTR "\n", scheme_entry()), je reçois un nombre de non-sens:

$ ./neg             
4294967254 

Je devine que c'est parce qu'il est un négatif 32 bits, 00000000FFFFFFFF, au lieu d'un négatif, ffffffffffffffff

Comment puis-je stocker une valeur 64 bits constante 64 bits. directement dans une fonction d'assembleur sur? Dois-je l'encoder en deux instructions distinctes?

+0

Ne l'imprimez-vous pas? 'scheme_entry' semble renvoyer un entier de 32 bits (sinon, pourquoi le placez-vous dans' eax'?) – harold

+0

gcc aligne normalement les points d'entrée de la fonction sur 16 octets. Il n'y a pas non plus de raison de forcer le padding à être NOP à un octet (car il ne fonctionnera jamais). Utilisez '.p2align 4' pour aligner' 1 << 4'. (Pour une fonction aussi minuscule, une limite de 8 octets couvrirait toute la fonction, donc vous pourriez '.p2align 3'.) Les processeurs modernes ne sont pas aussi sensibles à l'alignement du code que les processeurs plus anciens, mais c'est quand même une bonne idée. le remplissage NOP ne s'exécutera pas. –

+0

@PeterCordes un peu de cela est sur ma tête - je suis le long [un tutoriel d'écriture compilateur] (http://scheme2006.cs.uchicago.edu/11-ghuloum.pdf), qui nous a intentionnellement utilisez la sortie de 'gcc' pour de minuscules entrées C afin de décider de ce qui doit être émis par nos compilateurs. La plaquette ci-dessus a été copiée essentiellement textuellement, mais je n'ai pas encore appris ce qu'elle fait! : x – ELLIOTTCABLE

Répondre

3

Les messages instantanés 32 bits pour les instructions 32 bits (comme movl) sont utilisés tels quels et writing EAX zeros the upper 32 bits of RAX. Vous n'obtenez pas de bêtises, vous obtenez 2^32 - 42, ce qui est exactement ce à quoi vous devez vous attendre, car x86 utilise des entiers signés complémentaires de 2.

Les messages instantanés à 32 bits pour les instructions avec une taille d'opérande de 64 bits sont étendus à 64 bits.

Utilisez mov $-42, %rax pour renvoyer une valeur négative de 64 bits, au lieu d'une valeur positive de 64 bits légèrement inférieure à 2^32. (En utilisant %rax car la destination implique une taille d'opérande de 64 bits, c'est-à-dire movq.)

Utilisez un débogueur pour afficher les valeurs dans les registres.

+0

Ceci est une excellente information! Oui, j'étais au courant de deux-complément; mais '% rax' (et' mov' vs 'movl', apparemment?) étaient les pièces qui me manquaient ici. Je vais courir avec ça! Je vous remercie! – ELLIOTTCABLE

+2

@ELLIOTTCABLE Plutôt son movl vs movq. Le suffixe peut être omis s'il est clair pour les opérandes. – fuz