У 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.
Мы можем ясно видеть, что эти наблюдения пересекаются с некоторыми операторами +(добавить мнемонику), фактически, если мы вычислим таблицу истинностидля всего выражения (с именем 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 и and, мы приходим к следующему упрощенному сравнению в конце:
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 будут иметь одно и то же значение в конце.