Если оператор с оператором А в состоянии AT & T - PullRequest
0 голосов
/ 26 мая 2018

Как мне поступить с оператором if и оператором в качестве условия в AT&T Assembly?

assume x = 0x60
assume y = 0x45

Например:

if(x and y)
    //do something

Будет ли это правильный код дляэто?

.globl func

func:
    push %r10     //r10 = x
    push %r11     //r11 = y
    movq $0x60, %r10        
    movq $0x45, %r11
    jmp .loop

.loop:
     movq %r10, %r12
     and $r11, %r12
     cmpq $0xFF, %r12
     je .if
     jmp .done
.if:
     //Do something here
     jmp .done     
.done:
    pop %r10     //r10 = x
    pop %r11     //r11 = y
    ret

1 Ответ

0 голосов
/ 26 мая 2018

Проверка кода:

Ваш код сильно усложнен.(Но это нормально для новичков; если вы оглянетесь на это, как только у вас появится немного опыта в 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, если результат ИЛИ равен нулю.

...