xorpd има някои подобни на гатанки части от асемблерния код тук. В тази публикация ще анализирам гатанки 0x12, 0x0d и 0x0e, които имат някои общи неща. Нека се заемем!

xorpd гатанка 0x12

Ето кода:

mov      rcx,rdx
and      rdx,rax
or       rax,rcx
add      rax,rdx

Да вървим стъпка по стъпка:

mov      rcx,rdx  ; rcx =  x
and      rdx,rax  ; rdx =  x && y
or       rax,rcx  ; rax =  y || x
add      rax,rdx  ; rax = (y || x) + (x && y)

Интересният факт за този израз е, че е еквивалентен на или. За да ви покажа това, ще проведа някои тестове. Представяйки всяка неизвестна стойност като един бит, правдоподобните случаи са:

| X | Y |
---------
| 0 | 0 |
| 0 | 1 |
| 1 | 0 |
| 1 | 1 |

Разглобяването на израза е лесно да се забележи, че:

  • Последната част (x && y) ще бъде trueсамо ако и двете променливи са true
  • Първата част (x || y) ще бъде false само ако и двете променливи са false

Можем ясно да видим, че тези наблюдения се припокриват с някои от операторите +(add mnemonic), всъщност, ако изчислим таблицата на истинатаза целия израз (с име exp) и addможем да наблюдаваме, че са еквивалентни:

| X | Y | =>  | exp | add |
---------    -------------
| 0 | 0 |  => |   0 |   0|
| 0 | 1 |  => |   1 |   1|
| 1 | 0 |  => |   1 |   1|
| 1 | 1 |  => |  10 |  10|

xorpd гатанка 0x0d

Този път кодът изглежда така:

mov      rdx,rbx
xor      rbx,rcx
and      rbx,rax
and      rdx,rax
and      rax,rcx
xor      rax,rdx
cmp      rax,rbx

Какво става тук? Имаме 3 неизвестни стойности, идващи от регистрите rbx,rcxиrax. Нека ги наречем X, Y, Z. Ако заменим регистъра за променливи в кодовия фрагмент, получаваме следното:

mov      rdx,rbx  ; rdx = X
xor      rbx,rcx  ; rbx = X ^ Y
and      rbx,rax  ; rbx = Z & (X ^ Y)
and      rdx,rax  ; rdx = Z & X
and      rax,rcx  ; rax = Z & Y
xor      rax,rdx  ; rax = (Z & Y) ^ (Z & X)
cmp      rax,rbx  ; ((Z & Y) ^ (Z & X)) - (Z & (X ^ Y))

След като проследихме този поток от xor и и операции, достигаме до следното опростено сравнение в края:

cmp (Z & (X ^ Y)), ((Z & Y) ^ (X & Z))

В крайна сметка и двата израза ще имат една и съща стойност, независимо от началните стойности на регистрите. Това се случва поради разпределителното свойство на и върху xor, което произтича от законите на Де Морган.

xorpd гатанка 0x0e

Нека анализираме третия:

mov      rcx,rax
and      rcx,rbx
not      rcx
not      rax
not      rbx
or       rax,rbx
cmp      rax,rcx

Замяната на неизвестните стойности с променливи X и Y ни дава известна представа:

mov      rcx,rax  ; rcx = X
and      rcx,rbx  ; rcx = X & Y
not      rcx      ; rcx = !(X && Y)
not      rax      ; rax = !X
not      rbx      ; rbx = !Y
or       rax,rbx  ; rax = !X || !Y 
cmp      rax,rcx  ; cmp !X || !Y, !(X && Y)

Виждаме, че подобно на предишната гатанка, последното твърдение винаги ще бъде вярно, тъй като съответства на следния закон на Де Морган:

!X || !Y is equivalent to !(X && Y)

Така че, независимо от първоначалните стойности за rax и rbx, raxиrcxще имат една и съща стойност в края.