2015-04-23 1 views
2

Dans l'assembleur A64, il existe différentes manières de spécifier des adresses.Décalages de mémoire dans l'assemblage en ligne

/* 
[base{,#0}]     Simple register (exclusive) - Immediate Offset 
[base{,#imm}]    Offset - Immediate Offset 
[base,Xm{,LSL #imm}]  Offset - Register Offset 
[base,Wm,(S|U)XTW {#imm}] Offset - Extended Register Offset 
[base,#imm]!    Pre-indexed - Immediate Offset 
[base],#imm     Post-indexed - Immediate Offset 
label      PC-relative (literal) load - Immediate Offset 
*/ 

Je voudrais utiliser "Offset - immédiat Offset" en assembleur en ligne.

__asm__("ldp x8, x9, %0, 16 \n\t" 
     : 
     : "m" (*somePointer) 
     : "x8", "x9"); 

Cela se traduit à

ldp x8, x9, [x0], 16 

Mon objectif est d'atteindre

ldp x8, x9, [x0, 16] 

Comment puis-je écrire ces instructions avec assembleur en ligne?

+0

Je ne sais pas comment vous pouvez utiliser% 1 avec seulement 1 paramètre? Qu'en est-il de l'utilisation d'une contrainte de registre? Attention: je n'ai pas essayé cela, mais qu'en est-il de quelque chose comme 'asm (" ldp x8, x9, [% 0,% 1] "::" r "(certainsPointer)," i "(16):" x8 ", "x9"); '? –

+0

Correction de ceci - il devrait évidemment lire% 0. Extrait d'une instruction plus longue avec plus d'entrées/sorties, et a oublié de mettre à jour l'argument :-) Ces conseils ne sont-ils pas importants pour le compilateur, afin qu'il sache quelles régions de mémoire sont accédées par mon code? par exemple. si je l'utilise dans un contexte d'écriture, le compilateur a probablement besoin de savoir quelles régions de la mémoire j'ai clobées - dans ce cas, la contrainte de registre ne fonctionnera pas? – Etan

+0

Assez vrai. Donc, puisque le compilateur n'analyse pas réellement l'asm, vous pouvez faire: 'asm (" ldp x8, x9, [% 0,% 1] "::" r "(certainsPointer)," i "(16)," m "(* somePointer):" x8 "," x9 ");' (ie avoir la contrainte, mais ne pas le référencer). Ou ajoutez le clobber "mémoire". Notez que, tel qu'il est écrit, vous dites seulement au compilateur que asm * lit * la mémoire, pas qu'elle le change. –

Répondre

0

Je n'ai pas un ARM 64 bits toolchain pour tester cela avec, mais vous devriez être en mesure de faire quelque chose comme ceci:

asm("ldp x8, x9, %0\n\t" 
    : 
    : "Ump" (*((__int128 *) somePointer + 1)) 
    : "x8", "x9"); 

La Ump contrainte limite l'opérande de mémoire à ceux qui sont autorisés par l'instruction LDP entière, sinon cela fonctionne comme la contrainte m. Si somePointer est déjà un pointeur vers un type de 128 bits, vous pouvez simplement utiliser somePointer[1] comme opérande.

Si ce qui précède ne fonctionne pas alors la suggestion de David Wohlferd devrait:

asm("ldp x8, x9, [%0, %1]" 
    : 
    : "r" (somePointer), "i"(16), "m" (*somePointer) 
    : "x8", "x9");