Pull to refresh

Comments 35

Помимо x86 и arm есть еще mips, sh, blackfin и более чудные архитектуры с регистровыми окнами типа powerpc, байкалов и xtensa(https://sachin0x18.github.io/posts/demystifying-xtensa-isa/). Обычно ассемблер используют для вставок кода который нельзя написать на более высокоуровневых языках. И тут более важной информацией будет ABI или как передаются параметры в подпрограмму.

Байкал это обычный Arm. Про регистровые окна вы видимо Эльбрус имели ввиду

Из всех вышеупомянутых можно немного вспомнить про мипс, он еще в атеросах и мтк еще появляется и хтенца, но ес32/8266 это своеобразная хтенца, более того там и риск-в есть.

С какого момента powerpc стал с регистровыми окнами? Я что-то пропустил? С регистровыми окнами НЯЗ только спарки, из того что как-то живо и не экзотически-проприетарное типа икстенз и эльбрусов всяких.

Да ошибся. Spark, Эльюрус, Itanium и Xtensa используют регистровые окна. Я просто к тому что abi может быть весьма не тривиальным.

Порядок операндов в gas для инструкции MOV на x86 выглядит как-то очень непривычно после "классического" ассемблера.

Это синтаксис AT&T.

Насчёт различий архитектур, есть хорошая книга: Revers engineering для начинающих.

Непонятно, почему это недоразумение вообще существует. Есть Intel-синтаксис, и, какое совпадение, Intel же эту архитектуру и породила. То есть мы имеем синтаксис от отцов архитектуры, и некий альтернативный вариант, который непонятно почему вообще прижился.

Это "недоразумение" существовало и использовалось ещё на PDP11.

вырезка из https://en.wikipedia.org/wiki/X86_assembly_language#Syntax (перевод)

язык ассемблера x86 имеет две основные синтаксические ветви: Intel syntax и AT & T syntax. Синтаксис Intel доминирует в мире DOS и Windows, а синтаксис AT & T доминирует в мире Unix, поскольку Unix был создан в AT & T Bell Labs.

Это "недоразумение" существовало и использовалось ещё на PDP11.

Это само по себе не основание для переноса такого порядка на X86, при том, что для MIPS, ARM, RISC-V и прочих тот же gas использует порядок "результат первым".

В данном случае те люди, что сделали порт на 80386 для AT&T V86, заложили диверсию, которую, возможно, сами осознали, но было уже поздно.

Самая "мякотка" в этой диверсии в ситуациях типа:

0000000000000000 <.text>:
   0:   0f a4 d8 0a             shld   $0xa,%ebx,%eax
   4:   0f ac d8 0a             shrd   $0xa,%ebx,%eax

0000000000000000 <.text>:
   0:   0f a4 d8 0a             shld   eax,ebx,0xa
   4:   0f ac d8 0a             shrd   eax,ebx,0xa

Разворачивать все аргументы, а не только переносить приёмник вперёд... для shld, shrd в какой последовательности стоят аргументы - критично для понимания - а тут такая пакость возникла.

Для меня синтаксис AT&T более удобен. Я к нему быстрее привык, чем к синтаксису Intel. И это при том, что большую часть времени я сидел именно на синтаксисе Intel.

Думаю это не нам решать, по какой причине Unix системы остались на синтаксисе AT&T, а не перешли на соседний.

Для меня синтаксис AT&T более удобен. Я к нему быстрее привык, чем к синтаксису Intel.

Попробуйте понять, почему вы думаете, что он вам более удобен. При том, что:

1) Требуется после чтения родных Intel источников каждый раз мысленно разворачивать порядок аргументов.
2) В некоторых случаях требуется делать замены логики в именовании, как в соотношении fsub :: fsubr.
3) Некоторые команды переименованы вопреки всякой логике, причём не получено от этого никакой пользы (ну-тко чем отличается ctlq от clto? Почему вообще не решили назвать как sexto и sexti, чтобы никто не путался?)
4) Порядок аргументов не соответствует подавляющему большинству конкурирующих ISA.

Стоит ли оно того?

Думаю это не нам решать, по какой причине Unix системы остались на синтаксисе AT&T, а не перешли на соседний.

Эээ... вообще-то и нам, и кому угодно. Это не попытка принять решение за других. Это поиск именно исторических причин, в том, что уже состоялось 30-35 лет назад. Вы решили запретить (нам - кому именно нам?) исследовать историю?

Эээ... вообще-то и нам, и кому угодно.

Нет, не нам. Нам лишь решать использовать этот синтаксис или нет.

почему вы думаете

Не надо заниматься игрой слов. Если вам этот синтаксис не удобен, то это не значит что он не удобен другим. Все ваши "недочёты", нивелируются человеком который читает код и понимает разницу между синтаксисом AT&T и Intel.

А люди, которые читают код, иногда даже не обращают внимания на каком ЯП этот код написан. Потому что важна логика кода и что он делает, а не сам код.

Вы решили запретить (нам - кому именно нам?) исследовать историю?

Извиняюсь, что? ))) Зачем в очередной раз играть словами? Если я вам пишу, про то что: "не нам решать, что делать разработчику", но вы решили за разработчика что: "он должен делать так как вы сказали"!

Нам лишь решать использовать этот синтаксис или нет.

Именно. Поэтому, несмотря на то, что GCC и Clang по умолчанию используют AT&T syntax, и в ассемблерных кусках в ядрах и libc всяких Linux и *BSD в основном они - как только мы выходим за пределы этого поддомена, наблюдается существенный разворот в сторону Intel стиля. Я как-то анализировал наличную кодобазу в исходниках, где (в основном во всяком мультимедиа и криптографии) любят ассемблерные файлы.

Если вам этот синтаксис не удобен, то это не значит что он не удобен
другим. Все ваши "недочёты", нивелируются человеком который читает код и
понимает разницу между синтаксисом AT&T и Intel.

Кто занимается тут игрой слов, вопрос спорный, но я попытаюсь перейти к конструктиву. А он такой, что пропорция тех, кто предпочитает Intel, очень заметная, и за пределами тех, кто исторически с самого начала привык к AT&T, его (AT&T) очень мало хотят.

А с учётом резкого падения части X86 в разработках, где требуется ассемблер, будет падать ещё больше. Держать в голове постоянно выкрутки порядка - сложно.

Все ваши "недочёты", нивелируются человеком который читает код и
понимает разницу между синтаксисом AT&T и Intel.

Можно читать не обращая внимание на язык. А можно - обращая, и это полезнее. Потому что от языка может зависеть, например, реакция на целочисленное переполнение, или отличие && в C от and у Паскаля может давать код, который просто так не перенесётся (в любую из сторон).

Недочёты нивелируются, да. Но это лишняя затрата умственных сил, порой резко заметная.

Зачем в очередной раз играть словами?

Я отвечал на ваш вопрос - "зачем перешли", а не "зачем его использовать", "зачем сохранять" и всё такое. Там, где вы видите игру слов, я вижу минимально корректный учёт того, что действительно сказал собеседник. "Игра слов" выглядит иначе.

но вы решили за разработчика что: "он должен делать так как вы сказали"!

Они сами и решают, без меня (см. соседний комментарий). В MIPS, ARM, RISC-V, куче других не только приёмник первый - это не было бы проблемой, если бы единообразно в пределах ISA он был последним - но Unix мир не меняет то, что сделано у соседей. Диверсия введена только для x86 (и, ещё раз повторюсь, не только в плане порядка аргументов). И тем не менее куда ни глянь где nasm, fasm, другие аналоги - Intel порядок тотально.

Кто занимается тут игрой слов, вопрос спорный, но я попытаюсь перейти к конструктиву.

Проблема в том, что вы выше, уже за меня всё решили. Удобнее это мне или нет.

Но это лишняя затрата умственных сил, порой резко заметная.

Человеку надо тратить умственные силы, чтоб "не засиживаться на месте". Голова человека должна работать и человек должен осознавать свои ошибки и уметь их исправлять.

Так что зачастую, лишний раз пошевелить мозгами не помешает.

Я отвечал на ваш вопрос - "зачем перешли", а не "зачем его использовать", "зачем сохранять" и всё такое.

Тогда не соизволите объяснить, каким образом ваше мнение должно было учитываться при переходе/не переходе с одного синтаксиса на другой? Для разработчиков Unix в то время.

Тогда не соизволите объяснить, каким образом ваше мнение должно было учитываться при переходе/не переходе с одного синтаксиса на другой? Для разработчиков Unix в то время.

А это как раз у вас тут образцовая, 300%ная демагогия. Потому что речь не о ситуации, типа, пришёл покупатель земельного участка и вдруг "почему тут сарай? я хотел именно тут пасеку", а продавец, поставивший этот сарай 40 лет назад, не мог представить себе подобного желания.

Нет, аргументы в пользу сохранения порядка аргументов (и вообще синтаксиса в целом) Intel они полностью и безоговорочно были понятны и тогда, и в их принципиальной корректности сомнений не было. А вот почему для конкретной команды исполнителей вес этих аргументов оказался ниже веса аргументов за сохранение того, к чему они привыкли в случае VAX, PDP-11 или, как предположил mpa4b@, M68k, несмотря на потенциальные проблемы при будущем расширении активно развивающейся архитектуры - вот это как раз хороший предмет для исторического исследования. И вот это вы почему-то пытаетесь заткнуть откровенной подтасовкой, типа, что здесь моё мнение, а не аргументация.

Человеку надо тратить умственные силы, чтоб "не засиживаться на месте

Но на что-то полезное. Решение кросвордов, например (пример маргинальный, но показательный) слишком малоэффективно для целей написания программ. Разворот аргументов каждый раз в голове - из этой же серии.

Проблема в том, что вы выше, уже за меня всё решили. Удобнее это мне или нет.

Я за вас ничего не решал. Вы можете для себя переделать любой язык и любой ассемблер как угодно. Посмотрите, например, на ассемблер Go для x86. Он совершенно несовместим ни с Intel, ни с AT&T - там, например, регистр зовётся AX независимо от размера данных в операции. Но его авторы имели свои цели (которые как раз озвучили), и там хотя бы известно, как они описали свои причины. И они не стараются доказать, что это лучший вариант... В случае же AT&T vs. Intel "народная" любовь статистически именно на стороне Intel, и этому причины не только в том, что владелец архитектуры гнёт в эту сторону.

Я за вас ничего не решал.

Точнее это я сам себе писал?

Попробуйте понять, почему вы думаете, что он вам более удобен.

или мне привиделось?

Посмотрите, например, на ассемблер Go

Ну тогда можно было тогда взять (для примера) кроссплатформенный ассемблер FasmG. Зачем брать для этого ЯВУ?

А это как раз у вас тут образцовая, 300%ная демагогия.

Нападение лучшее средство защиты. Это ведь я писал:

Цитата: "Эээ... вообще-то и нам, и кому угодно."

в ответ на мои слова, цитата: "Думаю это не нам решать, по какой причине Unix системы остались на синтаксисе AT&T, а не перешли на соседний."

... и опять же скажем что мы ни за кого ни чего не решаем... всё по стандарту...

Думаю пора завязывать этот диалог.

clto

сами придумали команду?

В синтаксисе AT&T специально к командам "прицепили" буквы: b, w, l, q, s, t.

Странно что вы не жалуетесь на формат команд SIMD-инструкций. Ведь это ближе к AT&T синтаксису, а не Intel.

сами придумали команду?

cwtd. Опечатался немного, потому что там логики 0 целых фиг десятых. И вы тут таки неправы:

В синтаксисе AT&T специально к командам "прицепили" буквы: b, w, l, q, s, t.

потому что эта группа команд этим правилам не следует аж никак:

AT&T:

   0:   66 98                   cbtw   
   2:   98                      cwtl   
   3:   48 98                   cltq   
   5:   66 99                   cwtd   
   7:   99                      cltd   
   8:   48 99                   cqto 

Но Intel:

   0:   66 98                   cbw    
   2:   98                      cwde   
   3:   48 98                   cdqe   
   5:   66 99                   cwd    
   7:   99                      cdq    
   8:   48 99                   cqo

Логики нет у обоих, но у Intel хоть как-то ровнее. И, повторюсь, названные вами суффиксы не работают:))

Я бы их соответственно назвал: sexti8, sexti16, sexti32, sexto16, sexto32, sexto64 (или альтернативно: sexti ax,al; sexti eax,ax; sexti rax,eax; sexto dx,ax; sexto edx,eax; sexto rdx,rax). Но я тут не решаю.

Странно что вы не жалуетесь на формат команд SIMD-инструкций. Ведь это ближе к AT&T синтаксису, а не Intel.

В чём именно ближе? Вот с ходу из доки Intel:

66 0F 58 /r ADDPD xmm1, xmm2/m128
Add packed double precision floating-point values from xmm2/mem to xmm1 and store result in xmm1.

VEX.128.66.0F.WIG 58 /r VADDPD xmm1,xmm2, xmm3/mem
Add packed double precision floating-point values from xmm3/mem to xmm2 and store result in xmm1.

Приёмник снова первый. Где тут "ближе к AT&T"?

Кстати, вы вспомнили SIMD?

  15:   c5 f0 5c c2             vsubps xmm0,xmm1,xmm2
  15:   c5 f0 5c c2             vsubps %xmm2,%xmm1,%xmm0

Почему вычитаемое слева от уменьшаемого? ;))

Логики нет у обоих, но у Intel хоть как-то ровнее.

cbtw или cbw - byte to word
cwtl или cwde - word to longword
cltq или cdqe - longword to qword

В чём ровнее? Для AT&T я даже не задумываюсь о том, какое идёт расширение.

В чём именно ближе?

В том, что стали просто буквы использовать, а не полномасштабные команды. Если следовать логике Intel, то все команды должны быть расписаны чуть ли не в длинную цепочку каждое слово отдельно (это субъективное мнение).

Для AT&T я даже не задумываюсь о том, какое идёт расширение.

Какая логика вам объясняет, когда писать cwtl, а когда - cwtd?

В том, что стали просто буквы использовать, а не полномасштабные команды.

Вы имеете в виду, наверно, указание размера одиночного аргумента в векторных командах. Да, оно там неизбежно, но размер полного набора аргументов по-прежнему определяется регистром. "Полномасштабные команды" это с указаниями типа "dword ptr"? Если нет, уточните.

И я там в последний момент дописал вопрос, вы могли не заметить. Intel:

   a:   39 d8                   cmp    eax,ebx
  15:   c5 f0 5c c2             vsubps xmm0,xmm1,xmm2

Но AT&T:

    a:   39 d8                   cmp    %ebx,%eax
   15:   c5 f0 5c c2             vsubps %xmm2,%xmm1,%xmm0

Как так получилось, что уменьшаемое справа от вычитаемого? Ссылка на историю появления от PDP-11 тут не сработает: у PDP-11, даже, когда в "sub p, q" было вычитание p из q, при этом "cmp p, q" вычитало q из p.

Какая логика вам объясняет, когда писать cwtl, а когда - cwtd?

Довольно странный вопрос. Вы знаете что делает команда cwtl? cwtd?

Вы не видите различия их конечной работы? Или конечный результат eax против dx:ax ни чего не значит?

Как так получилось, что уменьшаемое справа от вычитаемого?

Да, такие моменты обескураживают. Но видятся достаточно логичными. Если у Intel операнд-приёмник идёт первым, а операнд-источник последним, то при полном развороте (когда два источника, один приёмник) для синтаксиса AT&T будет достаточно правильно поменять местами именно все операнды, а не какой-то один (но это лишь догадки с моей стороны).

Вполне возможно преследовали цель упростить компиляцию текста. Ведь в данном случае надо просто последовательно считать значения один за другим, не меняя в дальнейшем их местами.

Довольно странный вопрос. Вы знаете что делает команда cwtl? cwtd?

Пожалуйста, не делайте вид, что не поняли вопрос. Я не про понимание семантики, а про то, как из семантики дальше выводится конкретная буква окончания аббревиатуры. Тут понять невозможно, надо просто запомнить.

то при полном развороте (когда два источника, один приёмник) для
синтаксиса AT&T будет достаточно правильно поменять местами именно
все операнды, а не какой-то один (но это лишь догадки с моей стороны).

О! Извините, но, вероятно, вы себя тут сами засокра́тили (от имени Сократ). Получается, что синтаксис Intel всё равно исходный, и выяснение вопроса, как правильно, начинается с него... а затем зачем-то развернуть весь порядок.

Ведь в данном случае надо просто последовательно считать значения один за другим, не меняя в дальнейшем их местами.

Для чего именно? Для вычитания всё равно требуются оба аргумента, чтобы начать реальную операцию...

Тут понять невозможно, надо просто запомнить.

И? Это везде так. И в синтаксисе Intel тоже надо запоминать. Что вы пытаетесь тогда доказать?

Получается, что синтаксис Intel всё равно исходный

Где я писал обратное?

Для чего именно?

Для компилятора.

Я повторяюсь? Я ведь уже это написал?!

Последовательность байтов. Достаточно развернуть последовательность и получим тот же самый код, только из другого синтаксиса (вы точно программист?).

Возможно это мои догадки, но пока тут с вами демагогией занимаюсь, пришло на ум что синтаксис AT&T более правильный по отношению к компилятору. Надо будет изучить этот вопрос и более точно всё узнать. Наверняка не просто так была развёрнута последовательность источников и приёмника.

Ссылка на историю появления от PDP-11 тут не сработает

А ссылка например на 68k сработает?

Ну, возможно, да. Просто обычно в источниках пишут, что AT&T синтаксис был взят по аналогии с PDP-11. Я думаю, это уже натяжка, но на этом не акцентировал, а предполагал скорее VAX, на котором таки были образцовые Unix системы по состоянию на 1985. M68k тут как-то побоку, но как источник сомнительных решений типа "cmp p,q это источник флагов согласно q-p" вполне может прокатить...

Между прочим, это не "сомнительные решения", а основа большинства дешёвых (т.е. не всяких там вендорлоков типа VAX) unix-машин 80ых. Так что влияние 68k может быть даже больше, чем кривенького vax.

У меня к этому один вопрос - а почему для вас VAX "кривенький", а M68k - нет? По-моему, они друг друга стоят в плане извратности...

Можно включить Intel syntax.

Вообще так называемый AT&T syntax, происходящий от прямого переноса логики PDP-11 на X86 ребятами, сделавшими вначале AT&T V86, и что перешло в SCO и затем во все юниксы на X86 - да, штука немного странная. Эффекты не только в порядке аргументов - например, в некоторых командах FPU. Но в реальности достаточно легко привыкаешь.

если у вас Windows то вам надо будет использовать WSL или виртуальную машину. А если у вас Mac, то есть вероятность, что вы сможете сделать всё точно так же как и на Linux. Не сможете? Не переживайте, просто создайте виртуальную машину Linux.

А можно мне всё-таки без Линукса и WSL просто писать на ассемблере прямо в вижуал студии? Ну пожалуйста.

если вы найдёте на чём тестировать ваш код, то возможно всё что вашей душе угодно.

masm вроде в студию до сих пор входит, так что по крайней мере под текущую архитектуру писать никто не мешает.

Лично для меня ассемблер больше для понимания логики программ и реверса. Иногда (редко) приходилось инжектировать код, но и в этом случае обычно достаточно написать на C/C++, компильнуть, просмотреть ASM в листинге и обрезать весь обвес. А вот чтобы прямо писать на ассемблере с макросами с чистого листа так и осталось в глубинах времён DOS.

PS: ещё любопытно изучать как работают разные оптимизации на одном и том же исходном Сишном коде.

Зачем что-то обрезать? __declspec(naked).

Когда у людей ассемблер полотно ассоциируется с DOS, в этом есть что-то глубоко порочное.

Sign up to leave a comment.

Articles