Warunkowe zerowanie do rejestru?

Dec 01 2020

Czy istnieje sposób warunkowego przeniesienia zera do rejestru w asemblerze? Próbuję to zrobić

cmpb %r9b, %r8b #compare r9 and r8
cmovgq $0, %rcx #If r8>r9, move zero to rcx

Jednak kompilator skarży się na „niezgodność typu argumentu dla cmovg” z powodu faktu, że pierwszy operand jest natychmiastową stałą. Myślałem o warunkowym skoku do mov, ale nie jestem pewien, czy są inne kody, które mogłyby być lepsze. Jak mogę warunkowo wyzerować ten rejestr bez zjadania innego rejestru?

Odpowiedzi

dannyadam Dec 01 2020 at 03:36

Ponieważ cmovgqinstrukcja nie akceptuje natychmiastowego operandu wartości, podejście, które nie używałoby innego rejestru, mogłoby polegać na dodaniu wartości zerowej do stosu, użyciu odpowiadającego mu adresu zamiast używania wartości bezpośredniej, a następnie przywróceniu wskaźnika stosu.

pushq   $0 # push 0 onto the stack cmpb %r9b, %r8b # compare r9b and r8b cmovgq (%rsp), %rcx # if r8b > r9b, move zero to rcx addq $8,     %rsp  # restore stack pointer

Alternatywnie, zamiast wpychać zero do stosu, a następnie przywracać wskaźnik stosu, wartość zerowa może być przechowywana w innym miejscu w pamięci.

  cmpb    %r9b, %r8b  # compare r9b and r8b
  cmovgq  zero, %rcx  # if r8b > r9b, move zero to rcx
  ...

  .section .rodata
zero:
  .quad 0

Zamiast używania cmovgq, skok warunkowy jest alternatywnym podejściem, które nie użyłoby innego rejestru i spowodowałoby to samo zachowanie (tj. rcxWarunkowo ustawione na 0, jeśli r8b > r9b).

  cmpb    %r9b, %r8b   # compare r9 and r8
  jle     destination  # if r8b <= r9b, skip the next line
  movq    $0, %rcx     # if r8b > r9b, move zero to rcx
destination:
  ...