Функция поворота в сборке x86_64 AT&T

Я реализую функцию поворота в 64-битной сборке AT&T, и у меня возникают проблемы с получением правильного вывода в моем коде.

Я пытаюсь реализовать функцию

unsigned long rotate(unsigned long val, ul num, ul dir); 

Val - это значение, которое я хотел повернуть, num - сколько раз и направление влево или вправо, 0 - вправо, 1 - влево.

Мой код сборки:

.global rotate

rotate: #value = %rdi
        #num = %rsi 
        #direction = %rdx 
        mov %rsi, %r10 #puts num into register
        test %rdx, %rdx 
        jz right #if rdx is 0 jump to rotate right
        #else go to loop right below which rotates left
loop: 
     test %r10, %r10 #if num is 0 I am done
     jz done 
     rol $1, %rdi #rotate left 1 bit
     dec %r10 #decrement my count
     jmp loop #jump to top of loop 

 right: #same logic as left 
      test %r10, %10 
      jz done 
      rol $1, %rdi  
      dec %r10 
      jmp loop 
 done: 
      mov %rdi, %rax
      ret 

Мой код C:

#include <stdio.h> 
extern unsigned long rotate(unsigned long val, unsigned long num, unsigned long direction); 

int main()
{
unsigned long v,n,d; 
v = 0xDEADBEEFDEADBEEF; 
n = 2; 
d = 1; 

printf("%x\n ", rotate(v,n,d));    
}

Когда я компилирую и запускаю, я получаю значение 0x7AB6FBBF, тогда как я должен получить 0x7AB6FBBF7AB6FBBF.

Что-то не так с моими инструкциями, не отправляющими unsigned long или что-то еще?

Разве это не должно быть длинным длинным без знака?

Matthieu Brucher 30.10.2018 23:37

Вы знаете, что на большинстве платформ long 32-битный, верно?

Sneftel 30.10.2018 23:38

@Sneftel: x86-64 System V имеет 64-битный long, и этот код принимает аргументы в RDI и RSI, так что это определенно ABI. (Где документирован ABI для x86-64 System V?)

Peter Cordes 30.10.2018 23:39

Я изменил код c на все беззнаковые длинные длинные, и результаты такие же

pigsploof 30.10.2018 23:42

@pigsploof: x86 имеет rol %cl, %rdi и ror %cl, %rdi, которые вы можете использовать вместо цикла. Просто mov ваш счет смены в %ecx.

Peter Cordes 30.10.2018 23:43

@PeterCordes - хорошее замечание. Хотя даже если тип достаточно широкий, %x не будет печатать полные 64 бита.

Sneftel 30.10.2018 23:46

@Sneftel: да, я все еще смотрел на ужасно чрезмерно сложный asm и предполагал, что они правильно поняли C. Вы и @zch заметили ошибку %x, когда я отправлял ответ об ошибке asm: P

Peter Cordes 30.10.2018 23:48

Питер прав - все современные процессоры имеют баррель-шифтеры, которые могут сдвигать и вращать множество битов за одну инструкцию. Не нужно зацикливаться.

Lee Daniel Crocker 31.10.2018 00:18

@LeeDanielCrocker: баррель-шифтер позволяет одной инструкции иметь задержку в один цикл. Даже оригинальный 8086 имеет ror %cl, %di, но коды операций сдвига / поворота imm8 были добавлены в 286 (posix.nl/linuxassembly/nasmdochtml/nasmdoca.html). Только позже эти инструкции стали действительно быстрыми, но на тех старых процессорах сдвиги / повороты стоили примерно 1 цикл на счет. Это быстрее, чем может выполняться любой цикл, особенно неэффективный цикл с двумя ветвями, который не учитывает флаги, установленные dec.

Peter Cordes 31.10.2018 00:31
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
9
391
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

printf("%x", a) работает с типом unsigned int. На unsigned long вам нужно использовать "%lx" как строку формата.

У вас есть ошибка в вашем asm: ветвь цикла в right выполняет jmp loop вместо jmp right. По крайней мере, это один ваших ошибок, IDK, если их больше. (обновление: @zch обнаружил ошибку в вашем C, которая объясняет усечение, которое вы упоминаете.)

Это было бы легче обнаружить, если бы вы использовали имя лучше, чем loop. например left.

Но вы все равно не должны зацикливаться. x86 имеет rol %cl, %rdi и ror %cl, %rdi, которые можно использовать вместо цикла. Просто mov ваш счет смены в %ecx, например mov %esi, %ecx.

Причина, по которой я использую цикл, заключается в том, что когда я пытаюсь использовать rol% ecx,% rsi, я получаю ошибку несоответствия типа операнда для rol. Я должен использовать немедленную компиляцию, и я не знаю почему.

pigsploof 30.10.2018 23:49

Команды сдвига и вращения @pigsploof могут использовать только% cl или немедленный в качестве операнда счетчика.

zch 31.10.2018 00:03

@pigsploof: в моем ответе есть причина, по которой rol %cl, %rsi (felixcloutier.com/x86/RCL:RCR:ROL:ROR.html). Но mov %esi, %ecx может быть немного более эффективным, чем mov %sil, %cl или movzbl %sil, %ecx, поэтому я рекомендовал это для mov. x86 в любом случае маскирует счетчик сдвигов, поэтому не имеет значения, копируете ли вы или обнуляете старшие биты регистра, или объединяете их со старым значением RCX.

Peter Cordes 31.10.2018 00:26

Другие вопросы по теме