1. Если вы только начинаете программировать на ассемблере и не знаете с чего начать, тогда попробуйте среду разработки ASM Visual IDE
    (c) на правах рекламы
    Скрыть объявление

Однокомандный dzen-процессор ;)

Тема в разделе "WASM.ZEN", создана пользователем Black_mirror, 5 фев 2005.

  1. Black_mirror

    Black_mirror Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2002
    Сообщения:
    1.036
    Код (Text):
    1. Число регистров - 2^k (k должно быть не менее 3, наверное :)
    2.     (к ним также относится счётчик команд ip)
    3. Архитектура - трехадресная
    4. Число команд - одна единственная (условное вычитание)
    5. Число флагов - один (f - флаг переполнения)
    6. Разрядность машинного слова - 2+3*k
    7. Максимально адресуемое число ячеек памяти - 2^(2+3*k)
    8.  
    9. Все обрабатываемые числа считаются положительными,
    10. -1=11...1111 - максимальное число
    11.  
    12. Формат команды:
    13.  
    14. тип
    15. 00 R1 R2 R3 - csub R1,R2,R3 if f=0 then R1:=R2-R3,f:=R3>R2 else f=0
    16. 01 R1 R2 R3 - csub R1,R2,[R3]   if f=0 then R1:=R2-[R3],f:=[R3]>R2 else f=0
    17. 10 R1 R2 R3 - csub R1,[R2],R3   if f=0 then R1:=[R2]-R3,f:=R3>[R2] else f=0
    18. 11 R1 R2 R3 - csub [R1],R2,R3   if f=0 then [R1]:=R2-R3,f:=R3>R2 else f=0
    19.  
    20. R1,R2,R3 - поля размером k бит, вся команда занимает одну ячейку памяти
    21.  
    22. Основной цикл:
    23. Проверить флаг
    24.     если f=0
    25.         1) считать команду из памяти
    26.         2) если тип команды 01 или 10 - считать операнд из памяти
    27.         3) вычислить разность и установить флаг при переполнении
    28.         4) записать результат в приёмник и увеличить счетчик команд
    29.         если он(ip) не является приёмником данной команды       
    30.     иначе
    31.         сбросить флаг
    32.     перейти к началу
    33.  
    34. При включении питания или поступлении сигнала сброса все регистры и флаг
    35. переполнения обнуляются, и начинает выполняться команда расположеная по
    36. нулевому адресу.
    37.  
    38. Примеры(предполагается что в начале флаг переполнения сброшен)
    39.  
    40. 1) обнуление регистра
    41.  
    42. csub r,r,r; ;r=0
    43.  
    44. 2) загрузка в регистр единицы
    45.  
    46. csub r,r,r  ;r=0
    47. csub r,ip,r ;r=$(адрес этой команды)
    48. csub r,ip,r     ;r=1
    49.  
    50. 3) сложение регистров a и b
    51.  
    52. csub r,r,r      ;r=0
    53. csub b,r,b  ;b=-b
    54. csub r,r,r  ;при b>0 эта команда не выполяется
    55. csub a,a,b  ;a=a-(-b)
    56. csub r,r,r  ;при -b>a эта команда не выполяется
    57.  
    58. 4) проверка числа на 0
    59.  
    60. csub z,z,z
    61. csub z,z,r
    62. csub <- эта команда будет выполнена если r=0
    63.  
    64. 5) загрузка из памяти
    65.  
    66. csub z,z,z
    67. csub r,[m],z
    68.  
    69. 6) сохранение в памяти
    70.  
    71. csub z,z,z
    72. csub [m],r,z
    73.  
    74. 7) деление числа в регистре a на число в регистре b, с записью частного в
    75. регистр d и остатка в регистр a
    76.  
    77. #1 csub z,z,z   ;z=0
    78. #2 csub m,ip,z  ;m=$
    79. #3 csub m,m,ip  ;m=-1
    80. #4 csub z,z,z   ;никогда не исполняется
    81. #5 csub d,d,d   ;d=0
    82. #6 csub l,ip,m  ;l=адрес следующей команды
    83. ;начало цикла
    84. #7 csub d,d,m   ;d=d-(-1) не исполняется при первом проходе цикла
    85. #8 сsub z,z,z  ;исполняется только при первом прохорде
    86. #9 csub a,a,b   ;a=a-b
    87. #10 csub ip,l,z ;ip=l-z, то есть переход в начало цикла если в предыдущей
    88.         ;команде не произошло переполнение
    89. ;далее довычисление остатка
    90. #11 csub z,z,b  ;z=z-b
    91. #12 csub z,z,z  ;на результат предыдущей команды не влияет
    92. #13 csub a,a,b  ;формирование остатка
    93.  
    94.  
    95. Работа алгоритма:
    96.  
    97. пусть a=7 и b=3
    98. #1 z=0 f=0
    99. #2 m=2 f=0
    100. #3 m=-1 f=1 -1=11...1111
    101. #5 d=0 f=0
    102. #6 l=7 f=1
    103.  
    104. #8 z=0 f=0
    105. #9 a=4 f=0
    106. #10 ip=7 f=0
    107.  
    108. #7 d=1 f=1
    109. #9 a=1 f=0
    110. #10 ip=7 f=0
    111.  
    112. #7 d=2 f=1  частное уже вычислено
    113. #9 a=-2 f=1     -2=11...1110
    114.  
    115. #11 z=-3 f=1    -3=11...1101
    116. #13 a=1 f=0 остаток тоже вычислен
    117.  




    Вот такие идеи иногда приходят в голову ...

    Нужно будет сделать эмулятор ...
     
  2. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    Супер!!! (я пока пошёл за бутылкой, что бы разобраться :).



    Вот только как загружать данные в регистры безо всяких трюков ?



    если k = 4, то разрядность слова будет 14 бит.

    (это не совсем удобно при эмуляции на x86, т.к. 2 бита будут пропадать)

    Может быть увеличить чуть-чуть слово, расширив поле команды добавив ещё один бит?

    этот бит будет безусловно прибавляться к IP перед шагом 2 и можно будет хранить непосредственные операнды за кодом команды, адресуясь к ним по IP.
     
  3. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Black_mirror

    Да, круто :)))



    Даешь эмулятор до конца квАртала!!! :)))
     
  4. Black_mirror

    Black_mirror Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2002
    Сообщения:
    1.036
    S_T_A_S_



    Зато если k = 10 ...






    Код (Text):
    1. Добавлять для этого непосредственный операнд не нужно:
    2.  
    3. если в регистрах есть 0 и -1(если нет, придется их получить)
    4.  
    5. csub rc,ip,-1   ;f=1, адрес этой команды не должен быть равен -1
    6. const       ;эта ячейка пропускается
    7. csub rc,[rc],0  ;rc=const
    8.  
    9. или можно делать так если констант нужно много:
    10.  
    11. #0 csub rz,rz,rz    ;rz=0
    12. #1 csub r1,ip,rz    ;r1=1
    13. #2 csub rc,rz,r1    ;rс=-1=11...1111, f=1
    14. #3 const_start      ;адрес последней ячейки области констант
    15. #4 csub rc,ip,r1    ;rс=3
    16. #5 csub rc,[rc],rz  ;rс=const_start
    17.  
    18. ;константы
    19. #const_start-N  constN
    20.         constN-1
    21.         ...
    22.         const1  
    23. #const_start    const0
    24.  
    25. rz - регистр содержащий 0
    26. r1 - регистр содержащий 1
    27. rc - указатель на блок констант
    28. rx - некоторый регистр
    29.  
    30. ну а там где нужна константа пишем
    31.  
    32. csub rx,[rc],rz ;загружаем константу
    33. csub rc,rc,r1   ;переходим к следующей константе
    34.  
    35. далее вместо регистров с константами будет просто записано их(констант) значение
    36.  
    37.  
    38. Для циклов перед списком констант размещается указатель(перед входом в цикл
    39. адрес этой ячейки хранится в регистре rc) на начало области
    40. констант цикла, также этот указатель нужно будет поместить последней константой
    41. цикла чтобы он перезагружася при повторных итерациях.
    42.  
    43. L:  csub rc,[rc],0  ;установка указателя на первую константу цикла
    44.    
    45.     ...
    46.  
    47.     csub rx,[rc],0  ;загрузка первой константы
    48.     csub rc,rc,1   
    49.  
    50.     ...
    51.  
    52.     csub rx,[rc],0  ;загрузка последней константы
    53.             ;скорее всего равной метке L
    54.     csub rc,rc,1   
    55.  
    56.     ...
    57.  
    58.     csub <- тут должна быть проверка условия
    59.     csub ip,L,0 ;переход в начало цикла
    60.    
    61.     csub rc,rc,1    ;пропуск указателя на начало констант цикла
    62.  
    63. Для цикла использующего константы A,B и C соответствующий участок списка
    64. констант будет выглядеть так:
    65. #E
    66.    P
    67.    C
    68.    B
    69. #P A
    70. #S P
    71. Такой список будем представлять так:
    72. S:{P,P:{A,B,C,P}},E:...
    73. вложенные скобки не обязательны, а служат для
    74. лучшего отражения связи со структурой программы
    75.  
    76. В начале r2=S указывает на ячейку содержащую P
    77. Первая команда цикла загружает в r2 P, то есть адрес константы A
    78. В конце интерации r2 снова указывает на ячейку содержащую P
    79. Если переход будет выполнен, то в r2 будет загружено P
    80. иначе мы выходим из цикла и делаем r2 равным E,
    81. то есть началу следующего блока констант
    82.  
    83.  
    84.  
    85.  
    86. Размышления о вызовах процедур привели к выводу, что стоит малость изменить
    87. архитектуру: отобразить регистры на адресное пространство, чтобы без
    88. самомодифицирующегося кода можно было реализовать процедуры типа
    89. "сохранить регистры с R3 по R5 в области памяти на которую указывает R2".
    90.  
    91. Теперь карта памяти будет выглядеть так:
    92. 0: R0, он же ip, то есть счетчик команд
    93. 1: R1 - первый регистр
    94. 2: R2
    95. ...
    96. 2^k-1: Rn - последний регистр
    97. 2^k: - нулевая ячейка памяти ;)
    98. 2^k+1: - первая ячейка памяти
    99. ...
    100. 2^(2+k*3): - последняя ячейка памяти
    101.  
    102. А выполнение программы будет начинаться с адреса 2^k.
    103.  
    104.  
    105.  
    106. Еще несколько примеров(предполагается что константы уже есть в регистрах)
    107.  
    108. -1=max=11...1111
    109.  
    110. 8) побитовое отрицание
    111.  
    112. csub r,max,r    ;r=11...1111-r
    113.  
    114. 9) проверка старшего бита r и переход на метку L если бит сброшен
    115.  
    116. csub t,max,r    ;t=~r=max-r
    117. csub t,t,r  ;t=~r-r=max-r-r=max-2r=~2r
    118. csub ip,L,0 ;переход на метку L
    119.  
    120. 10) проверка старшего бита r и переход на метку L если бит установлен
    121.  
    122. csub t,-1,r ;t=~r=max-r
    123. csub t,r,t  ;t=r-~r=r-(max-r)
    124. csub ip,L,0 ;переход на метку L
    125.  
    126. 11) циклический сдвиг влево(от младших бит к старшим)
    127.  
    128. csub t,-1,r ;t=~r=max-r
    129. csub r,r,t  ;r=r-~r=r-(max-r)=2r+1
    130. csub r,r,1  ;вычесть 1 если старший бит r был сброшен
    131.  
    132. объединив несколько циклических сдвигов и один из пунктов 9) или 10)
    133. можно получить переход по состоянию любого бита
    134.  
    135. 12) логический сдвиг влево
    136.  
    137. csub t,-1,r ;t=~r=max-r
    138. csub r,r,t  ;r=r-~r=r-(max-r)=2r+1
    139. nop             ;например csub rz,rz,rz   где rz=0 перед выполнением
    140. csub r,r,1  ;r=2r+1-1=2r




    _DEN_



    После защиты как раз месяц останется 8)
     
  5. EvilsInterrupt

    EvilsInterrupt Постигающий азы дзена

    Публикаций:
    0
    Регистрация:
    28 окт 2003
    Сообщения:
    2.428
    Адрес:
    Russia
    А как бы вы это чудо реализовывали бы?
     
  6. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Black_mirror

    В IP можно писать? Чтобы jmp делать?
     
  7. Black_mirror

    Black_mirror Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2002
    Сообщения:
    1.036
    EvilsInterrupt

    Для начала ассемблер и програмный эмулятор с интерфейсом типа TD, а потом можно подумать о железе(ПЛИС например) и высокоуровневых языках.



    _DEN_

    Конечно можно, по другому его и не сделать.
     
  8. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    Black_mirror >




    Это хорошая мысль.

    Может быть принять за IP на R0, а RN, а при "инициализации" процессора заполнять каждый регистр значением его номера?

    Так получим некоторые нужные константы (0, 1) и заодно счётчик команд будет нуказывать на нужное место в памяти.
     
  9. EvilsInterrupt

    EvilsInterrupt Постигающий азы дзена

    Публикаций:
    0
    Регистрация:
    28 окт 2003
    Сообщения:
    2.428
    Адрес:
    Russia
    Black_mirror
    Ты его забросил?
     
  10. Proteus

    Proteus Member

    Публикаций:
    0
    Регистрация:
    19 июн 2004
    Сообщения:
    344
    Адрес:
    Russia
    Между регистрами и ячейками памяти принципиальной разницы нет. Можно одно убрать, например регистры. А память поделить на три области, константы, память и порты.
    Правда команды чуток рабухнут.....