x86 Абсолютная стоимость Cofusion - PullRequest
       11

x86 Абсолютная стоимость Cofusion

0 голосов
/ 29 сентября 2018

Я довольно новичок в сборке Intel x86.В настоящее время я пытаюсь принять абсолютное значение числа, переданного пользователем.На данный момент код просто выплевывает число, которое передается обратно.Если это -5, то программа заявляет, что ее абсолютное значение равно -5.Если это 5, программа заявляет, что его абсолютное значение равно 5. Я пытаюсь работать с условными выражениями и ТОЛЬКО переходить к фрагменту кода, который перевернул бы наш знаковый бит, когда наше число меньше нуля.Я не думаю, что я правильно перехожу к этому разделу кода, я не знаю, почему.Пока мой код выглядит следующим образом:

#compare with 0 and if less then flip sign

#Syntax: int abs_val(int num)
#Returns the absolute value of num
abs_val:
#num will be stored in %rdi
push %rbp
mov %rsp, %rbp
cmpq $0, %rdi
jl signFlip

leave
ret

signFlip:
    neg %rdi
    mov %rdi, %rax
    leave
    ret

Пожалуйста, обратите внимание: я не ищу кого-то, кто мог бы напечатать полное решение для меня.Я бы предпочел, чтобы меня вели в правильном направлении, например: «Вам нужно использовать вызов функции xyz вместо neg» или «Вы не сохраняете значение должным образом, попробуйте переместить бла-бла в ту и ту»

Заранее спасибо!

1 Ответ

0 голосов
/ 29 сентября 2018

Вы также заявляете это int в Си?int - это 32-разрядный тип в ABI System V x86-64, который вы используете.

Но вы оперируете qword long операндами после сообщениякомпилятор старших 32 битов arg не имеет значения.Поэтому, когда вы передаете -5 как int arg, вы получаете 0x00000000fffffffb в RDI, который является 64-разрядным положительным целым числом дополнения 2, 4294967291. (Это предполагает, что старшие биты равны нулю, например, если вызывающийиспользуется mov $-5, %edi, как компилятор C с постоянным аргументом. Но вы можете получить произвольный мусор, если приведете long к int: вызывающая сторона будет считать, что эта функция игнорирует старшие биты, как объявлено.)

Вы забыли mov %rdi, %rax на случай, если аргумент положительный.(Затем выполните условное neg %rax) Или, на самом деле, mov %edi, %eax / neg %eax.

Таким образом, ваша функция оставляет RAX неизменным, когда RDI положителен.(Но так как вызывающий, вероятно, был неоптимизирован C из gcc -O0, он также содержит копию аргумента. Это объясняет поведение abs(-5) => -5, а не полуслучайный мусор, который вы быожидайте от ошибки, подобной этой).


Соглашение о вызовах x86-64 System V не требует от вызывающего абонента расширять узкие аргументы или возвращать значения до полной ширины регистра,поэтому ваш cmp / jl зависит от того, какой мусор оставил вызывающий в верхней половине RDI.

( Требуется расширение знака или нуля при добавлении 32-битного смещения к указателю дляx86-64 ABI? ).Существует недокументированное поведение знака или нуля, расширяющее узкие аргументы до 32-разрядных, но не до 64.


Естественный размер / размер по умолчанию для большинства операций - это 64-разрядный размер операнда, 64-разрядный адресразмер, с неявным расширением нуля до 64-битного при записи 32-битного регистра.Используйте 32-битный размер операнда, если у вас нет особой причины для использования 64-битного кода (например, для указателей).


Посмотрите, что обычно делают компиляторы;они обычно используют cmov для abs().См. Вывод компилятора для long foo(long x) { return std::abs(x); } из компилятора C ++ с включенной оптимизацией, например, https://godbolt.org/z/I3NSIZ для long и int версий.

# clang7.0  -O3
foo(int):                                # @foo(int)
    movl    %edi, %eax
    negl    %eax                   # neg sets flags according to eax = 0-eax
    cmovll  %edi, %eax             # copy the original if that made it negative
    retq

 # gcc7.3 -O3
foo(int):
    movl    %edi, %edx
    movl    %edi, %eax
    sarl    $31, %edx
    xorl    %edx, %eax    # 2's complement identity hack.  Maybe nice with slow cmov
    subl    %edx, %eax
    ret

Но, к сожалению, gcc не переключается наСмов даже с -march=skylake, где это 1 моп.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...