Utilisation de l'assembleur en ligne [gcc, intel, c], comment vérifier si l'indicateur de portage est défini après une opération?vérifier si l'indicateur de portage est défini
Répondre
Avec des sauts conditionnels jc
(sauter si porter) ou jnc
(sauter si ne pas porter).
Ou vous pouvez stocker le drapeau de transport,
;; Intel syntax
mov eax, 0
adc eax, 0 ; add with carry
ah ok, ne connaissait pas les commandes jc, jnc, adc. Thx – hans
Warnin, GCC utilise la syntaxe AT & T. C'est la syntaxe Intel ... –
@Fififox, merci. J'ai édité ma réponse. –
sbb %eax,%eax
stockera -1 dans eax si le drapeau de transport est fixé, 0 s'il est clair. Il n'est pas nécessaire de pré-effacer eax à 0; soustraire EAX de lui-même fait cela pour vous. Cette technique peut être très puissante puisque vous pouvez utiliser le résultat comme un masque de bits pour modifier les résultats des calculs au lieu d'utiliser des sauts conditionnels.
Vous devez savoir qu'il est seulement valide de tester le drapeau de report s'il a été défini par l'arithmétique effectuée à l'intérieur du bloc asm en ligne. Vous ne pouvez pas tester le report d'un calcul qui a été effectué en code C, car il existe toutes sortes de façons pour le compilateur d'optimiser/de réorganiser les éléments susceptibles d'écraser le drapeau de report.
Cependant l'assembleur x86 est dédié rapide instructions d'essai d'indicateur ALU nommé SETcc où le cc est l'indicateur ALU désiré. Vous pouvez donc écrire:
setc AL //will set AL register to 1 or clear to 0 depend on carry flag
or
setc byte ptr [edx] //will set memory byte on location edx depend on carry flag
or even
setc byte ptr [CarryFlagTestByte] //will set memory variable on location CarryFlagTestByte depend on carry flag
Avec setcc instruction, vous pouvez tester les drapeaux comme carry, zéro, signe, dépassement ou parité, quelques instructions setcc permettent de tester deux drapeaux à la fois.
EDIT: test simple Ajouté fait à Delphes Disparaître un doute sur terme rapide
procedure TfrmTest.ButtonTestClick(Sender: TObject);
function GetCPUTimeStamp: int64;
asm
rdtsc
end;
var
ii, i: int64;
begin
i := GetCPUTimeStamp;
asm
mov ecx, 1000000
@repeat:
mov al, 0
adc al, 0
mov al, 0
adc al, 0
mov al, 0
adc al, 0
mov al, 0
adc al, 0
loop @repeat
end;
i := GetCPUTimeStamp - i;
ii := GetCPUTimeStamp;
asm
mov ecx, 1000000
@repeat:
setc al
setc al
setc al
setc al
loop @repeat
end;
ii := GetCPUTimeStamp - ii;
caption := IntToStr(i) + ' ' + IntToStr(ii));
end;
La boucle (itérations 1M) wich en utilisant l'instruction SETC est plus de 5 fois plus rapide que boucle avec adc instriuction.
EDIT: Ajout du second test dont le résultat du test est enregistré dans le registre AL comulatif dans le registre CL pour être plus réaliste.
procedure TfrmTestOtlContainers.Button1Click(Sender: TObject);
function GetCPUTimeStamp: int64;
asm
rdtsc
end;
var
ii, i: int64;
begin
i := GetCPUTimeStamp;
asm
xor ecx, ecx
mov edx, $AAAAAAAA
shl edx, 1
mov al, 0
adc al, 0
add cl, al
shl edx, 1
mov al, 0
adc al, 0
add cl, al
shl edx, 1
mov al, 0
adc al, 0
add cl, al
shl edx, 1
mov al, 0
adc al, 0
add cl, al
shl edx, 1
mov al, 0
adc al, 0
add cl, al
shl edx, 1
mov al, 0
adc al, 0
add cl, al
shl edx, 1
mov al, 0
adc al, 0
add cl, al
shl edx, 1
mov al, 0
adc al, 0
add cl, al
end;
i := GetCPUTimeStamp - i;
ii := GetCPUTimeStamp;
asm
xor ecx, ecx
mov edx, $AAAAAAAA
shl edx, 1
setc al
add cl, al
shl edx, 1
setc al
add cl, al
shl edx, 1
setc al
add cl, al
shl edx, 1
setc al
add cl, al
shl edx, 1
setc al
add cl, al
shl edx, 1
setc al
add cl, al
shl edx, 1
setc al
add cl, al
shl edx, 1
setc al
add cl, al
end;
ii := GetCPUTimeStamp - ii;
caption := IntToStr(i) + ' ' + IntToStr(ii);
end;
partie rutine avec l'instruction setcc est encore plus rapide pour environ 20%.
Avez-vous une citation pour les appeler rapidement? Je n'ai pas suivi les derniers processeurs depuis quelques générations, mais pendant longtemps, ils ont été considérés comme des opcodes lents. –
@R .. Il n'y a aucun doute: vous avez tort! Vérifiez le test supérieur! –
@R .. Oui, SETcc est une ancienne instruction, mais elle est beaucoup plus rapide que l'ADC ou utilise des sauts cinditional comme JC ou JNC. –
La première fonction effectue une addition non signée, puis teste le dépassement en utilisant le drapeau de report (CF). Les volatiles doivent rester. Sinon, l'optimiseur réorganisera les instructions, ce qui garantit un résultat incorrect. J'ai vu l'optimiseur changer le jnc
en jae
(qui est également basé sur CF).
/* Performs r = a + b, returns 1 if the result is safe (no overflow), 0 otherwise */
int add_u32(uint32_t a, uint32_t b, uint32_t* r)
{
volatile int no_carry = 1;
volatile uint32_t result = a + b;
asm volatile
(
"jnc 1f ;"
"movl $0, %[xc] ;"
"1: ;"
: [xc] "=m" (no_carry)
);
if(r)
*r = result;
return no_carry;
}
La fonction suivante est pour les entrées signées. La même utilisation de volatile s'applique. Notez que maths entiers signés saute sur le drapeau OF via jno
. J'ai vu l'optimiseur changer cela en un jnb
(qui est également basé sur OF).
/* Performs r = a + b, returns 1 if the result is safe (no overflow), 0 otherwise */
int add_i32(int32_t a, int32_t b, int32_t* r)
{
volatile int no_overflow = 1;
volatile int32_t result = a + b;
asm volatile
(
"jno 1f ;"
"movl $0, %[xo] ;"
"1: ;"
: [xo] "=m" (no_overflow)
);
if(r)
*r = result;
return no_overflow;
}
Dans l'ensemble, vous pouvez utiliser les fonctions suivantes.Dans le même tableau d'ensemble, beaucoup de gens rejetteront probablement le travail supplémentaire et non-beauté esthétique jusqu'à pwn'd par un trop-plein/enveloppement/underflow
int r, a, b;
...
if(!add_i32(a, b, &r))
abort(); // Integer overflow!!!
...
L'ensemble de GCC en ligne est disponible dans GCC 3.1 et au-dessus. Voir Assembler Instructions with C Expression Operands ou recherchez 'GCC Extended Assembly'.
Enfin, même dans Visual Studio serait la suivante (pas beaucoup de différence dans la génération de code), mais la syntaxe est beaucoup plus facile depuis MASM vous permet de passer directement à une étiquette C:
/* Performs r = a + b, returns 1 if the result is safe (no overflow), 0 otherwise */
int add_i32(__int32 a, __int32 b, __int32* r)
{
volatile int no_overflow = 1;
volatile __int32 result = a + b;
__asm
{
jno NO_OVERFLOW;
mov no_overflow, 0;
NO_OVERFLOW:
}
if(r)
*r = result;
return no_overflow;
}
Sur le mauvais Côté, le code MASM ci-dessus est uniquement applicable pour l'assemblage x86. Pour l'assemblage x64, il n'y a pas d'inline, vous devrez donc le coder en assembly (dans un fichier séparé) et utiliser MASM64 pour compiler.
Vous pouvez utiliser l'extension goto pour accéder à une étiquette C en utilisant par exemple. asm volatil goto ("ja% l [clabel]"::: "mémoire": clabel) ;, où clabel est libellé C –
La lecture ci-dessous la réponse de @R .. semble invalider votre fonction. 'Vous devez savoir qu'il est seulement valide de tester le drapeau de report s'il a été défini par l'arithmétique effectuée à l'intérieur du bloc asm en ligne. Êtes-vous sûr de cela? –
@DrBeco - oui, pour GCC, cela dépend. GCC assurera la "consécution" des instructions dans votre bloc, mais il pourra insérer/entrelacer ses propres instructions. Si les instructions de GCC ne modifient pas CC, tout ira bien. L'assembleur en ligne de Microsoft ne souffre pas des limitations de GCC. – jww
- 1. Comment vérifier si un objet est défini?
- 2. Kohana: Est-il nécessaire de vérifier si SYSPATH est défini?
- 3. Comment vérifier si la variable d'objet est défini
- 4. Page`_IsValid est défini sur true si OnClientClick est défini
- 5. Comment vérifier si le WaitHandle a été défini?
- 6. Comment vérifier si la méthode abstraite C de est défini lors de l'exécution
- 7. Comment vérifier si un type de données est "défini" avec typedef
- 8. vérifier si NSNumber est vide
- 9. Vérifier si l'objet est visible
- 10. Vérification si un bit est défini ou non
- 11. Cocoa Touch - Vérifier si un int est nul ou non défini?
- 12. Impossible de vérifier si int est nul
- 13. Est-il possible de vérifier si un appareil est jailbreaké?
- 14. Comment vérifier si un pointeur est valide?
- 15. Comment vérifier si javascript est désactivé?
- 16. Comment vérifier si le format est correct
- 17. Vérifier si le contrôle est à l'écran
- 18. powershell - vérifier si le pdf est crypté
- 19. Comment vérifier si l'email est valide?
- 20. Comment vérifier si la fenêtre est active?
- 21. Comment vérifier si FileObject est un dossier?
- 22. Java vérifier si BufferedImage est un GIF
- 23. Comment vérifier si le fichier est binaire?
- 24. Comment vérifier si le formulaire est maximisé?
- 25. javascript vérifier si img src est valide?
- 26. Comment vérifier si un BOOL est nul?
- 27. vérifier si la connexion mysql est valide
- 28. AS3: Vérifier si un dictionnaire est vide
- 29. Java: Vérifier si le PC est inactif
- 30. ASP.NET [Comment vérifier si SqlDataSource1 est vide]
Vous voulez tester cela dans un bloc d'asm ou vous voulez passer l'état de l'indicateur de report à quelque chose dans le code C dans lequel votre asm est en ligne? –
tests dans un bloc de ASM est suffisant. le faire sortir ne devrait pas être si difficile. – hans