Signe étendre neuf nombre de bits en C
J'ai un court, instr
, qui ressemble à ceci:
1110xxx111111111
J'ai besoin de sortir de bits de 0 à 9, ce que je fais avec (instr & 0x1FF)
. Cette quantité est ensuite stockée dans un nouveau court. Le problème est que lorsque cela se produit, il devient 0x0000000111111111
, pas 0x1111111111111111
comme je veux. Comment puis-je résoudre ce problème? Merci!
MODIFIER
Voici le code:
short instr = state->mem[state->pc];
unsigned int reg = instr >> 9 & 7; //0b111
state->regs[reg] = state->pc + (instr & 0x1FF);
C'est un simulateur qui lit dans l'assemblée. state
est la machine, regs[]
sont les registres et pc
est l'adresse de l'instruction courante dans mem[]
.
C'est très bien si les neuf derniers bits représentent un nombre positif, mais si ils représentent -1, il est enregistré comme toutes les 1, ce qui est interprété comme une valeur positive par mon code.
Ce n'est pas clair, qui devrait devenir
0x1111111111111111
?OriginalL'auteur Chris Long | 2011-04-28
Vous devez vous connecter pour publier un commentaire.
Vous pouvez le faire manuellement:
(instr & 0x1FF) | ((instr & 0x100) ? 0xFE00 : 0)
. Ce teste le bit de signe (le pont le plus de bits que vous faites de la rétention,0x100
) et met tous les bits ci-dessus, si le bit de signe est défini. Vous pouvez l'étendre à 5 bits en adaptant les masques pour0x1F
,0x10
et0xFFE0
, étant inférieur à 5 bits, le 5ème peu lui-même et tous les bits 5-16 respectivement.Ou vous pouvez trouver une excuse pour attribuer les bits de la partie supérieure de la signature de courte et de les déplacer vers le bas (l'obtention d'un signe-extension dans le processus):
short x = (instr & 0x1FF) << 7; x >>= 7;
ce dernier peut effectivement finir par être plus simple dans l'assemblée et n'impliquera pas la branche. Siinstr
est signé cela peut être fait en une seule expression:(instr & 0x1FF) << 7 >> 7
. Depuis déjà supprime les bits de poids il simplifie àinstr << 7 >> 7
. Remplacez 7 à 11 pour 5 bits (16-5).Sur ce dernier point, ne pourriez-vous faire
(instr & 0x1FF << 7) >> 7
?J'ai mis à jour la réponse à l'adresse de commentaires...
+1, mais tout en décalant à gauche puis à déplacement droit du travail (tant que vous utilisez un type signé), mais je ne serais pas surpris si certains relativement obscure de compilateurs (peut-être sur les plateformes embarquées) incorrecte optimiser ce que l'écart, en supposant que les deux équipes vont s'annuler et de ne pas le signe-l'extension des effets secondaires. Je mentionne cela parce que le style de code semble le plus probablement se produire avec une plate-forme intégrée lors de l'extraction d'une valeur à partir d'un matériel de registre.
Jackson, @Steve314 est en droit de s'inquiéter de la signé décalage à droite. Le résultat de signé décalage à droite n'est pas défini par la norme. Bien sûr, votre première solution fonctionne, tant que vous en acceptez l'OP du principe que
short
est de 16 bits (également non garantis).OriginalL'auteur Ben Jackson
* Pas de branchement requis *
Voir http://graphics.stanford.edu/~seander/bithacks.html#FixedSignExtend pour une liste très utile peu hacks. Plus précisément, le signe, l'extension est très simple:
Vous devrez peut-être effacer le dessus des morceaux de " x " s'ils ne sont pas à zéro (
x = x & ((1U << b) - 1);
) avant d'utiliser la procédure ci-dessus.Si le nombre de bits 'b' est connu au moment de la compilation (par exemple, les 5 bits de poids dans votre cas), il y a même une solution plus simple (cela pourrait déclencher une connexion spécifique à étendre l'instruction si le processeur prend en charge et le compilateur est assez intelligent):
OriginalL'auteur nimrodm
Comment ça fonctionne? Il sélectionne le bit de signe et la décale vers la de 2 de sa position. Ce est utilisé pour générer la valeur de 1 (si le bit de signe est absent) ou -1 (si le bit de signe est présent).
Cette solution est dépourvu de branches et ne dépend pas d'un comportement indéfini.
OriginalL'auteur rlibby
Je ne suis pas sûr de savoir comment vous obtenez 13 bits à 1 après masquage avec
0x1ff
, mais cela devrait signer étendre un 9-nombre de bits en 16 bits court. Pas assez (ou particulièrement efficace), mais il fonctionne:Masque le bit de signe, passage à la position 1 pour obtenir 0/1. Multipliez cela par le haut bits, si le signe est 1, alors la 9-nombre de bits sera OU ed avec
0xfe
, qui va régler tous les bits de poids de 1.Masquer le bit de signe et de décalage bit à la position 1 (de sorte que vous obtenez 1 si vous disposez d'un nombre négatif et 0 sinon). Puis de créer un OU masque de l'extension de bits et de multiplier ce chiffre par le changé de signe. Si votre numéro d'origine a été négative, ce masque va rester tous ceux, et sinon, ils sont tous des zéros. OU avec votre numéro masqué pour remplir la partie supérieure de bits à 1.
OriginalL'auteur Hoa Long Tam
Juste tombé sur cette recherche de quelque chose d'autre, peut-être un peu tard, mais ce sera peut-être utile pour quelqu'un d'autre. AFAIAC tous les programmeurs C devrait commencer la programmation en assembleur.
De toute façon signer l'extension est beaucoup plus facile que les 2 autres propositions. Juste assurez-vous d'utiliser signé variables et d'utiliser ensuite les 2 périodes.
Si la variable est signé, puis le C compilateur traduit >> Décalage à Droite qui a conservé signe. Ce comportement est indépendant de la plateforme.
Donc, en supposant que l'instrument commence avec 0x1ff alors que nous avons, << 7 SL (Décalage à Gauche), la valeur de sorte que l'instrument est maintenant 0xff80, puis >> 7 ASR de la valeur, de sorte que l'instrument est maintenant 0xffff.
OriginalL'auteur SurrealWombat
C'est plus une amélioration de la réponse à la question précédente, mais pas entièrement générique solution a été présentée jusqu'à présent. Cette macro va signer étendre une valeur
v
avecsb
indiquant la base 0 nombre de bits, le bit de signe.Il utilise la ramification de maximiser la portabilité entre les plates-formes qui n'ont pas de matériel de multiplier ou de barrel shifter.
OriginalL'auteur Kevin Thibedeau
Une solution facile, est-ce, pour
x
être un 5 bits 2'effectif du numéro, regardez:OriginalL'auteur dsula