Проверка кода:
Ваш код сильно усложнен.(Но это нормально для новичков; если вы оглянетесь на это, как только у вас появится немного опыта в asm, вы скажете то же самое.)
Вам не нужно сохранять / восстанавливать r10 илиr11 : функциям разрешено забивать их.то есть, они забиты звонками.Обычно вы используете «устаревшие» регистры, такие как eax / rax и edx / rdx (с 32-битным размером операнда, потому что ваши числа малы), чтобы сохранить размер кода.Но вы можете побеспокоиться о сохранении префиксов REX позже;с r10 и r11 все в порядке.
Вам не нужны никакие инструкции jmp
. jmp
до следующей строки является избыточной, и нет операции: выполнение переходит к следующейсама по себе, независимо от того, есть ли там метка.
Вам нужен только один je
или jne
, чтобы пропустить блок .if
, если условие ложно.
Если ответвляется
Ваше условие and/cmp
не имеет смысла для логических или побитовых and
.Почему это верно, только если все 8 бит установлены?Инструкции SSE2 SIMD, такие как pcmpeqb
, дают результат сравнения 0 или 0xFF, но нет инструкции, которая выдает 0xFF
, если оба входных операнда отличны от нуля.(Итак, что вы реализовали, это if ((x&y) == 0xFF)
Для побитового значения if(x & y)
используйте test %r10,%r11 / jz .done
. Для логического значения, значение test-and-branch для x не равно нулю (test %r10,%r10 / jz .done
, затем повторитедля y.
.globl bitwise_and # args: x in RDI, y in RSI
bitwise_and: # x86-64 System V calling convention
test %rdi, %rsi # set flags according to x&y
jz .Lfalse # skip the next block if (x&y) == 0
# if condition was true, fall into the if block
.Lfalse:
ret
или для логического значения
.globl boolean_and # args: x in RDI, y in RSI
boolean_and:
test %rdi, %rdi
jz .Lfalse
test %rsi, %rsi
jz .Lfalse
# if condition was true, fall into the if block
.Lfalse:
ret
x86, к сожалению, не очень хороший способ использовать только одну инструкцию ветвления, чтобы проверить, равен ли один из входов нулю.ввод по отдельности, например, поведение C x && y
при коротком замыкании - это то, что часто делают компиляторы.
Для x || y
это намного лучше: x || y
верно в тех же случаях, когда x | y
верно, поэтому мы можем просто сделать or %rdi, %rsi
, который устанавливает флаги в соответствии с результатом. Затем jz
, чтобы пропустить блок if
, если результат ИЛИ равен нулю.