Аргументы пронумерованы слева направо (спасибо @R. За то, что вы заметили, что это действительно ваше замешательство; я думал, что вы говорили о порядке инструкций asm, и пропустил последний абзац вопрос.)
Выглядит нормально для меня. Когда выполняется инструкция call swap
,
rdi
содержит указатель на a
(локальный в стеке), установленный
lea -0x4(%rbp),%rax
и mov %rax,%rdi
.
(вместо lea
в rdi
, потому что вы не включили оптимизацию.)
rsi
содержит указатель на shared
, настроенный на mov $shared,%esi
al
содержит 0
, потому что вы не определили или не создали прототип функции перед ее вызовом. (GCC должен был предупредить вас об этом даже без -Wall
)
Демонтаж .o
показывает $shared
как 0, потому что он еще не связан, так что это заполнитель (и смещение 0) от символа. Используйте objdump -drwC
, чтобы увидеть символы перемещения. (Мне также нравится -Mintel
вместо синтаксиса AT & T.)
Также проще посмотреть на вывод asm компилятора, где вместо числа и ссылки на символ вы увидите $shared
. См. Как удалить «шум» из вывода сборки GCC / clang? .
Неважно, какие регистры порядка записываются, только их значение при входе в вызываемую функцию.
То же самое для аргументов стека: если компилятор решит использовать mov
для записи аргументов в стек, он может сделать это в любом порядке.
Только если вы решите использовать push
, вам нужно идти справа налево, чтобы оставить первый (самый левый) аргумент по самому низкому адресу, как того требуют все основные соглашения о вызовах C для аргументов, которые не ' t передано в регистрах (если есть).
Этот порядок справа налево может быть причиной, по которой gcc -O0
(без оптимизации, плюс антиоптимизация для отладки) выбирает регистры в этом порядке, даже если это не имеет значения.
Кстати, xor-swap бесполезен и бессмыслен, даже если он реализован правильно без UB. ( Существуют ли точки последовательности в выражении a ^ = b ^ = a ^ = b или оно не определено? ).
if(a==b) { *a = *b = 0; } else { int tmp = *a; *a=*b; *b=tmp; }
- более эффективный своп, который сохраняет поведение безопасного xor-swap обнуления, если оба указателя относятся к одному и тому же объекту. Я полагаю, вы хотите этого? Зачем еще использовать xor-swap?
Генерируемый компилятором asm для любого из них будет в основном плохим, если вы не включите оптимизацию, как код для main
отстой по той же причине. И если вы это сделаете, swap
часто может быть встроенным и содержать ноль инструкций, или просто стоит до 3 mov
инструкций между регистрами; иногда меньше. (Компилятор может просто изменить распределение регистров и решить, что a
и b
теперь находятся в противоположных регистрах.)