Page 1 of 2

Синтаксис ассемблера

Posted: Mon Jun 03, 2013 2:30 pm
by godlin
Уважаемые разработчики на ассемблере, надеюсь мой вопрос не покажется вам глупому, но мне очень интересно ваше мнение по такому вопросу:
Мы все привыкли к определённому синтаксису ассемблера, который придуман не нами и имеет вполне конкретную историю происхождения.
Давайте на секунду представим, что мы можем поменять синтаксис не меняя сути.
Вот моя небольшая фантазия на эту тему.
Возьмем, к примеру, небольшой фрагмент кода из КолибриОС:

Code: Select all

   NoteforOctave:
        sub     al, 0x81         ; correction value for delay Note
        mov     [countDelayNote], al; save counter delay this new Note
        call    ReadNoteByte
        cmp     al, 0xFF         ; this is PAUSE ?
        jne     packCode         ; no, this is PACK CODE
        in      al, 0x61         ; Get contents of system port B chip 8255
        and     al, 0xFC         ; Turn OFF timer and speaker
        out     0x61, al         ; Send out new values to port B chip 8255
        jmp     saveESI
 
   packCode:
        mov     cl, al           ; save code
        and     al, 0xF          ; clear upper bits
        dec     al               ; correction
        add     al, al           ; transform number to offset constant
        movsx   eax, al          ; EAX - offset
        add     eax, dword kontrOctave; EAX - address from constant
        mov     ax, [eax]        ; read constant
        shr     cl, 4            ; transform for number Octave
        shr     ax, cl           ; calculate from Note this Octave!
   pokeNote:
        out     0x42, al         ; Lower byte Out to channel 2 timer chip 8253
        mov     al, ah
        out     0x42, al         ; Upper byte Out to channel 2 timer chip 8253
        in      al, 0x61         ; Get contents of system port B chip 8255
        or      al, 3            ; Turn ON timer and speaker
        out     0x61, al         ; Send out new values to port B chip 8255
   saveESI:
        pop     eax
        RET
        
ReadNoteByte:
;result:
;  al - note
        push    eax
        push    ecx
        push    edx
        push    esi
 
        mov     eax, [pidProcessNote]
        call    pid_to_slot
        test    eax, eax
        jz      .failed
        lea     ecx, [esp+12]
        mov     edx, 1
        mov     esi, [memAdrNote]
        inc     [memAdrNote]
 
        call    read_process_memory
.failed:
        pop     esi
        pop     edx
        pop     ecx
        pop     eax
        ret
Что, если тот же самый код будет выглядеть вот так:

Code: Select all

   NoteforOctave:
        al    - 0x81             ; correction value for delay Note
        [countDelayNote] = al    ; save counter delay this new Note
        ReadNoteByte()
        al    <> 0xFF:  packCode ; this is PAUSE ?       ; no, this is PACK CODE
        0x61  -> al              ; Get contents of system port B chip 8255
        al    & 0xFC             ; Turn OFF timer and speaker
        0x61  <- al              ; Send out new values to port B chip 8255
        jmp   saveESI
 
   packCode:
        cl    =  al               ; save code
        al    &  0xF              ; clear upper bits
        -- al                     ; correction
        al    +  al               ; transform number to offset constant
        movsx    eax, al          ; EAX - offset
        eax   +  dword kontrOctave; EAX - address from constant
        ax    =  [eax]            ; read constant
        cl    >> 4                ; transform for number Octave
        ax    >> cl               ; calculate from Note this Octave!
   pokeNote:
        0x42  <- al               ; Lower byte Out to channel 2 timer chip 8253
        al    =  ah
        0x42  <- al               ; Upper byte Out to channel 2 timer chip 8253
        0x61  -> al               ; Get contents of system port B chip 8255
        al    &  3                ; Turn ON timer and speaker
        0x61  <- al               ; Send out new values to port B chip 8255
   saveESI:
        pop   eax
        RET
        
ReadNoteByte:
;result:
;  al - note
        push    eax, ecx, edx,  esi
 
        eax   = [pidProcessNote]
        pid_to_slot()
        eax  &&  eax
        jz  .failed
        ecx   =^ [esp+12]
        edx   =  1
        esi   =  [memAdrNote]
        ++  [memAdrNote] 
 
        read_process_memory()
.failed:
        pop   esi, edx, ecx, eax
        RET
По сути, я ничего не изменил - подобное изменение легко реализовать на уровне препроцессинга текста. Код стал немного короче. Вопрос в том, стал ли он читабельнее?
Как вы относитесь к подобной идее?

Re: Синтаксис ассемблера

Posted: Mon Jun 03, 2013 2:41 pm
by Mario_r4
godlin wrote:Вопрос в том, стал ли он читабельнее?
Исключительно личное субъективное оценочное суждение - Код стал намного хуже для читабельности, а с подстветкой так и вообще не понятно что будет. Какая-то каша Си + ассемблер.

Re: Синтаксис ассемблера

Posted: Mon Jun 03, 2013 3:16 pm
by SoUrcerer
Собственно, догадаться, что есть что, всё еще можно. Но насколько это стало понятнее людям "снаружи" - не знаю. А как насчет сложной адресации - типа [esi+edi*2+4]? Как не ввести программиста в заблуждение? Чем это лучше существующих "промежуточных" решений? Такие вопросы стоит обдумать, если есть желание развивать идею.

Re: Синтаксис ассемблера

Posted: Mon Jun 03, 2013 3:37 pm
by Serge
Тогда уж
al -= 0x81
al &= 0xFC
ещё немного и будет С--

Re: Синтаксис ассемблера

Posted: Mon Jun 03, 2013 4:03 pm
by godlin
SoUrcerer wrote:Собственно, догадаться, что есть что, всё еще можно. Но насколько это стало понятнее людям "снаружи" - не знаю. А как насчет сложной адресации - типа [esi+edi*2+4]? Как не ввести программиста в заблуждение? Чем это лучше существующих "промежуточных" решений? Такие вопросы стоит обдумать, если есть желание развивать идею.
С адресацией как-раз не так всё сложно, потому что она в квадратные скобочки ставится :)
Я на самом деле очень-очень плохо знаю ассемблер, и поскольку я крайне избалован высокоуровневыми языками, я ищу способы максимально облегчить себе жизнь при работе с ассемблером.

Re: Синтаксис ассемблера

Posted: Mon Jun 03, 2013 4:10 pm
by godlin
Serge wrote:Тогда уж
al -= 0x81
al &= 0xFC
Да, я сперва тоже так написал, но потом подумал, что эти "=", возможно, лишние, потому что и так понятно, что результат должен записываться в первый операнд, и они требуют лишнего нажатия, и лишний байт занимают :) Возможно, я не прав))
Serge wrote: Тогда уж ещё немного и будет С--
Вот это врядли :lol: Потому что для этого потребуется разбор сложных выражений, а на ассемблере от программиста требуется декомпозиция сложных выражений на (почти) атомарные шаги.

Re: Синтаксис ассемблера

Posted: Mon Jun 03, 2013 4:25 pm
by godlin
Mario_r4 wrote:
godlin wrote:Вопрос в том, стал ли он читабельнее?
Исключительно личное субъективное оценочное суждение - Код стал намного хуже для читабельности, а с подстветкой так и вообще не понятно что будет. Какая-то каша Си + ассемблер.
Инфиксная запись позволяет избавиться от лишних запятых, а замена "длинных" названий на операторы сокращает количество текста. Хотя, конечно, красиво отформатировать стало труднее.

Я собственно, думаю как раз о том, как можно сократить количество кода, не потеряв в читабельности и в качестве кода, т.е., сохранить то, ради чего люди пишут на асме, но еще больше упростив им жизнь. Собственно, тот же fasm ровно этим и занимается, но, вероятно, он не достиг еще совершенства в этом вопросе.

Например, за cmp обычно идет какой-нибудь jne, почему бы объединить их в одну строчку?

Re: Синтаксис ассемблера

Posted: Mon Jun 03, 2013 5:26 pm
by IgorA
godlin wrote:Например, за cmp обычно идет какой-нибудь jne, почему бы объединить их в одну строчку?
не всегда так, в зависимости от условий может быть любой переход из списка:

Code: Select all

JA Jump if above (X > Y) CF=0 & ZF=0 
JAE Jump if above or equal (X >= Y) CF=0 
JB Jump if below (X < Y) CF=1 
JBE Jump if below or equal (X < Y) CF=1 or ZF=1 
JC Jump if carry (cf=1) CF=1 
JCXZ Jump if CX=0 регистр CX=0 
JE (то же, что и JZ) Jump if equal (X = Y) ZF=1 
JG Jump if greater (signed) (X > Y) ZF=0 & SF=OF 
JGE Jump if greater or equal (signed) (X >= y) SF=OF 
JL Jump if less (signed) (X < Y) SF != OF 
JLE Jump if less or equal (signed) (X <= Y) ZF=1 or SF!=OF 
JNA Jump if not above (X <= Y) CF=1 or ZF=1 
JNAE Jump if not above or equal (X < Y) CF=1 
JNB Jump if not below (X >= Y) CF=0 
JNBE Jump if not below or equal (X > Y) CF=1 & ZF=0 
JNC Jump if not carry (cf=0) CF=0 
JNE Jump if not equal (X != Y) ZF=0 
JNG Jump if not greater (signed) (X <= Y) ZF=1 or SF!=OF 
JNGE Jump if not greater or equal (signed) (X < y) SF!=OF 
JNL Jump if not less (signed) (X >= Y) SF=OF 
JNLE Jump if not less or equal (signed) (X > y) ZF=0 & SF=OF 
JNO Jump if not overflow (signed) (of=0) OF=0 
JNP Jump if no parity (pf=0) PF=0 
JNS Jump if not signed (signed) (sf=0) SF=0 
JNZ Jump if not zero (X != Y) ZF=0 
JO Jump if overflow (signed) (of=1) OF=1 
JP Jump if parity (pf=1) PF=1 
JP Jump if parity (pf=1) PF=1 
JPE Jump if parity even PF=1 
JPO Jump if parity odd PF=0 
JS Jump if signed (signed) SF=1 
JZ Jump if zero (X = Y) ZF=1

Re: Синтаксис ассемблера

Posted: Mon Jun 03, 2013 6:34 pm
by godlin
IgorA wrote:
godlin wrote:Например, за cmp обычно идет какой-нибудь jne, почему бы объединить их в одну строчку?
не всегда так, в зависимости от условий может быть любой переход из списка:

Code: Select all

JA Jump if above (X > Y) CF=0 & ZF=0 
...
JZ Jump if zero (X = Y) ZF=1
Это-то как раз понятно, но цель, во-первых, перестать писать cmp, если за ним всё-равно какой-то jump идёт, и, может быть, придумать способ не запоминать весь список, а вместо него использовать какую-то легко читаемую (для новичка) конструкцию (ну, или несколько таких конструкций)? :)
Грубо говоря, в Си мы jump-ы заменяем if-ами с соответствующими условиями, но теряем в объеме кода и производительности.
Например, можно использовать что-то вроде:

Code: Select all

X >     Y : lable     ; JA    
X >=   Y : lable     ; JAE    
X ==   Y : lable     ; JE    
Я хочу обратить внимание, что прекрасно понимаю, господа ассемблерщики, что отказаться от привычного всегда трудно, но прошу попытаться взглянуть на ситуацию свежим взглядом.
Не факт, что из этого что-то хорошее получится, но попытаться стоит)

Re: Синтаксис ассемблера

Posted: Mon Jun 03, 2013 7:14 pm
by CleverMouse
цель, во-первых, перестать писать cmp, если за ним всё-равно какой-то jump идёт
Это достигается простым макросом, приведённым прямо в мануале по fasm:

Code: Select all

macro jif op1,cond,op2,label
{
cmp op1,op2
j#cond label
}
Пример использования:

Code: Select all

jif eax,ae,10h,exit
превратится в

Code: Select all

cmp eax,10h
jae exit
После небольшой доработки макроса можно было бы писать

Code: Select all

jif eax,>=,10h,exit
если бы не то обстоятельство, что ">=" неоднозначно: это может быть знаковым сравнением ge или беззнаковым сравнением ae.

Re: Синтаксис ассемблера

Posted: Mon Jun 03, 2013 7:37 pm
by Freeman
godlin wrote:перестать писать cmp, если за ним всё-равно какой-то jump идёт
А если sete или setb какой-нибудь?

Re: Синтаксис ассемблера

Posted: Mon Jun 03, 2013 9:22 pm
by godlin
Freeman wrote:
godlin wrote:перестать писать cmp, если за ним всё-равно какой-то jump идёт
А если sete или setb какой-нибудь?
Ну, не обязательно же отказываться от базового синтаксиса)
Просто, что в данном случае удобнее, тем и пользоваться.

Re: Синтаксис ассемблера

Posted: Wed Feb 05, 2014 8:44 pm
by Kopa
Похоже идея так и осталась идеей и вариант HLA ассемблера для использования "неподходит"

Моя идея несколько локальнее
Дополнить ассемблер командой -> вариант команды mov с "прямым" порядком аргументов

Примеры;
-> [variable1],eax
eax -> [variable2]

В первом варианте - это как бы временный алиас переменной в регистре
Второй случай классическая пересылка
Могут быть сравнения
eax = ebx
eax ? ebx ; тестирование
eax u= ebx ; беззнаковое сравнение

P.S. Тут я не первоизобретатель. Подобный синтаксис использован в ассемблере для AVR проекта Алгоритм Билдер
Интересно также рассмотреть ранее дискутируемый вариант на тему ассемблера - ни много - ни мало Компилирующий ассемблер
цель разбавить команды-слова различными знаковыми "сокращёнными" представлениями - эргономика восприятия кода должна повыситься

'Высокоуровневые" варианты циклов ветвлений тоже вполне возможны.
Пример (с которым близко знаком) использования и расширения ассемблера в проекте
ff303 для AVR see ДопКоманды.rar
(в моём варианте для PDP-11 )
(Также можно и для PC asm сделать)

Re: Синтаксис ассемблера

Posted: Wed Feb 05, 2014 8:51 pm
by 0CodErr
Kopa wrote:вариант HLA ассемблера для использования "неподходит"
Если ты про HLA by Randall Hyde, то он-то как раз и подходит. Есть возможность транслировать исходник в FASM, NASM, MASM, GAS.

Re: Синтаксис ассемблера

Posted: Wed Feb 05, 2014 8:54 pm
by Kopa
0CodErr wrote:
Kopa wrote:вариант HLA ассемблера для использования "неподходит"
Если ты про HLA by Randall Hyde, то он-то как раз и подходит. Есть возможность транслировать исходник в FASM, NASM, MASM, GAS.
С какими-то ключами? (не в курсе)