Обратная польская запись

Тема в разделе "WASM.BEGINNERS", создана пользователем assch, 4 сен 2021.

  1. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    203
    Код (ASM):
    1.  
    2. В интернете очень много написано об обратной польской записи
    3. это запись где арифметический оператор записывается
    4. не между операндами а после них
    5. например утрированное выражение:
    6.  
    7. 3*(40-(2+3)*4/2)
    8.  
    9. последовательно в лоб это выражение не решить
    10. потому что надо сначала выполнять приоритетные операции
    11. для этого 100 лет тому назад (если я не ошибаюсь)
    12. придумали особый вид записи выражения
    13. которое потом последовательно можно легко решить
    14. следуя определённому алгоритму
    15. выражение записанное выше
    16. переводится в обратную польскую запись
    17.  
    18. 3 40 2 3 + 4 * 2 / - *
    19.  
    20. следуя по записи надо дойти до арифметической команды
    21. и произвести это действие между двумя операндами
    22. которые стояли перед этой арифметической командой
    23. потом эти два операнда убираются из записи
    24. а вместо записи этой арифметической команды
    25. прописывается результат выполнения
    26. в квадратных скобках справо полученный результат
    27.  
    28. 3 40 2 3 + 4 * 2 / - *   -->   3 40 [5] 4 * 2 / - *
    29. 3 40 [5] 4 * 2 / - *   -->   3 40 [20] 2 / - *
    30. 3 40 [20] 2 / - *   -->   3 40 [10] - *
    31. 3 40 [10] - *   -->   3 [30] *
    32. 3 [30] *   -->   [90]
    33.  
    34. результат - 90
    35.  
    36. с получением результата от обратной польской записи всё понятно
    37. а вот как из стандартной записи выражения
    38. получить саму эту обратную польскую запись это вопрос
    39. в интернете на разных площадках иногда вроде бы объясняют как
    40. но то ли не договаривают то ли сами не всё знают не понятно
    41. даже есть онлайн переводчики из стандартного выражения
    42. в обратную польскую запись но они справляются не со всеми выражениями
    43. хотя я не исключаю что где нибудь есть более точная информация
    44.  
    45. Вопрос к тем кто в теме
    46. Кто нибудь занимался этим вопросом
    47. Или кто то даст ссылку где есть более полные объяснения
    48. как правильно перевести выражение в обратную польскую запись
    49.  
     
  2. vitokop

    vitokop Member

    Публикаций:
    0
    Регистрация:
    20 май 2006
    Сообщения:
    48
    В.Н.Лебедев Введение в системы программирования. М.Статистика. 1975
    стр.134 и далее...
    так нас учили...
     
  3. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    Так а что сложного тут? Все стековые виртуальные машины (CLR, JVM, CPython и тд) так работают, не говоря уже о языках типа Форта или Фактора. Просто число - кладет это число на стек, оператор - берет с верхушки стека два числа, применяет к ним оператор и результат кладет на верхушку стека. Вопрос то какой? И я не знаю, как можно не справляться со всеми выражениями. Приведи пример, все выражения можно представить в такой записи. И еще, закаким тебе вообще это нужно в 2021 году?
     
  4. vitokop

    vitokop Member

    Публикаций:
    0
    Регистрация:
    20 май 2006
    Сообщения:
    48
    не забываем:
    приоритеты операций, скобки, унарные операции...
    тов. В.Н.Лебедев все растолковал..
     
  5. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    203
    под обычными выражениями я имел ввиду пример описанный выше

    3*(40-(2+3)*4/2)

    а вот если его немного усложнить например добавить минус перед скобкой (2+3)

    3*(40--(2+3)*4/2)

    то есть надо не только раскрыть скобки (2+3) а потом ещё надо у этого результата поменять знак

    vitokop спасибо за наводку почитаю
     
  6. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.792
  7. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    203
    Код написал на masm32
    постарался ничего не упустить
    для быстроты только для обычных операций (+ - * /)
    но при желании можно дополнить какими нибудь битовыми операциями
    так же добавил операцию смены знака после раскрытия скобок
    что к моему удивлению почему то нет в онлайн конверторах
    на просторах интернета или может быть мне просто попались такие
    Суть проста если прописать символ минуса перед скобкой
    то по сути это будет означать что после раскрытия скобок
    у этого результата нужно поменять знак
    для этого я произвольно задействовал символ решётки - #
    разница только в том что при обработки обратной польской записи
    при встрече обычной арифметической операции нужно задействовать
    два предпоследних операнда а при встрече символа решётки - #
    нужно задействовать только один предпоследний операнд
    по сути у этого операнда сменить знак командой ассемблера (neg)
    Код (ASM):
    1.  
    2. ;---------------------------------------------------------------------
    3. ;---------------------------------------------------------------------
    4. ;---------------------------------------------------------------------
    5. .data
    6. txt db "3*-(40-(2+3)*4/2)+2"
    7. tmp dd 0
    8. .data?
    9. buf dd 256 dup(?)
    10. .code
    11. ;---------------------------------------------------------------------
    12. ;---------------------------------------------------------------------
    13. ;---------------------------------------------------------------------
    14. push esi
    15. push edi
    16. ;--------------------------------------------
    17. push 0
    18. push offset tmp
    19. push offset txt
    20. push 0
    21. call MessageBox
    22. ;--------------------------------------------
    23. lea edi,buf
    24. lea esi,txt
    25. xor edx,edx
    26. ;--------------------------------------------
    27. Loc__exp:
    28. ;--------------------------------------------
    29. mov eax,dword ptr [esi]
    30. ;--------------------------------------------
    31. ;--------------------------------------------
    32. ;--------------------------------------------
    33. .if al == 0
    34. Loc__nul:
    35. pop eax
    36. ;---------------------------
    37. .if eax == 28h ; "("
    38. .elseif eax
    39. mov word ptr [edi],0A0Dh
    40. add edi,2
    41. movzx eax,al
    42. mov byte ptr [edi],al
    43. inc edi
    44. jmp Loc__nul
    45. .endif
    46. ;---------------------------
    47. mov dword ptr [edi],0
    48. ;--------------------------------------------
    49. ;--------------------------------------------
    50. ;--------------------------------------------
    51. .elseif ax == 282Dh && edx == 0 ; "-("
    52. push 28h                        ; "("
    53. push 23h                        ; "#"
    54. inc esi
    55. jmp Loc__inc
    56. ;--------------------------------------------
    57. ;--------------------------------------------
    58. ;--------------------------------------------
    59. .elseif ax == 282Bh && edx == 0 ; "+("
    60. inc esi
    61. push 28h                        ; "("
    62. jmp Loc__inc
    63. ;--------------------------------------------
    64. ;--------------------------------------------
    65. ;--------------------------------------------
    66. .elseif al == 2Bh || al == 2Dh ; или  "+"  или  "-"
    67. ;---------------------------
    68. .if edx == 0
    69. jmp Loc__rec
    70. .endif
    71. ;---------------------------
    72. mov word ptr [edi],0A0Dh
    73. add edi,2
    74. mov cl,byte ptr [esp]
    75. ;---------------------------
    76. .if cl == 2Bh || cl == 2Dh || cl == 2Ah || cl == 2Fh ; "+" или "-" или "*" или "/"
    77. pop ecx
    78. mov byte ptr [edi],cl
    79. mov word ptr [edi+1],0A0Dh
    80. add edi,3
    81. movzx eax,al
    82. push eax
    83. ;---------------------------
    84. .else
    85. movzx eax,al
    86. push eax
    87. .endif
    88. ;---------------------------
    89. xor edx,edx
    90. jmp Loc__inc
    91. ;--------------------------------------------
    92. ;--------------------------------------------
    93. ;--------------------------------------------
    94. .elseif al == 2Ah || al == 2Fh ; "*" или "/"
    95. mov word ptr [edi],0A0Dh
    96. add edi,2
    97. mov cl,byte ptr [esp]
    98. ;---------------------------
    99. .if cl == 2Ah || cl == 2Fh    ; "*" или "/"
    100. pop ecx
    101. mov byte ptr [edi],cl
    102. mov word ptr [edi+1],0A0Dh
    103. add edi,3
    104. movzx eax,al
    105. push eax
    106. ;---------------------------
    107. .else
    108. movzx eax,al
    109. push eax
    110. .endif
    111. ;---------------------------
    112. xor edx,edx
    113. jmp Loc__inc
    114. ;--------------------------------------------
    115. ;--------------------------------------------
    116. ;--------------------------------------------
    117. .elseif al == 28h ; "("
    118. xor edx,edx
    119. movzx eax,al
    120. push eax
    121. jmp Loc__inc
    122. ;--------------------------------------------
    123. ;--------------------------------------------
    124. ;--------------------------------------------
    125. .elseif al == 29h ; ")"
    126. Loc__skb:
    127. pop eax
    128. ;---------------------------
    129. .if eax != 28h            ; "("
    130. mov word ptr [edi],0A0Dh
    131. mov byte ptr [edi+2],al
    132. add edi,3
    133. jmp Loc__skb
    134. .endif
    135. ;---------------------------
    136. jmp Loc__inc
    137. ;--------------------------------------------
    138. ;--------------------------------------------
    139. ;--------------------------------------------
    140. .else
    141. ;---------------------------
    142. Loc__rec:
    143. ;---------------------------
    144. mov edx,1
    145. mov byte ptr [edi],al
    146. inc edi
    147. ;---------------------------
    148. Loc__inc:
    149. ;---------------------------
    150. inc esi
    151. jmp Loc__exp
    152. .endif
    153. ;--------------------------------------------
    154. ;--------------------------------------------
    155. ;--------------------------------------------
    156. push 0
    157. push offset tmp
    158. push offset buf
    159. push 0
    160. call MessageBox
    161. @dBox &buf
    162. ;---------------------------------------------
    163. pop edi
    164. pop esi
    165. ;---------------------------------------------------------------------
    166. ;---------------------------------------------------------------------
    167. ;---------------------------------------------------------------------
    168.  
    Всем спасибо за участие
     
  8. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.995
    Конструкции типа
    Код (ASM):
    1. .if ...
    2. jmp .label
    3. .elseif ...
    4. jmp .label
    5. .endif
    избыточные. Если у тебя внутри кейса безусловный переход, надо закрывать .if и открывать новый.
     
  9. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    203
    Посмотрите код повнимательней
    если я уберу эти безусловные переходы то при встрече первой же арифметической операции алгоритм выйдет из перебора символов выражения
    потому что вы наверное просто не заметили что переход на начало просмотра следующего символа у меня стоит именно в теле оператора - .else
    --- Сообщение объединено, 4 сен 2021 ---
    Не большое дополнение для тех кому это конечно интересно
    не критично но желательно сначала обрабатываемый массив выражения
    прогнать через алгоритм который пересоберёт массив выражения естественно в новый буфер
    чтобы убрать из массива все пробелы если конечно они там есть
    попутно проверив правильное ли количество скобок прописано в выражении
    то есть чтобы у каждой открывающей скобки была закрывающая скобка
    сделать это не трудно достаточно поставить счётчик по принципу
    плюс открывающая скобка минус закрывающая скобка если на выходе на счётчике ноль значит всё в порядке
    если счётчик плюсовой значит не хватает скобок а если счётчик ушёл в минус значит по ошибке
    закрывающую скобку поставили впереди только этот минус счётчика нужно ловить не в конце
    а сразу же как только счётчик ушёл в минус

    После этот уже пересобранный массив выражения можно скормить коду прописанному выше
     
  10. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.995
    Код (ASM):
    1. .elseif ax == 282Bh && edx == 0 ; "+("
    2. inc esi
    3. push 28h                        ; "("
    4. jmp Loc__inc
    5. ;--------------------------------------------
    6. ;--------------------------------------------
    7. ;--------------------------------------------
    8. .elseif al == 2Bh || al == 2Dh ; или  "+"  или  "-"
    У меня вообще-то буквально написано было что надо сделать. Это про внимательность. .elseif это безусловный переход к .endif'у и следующие за ним проверки. Сам этот безусловный переход никакого смысла не имеет, потому что будет следовать за выставленным вручную безусловным переходом.
     
  11. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    203
    я специально убрал лишнее
    Код (ASM):
    1.  
    2. Loc__exp:
    3. mov eax,dword ptr [esi]
    4. .if al == 0
    5. ...
    6. .elseif ax == 282Bh && edx == 0 ; "+("
    7. inc esi
    8. push 28h
    9. jmp Loc__inc
    10. .else
    11. Loc__inc:
    12. inc esi
    13. jmp Loc__exp
    14. .endif
    15.  
    теперь посмотрите что будет если убрать как вы считаете
    лишним безусловный переход - jmp Loc__inc
    алгоритм просто выйдет за пределы - .endif
    и соответственно код не выполнит свою задачу до конца
    вы пишите:

    .elseif это безусловный переход к .endif и следующие за ним проверки

    а где вы увидели после .endif какие то проверки их там нет
    в .elseif прописан безусловный переход на метку в теле - .else
    подчёркиваю три раза красным на метку в теле - .else
    и уже из этого тела идёт безусловный переход на начало
     
  12. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.995
    Да, понял уже, что воткнуть похожий безусловный переход в конце первого обработчика мешает какая-то непреодолимая сила, не действующая во 2,3,4,5 и 6м. Докапываюсь, но просто не мог пройти мимо.
    У меня получился точно такой же алгоритм, но на 24 байта дешевле и в основном за счет убранных бесполезных переходов, которые никогда не будут выполнены:
    Код (ASM):
    1.  
    2.             push esi
    3.             push edi
    4.             push 0
    5.             push tmp
    6.             push txt
    7.             push 0
    8.             call [MessageBox]
    9.             lea edi,[buf]
    10.             lea esi,[txt]
    11.             xor edx,edx
    12.             Loc__exp:
    13.             mov eax,dword[esi]
    14.             test al,al
    15.             .if ZERO?
    16.                 Loc__nul:
    17.                 pop eax
    18.                 .if eax<>28h & eax
    19.                     mov word[edi],0A0Dh
    20.                     add edi,2
    21.                     movzx eax,al
    22.                     mov byte[edi],al
    23.                     inc edi
    24.                     jmp Loc__nul
    25.                 .endif
    26.                 mov dword[edi],0
    27.                 jmp Loc__done
    28.             .endif
    29.             test edx,edx
    30.             .if ZERO? & ax='-('
    31.                 push 28h
    32.                 push 23h
    33.                 inc esi
    34.                 jmp Loc__inc
    35.             .endif
    36.             test edx,edx
    37.             .if ZERO? & ax='+('
    38.                 inc esi
    39.                 push 28h
    40.                 jmp Loc__inc
    41.             .endif
    42.             .if al='+' | al='-'
    43.                 test edx,edx
    44.                 je Loc__rec
    45.                 mov word[edi],0A0Dh
    46.                 add edi,2
    47.                 mov cl,byte[esp]
    48.                 .if cl = '+' | cl = '-' | cl = '*' | cl = '/'
    49.                     pop ecx
    50.                     mov byte[edi],cl
    51.                     mov word[edi+1],0A0Dh
    52.                     add edi,3
    53.                     movzx eax,al
    54.                     push eax
    55.                 .else
    56.                     movzx eax,al
    57.                     push eax
    58.                 .endif
    59.                 xor edx,edx
    60.                 jmp Loc__inc
    61.             .endif
    62.             .if al='*' | al='/'
    63.                 mov word[edi],0A0Dh
    64.                 add edi,2
    65.                 mov cl,byte[esp]
    66.                 .if cl = 2Ah | cl = 2Fh
    67.                     pop ecx
    68.                     mov byte[edi],cl
    69.                     mov word[edi+1],0A0Dh
    70.                     add edi,3
    71.                     movzx eax,al
    72.                     push eax
    73.                 .else
    74.                     movzx eax,al
    75.                     push eax
    76.                 .endif
    77.                 xor edx,edx
    78.                 jmp Loc__inc
    79.             .endif
    80.             .if al = '('
    81.                 xor edx,edx
    82.                 movzx eax,al
    83.                 push eax
    84.                 jmp Loc__inc
    85.             .endif
    86.             .if al = ')'
    87.                 Loc__skb:
    88.                 pop eax
    89.                 .if eax <> '('
    90.                     mov word[edi],0A0Dh
    91.                     mov byte[edi+2],al
    92.                     add edi,3
    93.                     jmp Loc__skb
    94.                 .endif
    95.                 jmp Loc__inc
    96.             .endif
    97.             Loc__rec:
    98.             mov edx,1
    99.             mov byte[edi],al
    100.             inc edi
    101.             Loc__inc:
    102.             inc esi
    103.             jmp Loc__exp
    104.             Loc__done:
    105.             push 0
    106.             push tmp
    107.             push buf
    108.             push 0
    109.             call [MessageBox]
    110.             ;@dBox &buf
    111.             pop edi
    112.             pop esi
     
  13. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    Ну это зависит от приоритета операторов и ЯП, но я не вижу причин, почему это не должно корректно парситься. Унарный и бинарный минус как бы своего рода разные операторы.
     
  14. GRAFik

    GRAFik Active Member

    Публикаций:
    0
    Регистрация:
    14 мар 2020
    Сообщения:
    352
    Спасибо за интересный тред.

    f13nd, проверьте пожалуйста ваш вариант кода, а-то вариант assch в MASM скомпилировался, а ваш ни в MASM, ни в FASM не могу скомпилировать. Мне для общего развития, если что. Хотел вникнуть сравнить ваш вариант и assch'а.

    P.S. У варианта assch'а 161 строку нужно закомментировать ( 161 @dBox &buf ), а-то MASMу не нравится.
     
  15. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    203
    Посмотрел код - f13nd
    разница только в том что вы переход на начало просмотра следующего символа
    разместили в конце после операторов (макросов) условного сравнения
    просто для примера сильно утрированно:
    Код (ASM):
    1.  
    2. ;--------------------------
    3. Loc__exp:
    4. ;--------------------------
    5. .if al
    6. jmp Loc__inc
    7. .endif
    8. ;--------------------------
    9. .if al
    10. jmp Loc__inc
    11. .endif
    12. ;--------------------------
    13. Loc__inc:
    14. jmp Loc__exp
    15. ;--------------------------
    16.  
    я же разместил этот переход не в конце а в теле - .else
    так же просто для примера сильно утрированно:
    Код (ASM):
    1.  
    2. ;--------------------------
    3. Loc__exp:
    4. ;--------------------------
    5. .if al
    6. jmp Loc__inc
    7. ;--------------------------
    8. .elseif al
    9. jmp Loc__inc
    10. ;--------------------------
    11. .else
    12. Loc__inc:
    13. jmp Loc__exp
    14. .endif
    15. ;--------------------------
    16.  
    оптимизация в вашем случае оптимизация байт-кода дело конечно хорошее
    я тоже иногда задумываюсь об этом но это уже процесс отладки
    я же свой код выставил как первый черновой вариант
    можно ли мой код оптимизировать да конечно наверное можно
    для этого нужно просто проанализировать код
    я же своей главной целью ставил
    чтобы алгоритм просто выполнял свою задачу
    на мой взгляд (который конечно же может быть ошибочным)
    оптимизацию байт-кода не всегда нужно ставить во главе угла
    например если вы загляните под капот какой нибудь API функции
    вы просто ужаснётесь сколько там перегруженного байт-кода
    и дело даже не в проверках на возможные ошибки
    просто инженеры-программисты которые разрабатывают алгоритмы
    на перегруженность байт-кода не смотрят
    потому что на данный момент времени это уже далеко не актуально
    их главная цель это скорость выполнения алгоритма кода

    я кстати проверил ваш код и например у выражения с унарным минусом

    -(2+3)

    он выдал не корректные данные

    -2
    3
    +

    которые в результате дадут (1)

    обратная польская запись для этого выражения должна быть

    2
    3
    +
    #

    чтобы получился правильный результат (-5)

    я может быть что то напутал
    потому что синтаксис платформ у нас немного разные
    на всякий случай если я не ошибся проверьте свой код
    --- Сообщение объединено, 5 сен 2021 ---
    По поводу строки (161) @dBox &buf на которую обратил внимание - GRAFik
    я просто забыл её убрать из кода
    это мой макрос - @dBox
    который при отладке кода показывал мне дамп по адресу - buf
     
  16. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.995
    Да нет никакого тела, этими переходами в соседний кейс ты ломаешь композицию .if/.elseif/.endif, и видимо используешь их тупо для удобства. Отсюда и кривизна получившегося кода - эти макросы просто не задуманы чтобы использовать их так.
     
  17. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    203
    У нас с вами разные представления о ветвлении условных конструкций
    Особенно умиляют ваши смелые высказывания что нет ни какого тела у этих операторов
    но по сути в этом нет ничего страшного так как каждый сам делает свой выбор

    Вы исправили ошибку в своём коде с унарным минусом?
    или пологаете что и так сойдёт
    --- Сообщение объединено, 5 сен 2021 ---
    обнаружил падение стека на четыре байта
    чтобы этого не происходило
    лучше использовать немного подправленный код
    Код (ASM):
    1.  
    2. ;---------------------------------------------------------------------
    3. ;---------------------------------------------------------------------
    4. ;---------------------------------------------------------------------
    5. .data
    6. txt db "3*-(40-(2+3)*4/2)+2"
    7. tmp dd 0
    8. .data?
    9. buf dd 256 dup(?)
    10. .code
    11. ;---------------------------------------------------------------------
    12. ;---------------------------------------------------------------------
    13. ;---------------------------------------------------------------------
    14. push esi
    15. push edi
    16. ;--------------------------------------------
    17. push 0
    18. push offset tmp
    19. push offset txt
    20. push 0
    21. call MessageBox
    22. ;--------------------------------------------
    23. lea edi,buf
    24. lea esi,txt
    25. xor edx,edx
    26. push 0 ; положим в стек нулевую метку
    27. ;--------------------------------------------
    28. Loc__exp:
    29. ;--------------------------------------------
    30. mov eax,dword ptr [esi]
    31. ;--------------------------------------------
    32. ;--------------------------------------------
    33. ;--------------------------------------------
    34. .if al == 0
    35. Loc__nul:
    36. pop eax
    37. ;---------------------------
    38. .if eax ; пока не встретится нулевая метка пишем в буфер
    39. mov word ptr [edi],0A0Dh
    40. add edi,2
    41. movzx eax,al
    42. mov byte ptr [edi],al
    43. inc edi
    44. jmp Loc__nul
    45. .endif
    46. ;---------------------------
    47. mov dword ptr [edi],0
    48. ;--------------------------------------------
    49. ;--------------------------------------------
    50. ;--------------------------------------------
    51. .elseif ax == 282Dh && edx == 0 ; "-("
    52. push 28h                        ; "("
    53. push 23h                        ; "#"
    54. inc esi
    55. jmp Loc__inc
    56. ;--------------------------------------------
    57. ;--------------------------------------------
    58. ;--------------------------------------------
    59. .elseif ax == 282Bh && edx == 0 ; "+("
    60. inc esi
    61. push 28h                        ; "("
    62. jmp Loc__inc
    63. ;--------------------------------------------
    64. ;--------------------------------------------
    65. ;--------------------------------------------
    66. .elseif al == 2Bh || al == 2Dh ; или  "+"  или  "-"
    67. ;---------------------------
    68. .if edx == 0
    69. jmp Loc__rec
    70. .endif
    71. ;---------------------------
    72. mov word ptr [edi],0A0Dh
    73. add edi,2
    74. mov cl,byte ptr [esp]
    75. ;---------------------------
    76. .if cl == 2Bh || cl == 2Dh || cl == 2Ah || cl == 2Fh ; "+" или "-" или "*" или "/"
    77. pop ecx
    78. mov byte ptr [edi],cl
    79. mov word ptr [edi+1],0A0Dh
    80. add edi,3
    81. movzx eax,al
    82. push eax
    83. ;---------------------------
    84. .else
    85. movzx eax,al
    86. push eax
    87. .endif
    88. ;---------------------------
    89. xor edx,edx
    90. jmp Loc__inc
    91. ;--------------------------------------------
    92. ;--------------------------------------------
    93. ;--------------------------------------------
    94. .elseif al == 2Ah || al == 2Fh ; "*" или "/"
    95. mov word ptr [edi],0A0Dh
    96. add edi,2
    97. mov cl,byte ptr [esp]
    98. ;---------------------------
    99. .if cl == 2Ah || cl == 2Fh    ; "*" или "/"
    100. pop ecx
    101. mov byte ptr [edi],cl
    102. mov word ptr [edi+1],0A0Dh
    103. add edi,3
    104. movzx eax,al
    105. push eax
    106. ;---------------------------
    107. .else
    108. movzx eax,al
    109. push eax
    110. .endif
    111. ;---------------------------
    112. xor edx,edx
    113. jmp Loc__inc
    114. ;--------------------------------------------
    115. ;--------------------------------------------
    116. ;--------------------------------------------
    117. .elseif al == 28h ; "("
    118. xor edx,edx
    119. movzx eax,al
    120. push eax
    121. jmp Loc__inc
    122. ;--------------------------------------------
    123. ;--------------------------------------------
    124. ;--------------------------------------------
    125. .elseif al == 29h ; ")"
    126. Loc__skb:
    127. pop eax
    128. ;---------------------------
    129. .if eax != 28h            ; "("
    130. mov word ptr [edi],0A0Dh
    131. mov byte ptr [edi+2],al
    132. add edi,3
    133. jmp Loc__skb
    134. .endif
    135. ;---------------------------
    136. jmp Loc__inc
    137. ;--------------------------------------------
    138. ;--------------------------------------------
    139. ;--------------------------------------------
    140. .else
    141. ;---------------------------
    142. Loc__rec:
    143. ;---------------------------
    144. mov edx,1
    145. mov byte ptr [edi],al
    146. inc edi
    147. ;---------------------------
    148. Loc__inc:
    149. ;---------------------------
    150. inc esi
    151. jmp Loc__exp
    152. .endif
    153. ;--------------------------------------------
    154. ;--------------------------------------------
    155. ;--------------------------------------------
    156. push 0
    157. push offset tmp
    158. push offset buf
    159. push 0
    160. call MessageBox
    161. ;---------------------------------------------
    162. pop edi
    163. pop esi
    164. ;---------------------------------------------------------------------
    165. ;---------------------------------------------------------------------
    166. ;---------------------------------------------------------------------
    167.  
     
    Последнее редактирование: 5 сен 2021
  18. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.995
    Это не представления, речь про неэффективное генерирование кода с лишними неиспользуемыми инструкциями. Ассемблер не высокоуровневый ЯП, где компилятор занимается такими вещами сам, их надо контролировать самстоятельно. А макросы просто средство. Закрывая .if после безусловного перехода ты получаешь то же самое, но без лишней инструкции. Если до зарезу надо безусловный переход в .else, просто вставляешь его вручную.
    Я не собирался под ключ делать, только показывал как код должен был быть устроен. Тем более, если он изначально содержал в себе баги, проще было бы с нуля переписать, но в этом я не вижу смысла.
    Эти фокусы с пушами-попами вообще скользкая дорожка.
     
    Последнее редактирование: 5 сен 2021
  19. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    203
    Дискусия была жаркой но в любом случае очень интересной
    Всем спасибо за участие

    PS

    Rel вначале риторически спрашивал за каким это вообще нужно в 2021 году?

    Отвечаю:

    Я когда только начинал писать коды на masm32 я естественно столкнулся с рутиной написания кода
    хотя masm32 это и не чистый ассемблер и в нём есть какие никакие высокоуровневые вшитые макросы всё равно рутина порядком надоедала
    выход как мне казалось в то время был один это писать собственные макросы
    и пошло поехало я собрал внушительную библиотеку собственных макросов которые существенно снизили рутину
    код на порядок стал компактнее да читабельность кода стала намного лучше
    но в один прекрасный момент на не очень маленьких проектах я столкнулся с тем что время сборки проекта компилятором существенно выросла
    например время доходило до 1500 миллисекунд (полторы секунды) по сути вроде бы ерунда и не смертельно главное код писался намного проще и быстрее
    но я прекрасно понимал почему это происходит а происходит это потому что существенно выросла нагрузка на компилятор из за прописанных в коде макросов
    на тот момент я уже професионально писал макросы и прекрасно знал что они могут очень многое но к сожелению не всё
    в частности нужно строго соблюдать правила синтаксиса при написании алгоритма действий в макросе
    да и ограничение употребления определённых символов в этом макросе и кстати размер данных в макросе тоже имел свой предел

    Ради интереса я этот код который был компактный но компилировался как я уже говорил 1500 миллисекунд (полторы секунды)
    я переписал не просто на masm32 а на чистом ассемблере и скормил этот код компилятору и время компила составила всего 50 миллисекунд в 30 раз быстрее
    поразмыслив я решил написать интерпретатор который бы брал мой привычный компактный код
    переводил бы его в листинг ассемблера и уже этот листинг скармливал бы основному компилятору - ml.exe
    большой плюс этого интерпретатора состоял бы и в частности в том что никаких (от слово вообще) ограничений в написании кода
    по сути хоть пиши в коде на русском главное научить интерпретатор понимать код
    и синтаксически правильно переводить это в ассемблерный листинг

    Я понимал что задача эта не тривиальная но всё же полгода тому назад я взялся за этот проект интерпретатора
    вначале работы я представлял себе что мой интерпретатор сократит время сборки в два а то и в три о то и в четыре раза дальше я даже и не мечтал
    недавно я закончил основную часть проекта остались только небольшие ньюансы
    результат превзошёл все мои ожидания тот самый проект скомпилировался за 70 миллисекунд в 22 раза быстрее
    из них первые 20 миллисекунд ушло на работу интерпретатора а остальные 50 миллисекунд потратил - ml.exe

    Я понял одно что макросы это конечно хорошо но интерпретатор гораздо лучше
    да и описывать в функциях интерпретатора поведение гораздо легче чем то же самое описывать в макросе
    разбор и вычесление выражений у меня в интерпретаторе правильное но немного другое по этому я и заинтересовался обратной польской записью
    и соответственно попробую перевести разбор и вычесление выражений в интерпретаторе на эти рельсы
    то что это будет немного проще это уже и сейчас мне понятно а насчёт скорости не знаю но думаю что медленней точно не будет

    Получилось очень длинно мне просто захотелось более подробно рассказать о том почему я заинтересовался обратной польской записью
    многие конечно не поймут по этому сразу оговорюсь что занимаюсь этим просто ради любопытства

    Интересно кто нибудь занимался подобной тематикой
     
    Последнее редактирование: 5 сен 2021
  20. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    Ну Форты, конечно, быстро парсятся, и их можно интерпретировать без дополнительных структур данных, таких как AST (абстрактное синтаксическое дерево). Но ты реально хочешь перекрутить себе яйки использованием Форта? Ты потом сам возненавидишь свой интерпретатор.