Важная информация

User Tag List

Страница 1 из 3 123 ПоследняяПоследняя
Показано с 1 по 10 из 23

Тема: try-catch на ассемблере z80

  1. #1
    Master Аватар для siril
    Регистрация
    01.02.2005
    Адрес
    perm/ru
    Сообщений
    520
    Записей в дневнике
    1
    Спасибо Благодарностей отдано 
    0
    Спасибо Благодарностей получено 
    0
    Поблагодарили
    0 сообщений
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию try-catch на ассемблере z80

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


    Вот пример на sjasmplus:
    Код:
    ; macro
    	macro border color
    		ld a,color
    		out (#fe),a
    	endm
    	
    	macro set_page pagenum
    		ld a,pagenum
    		ld bc,#7ffd
    		out (c),a
    	endm
    	macro stop
    		jp $
    	endm
    	
    ;try-catch macro {
      	macro try catch_addr
    		ld hl, catch_addr
    		call begtry_subr
      		endm
      		
    	macro epop_2
    		ld hl,(esp)
    		inc hl,hl,hl,hl
    		ld (esp),hl
    	endm
    
    	macro raise exception
    		ld sp,(esp) ; restore alt stack
    		pop de      ; pop adress of main stack
    		pop hl      ; pop adress of "catch"
    		ld (esp),sp ; store alt stack
    		ex de,hl
    		ld sp,hl
    		ld a,exception
    		ex de,hl
    		jp (hl)
    	endm
    
    	macro epush_hl_sp
    		ld   (tsp),sp ; save main stack
    		ld   sp,(esp) ; restore alt stack
    		push hl       ; push catch_adress to alt stack
    		ld   hl,(tsp) ; 
    		push hl       ; push main stack top to alt stack
    		ld   (esp),sp ; save alt stack
    		ld   sp,(tsp) ; restore main stack
    	endm
    	
    	macro endtry
    		call endtry_subr
    	endm	
    ;} try-catch macro 
    	
    	
    	device ZXSPECTRUM128
    	
    	org #6000
    init		
    	di	
    ; устанавливаем обработчик исключений на процедуру по адресу catch0
    	try catch0
    	call setup
    	call start
    ; снимаем обработчик исключений по endtry
      	endtry
      	ld a,'A' ;ok
    	ret
    ; сюда попадём по raise с любой глубины 
    catch0
    	ld a,'B' ;plan 'B' =)
    	ret
    	
    ;
    	ifused begtry_subr
    begtry_subr
     	epush_hl_sp
    	ret
    	endif
    	ifused endtry_subr
    endtry_subr
     	epop_2
    	ret
    	endif
    
    ;----------------------------------------------------------------
    setup
    		call set_screen
    		ret
    start
    		ret
    		
    set_screen
    	di
    	call cls
    	call scr_grid
    	ei
    	ret
    
    cls
    	ld hl,#4000
    	ld de,#4001
    	ld bc,#17ff
    	ld a,#00
    	ld (hl),a 
    	ldir
    	ret
    scr_grid
    
    	ld hl,#5800
    	ld de,#5802
    	ld b,12
    scr_grid_lp1
    	push bc
    	ld bc,#20
    	ld a,#0f | #40
    	ld (hl),a 
    	inc hl
    	ld a,#0f | #00
    	ld (hl),a 	
    	dec hl
    	ldir
    	
    	ld bc,#20
    	ld a,#0f | #00
    	ld (hl),a 
    	inc hl
    	ld a,#0f | #40
    	ld (hl),a 	
    	dec hl		
    	ldir
    ; вызываем исключение:
            raise 1
    
    	pop bc
    	djnz scr_grid_lp1
    	ret
    
    program_end
    ;{DATA ---------------------------------------------------------------
    data_start
    
    ;alternative exceptions stack top:
    estack_top equ #bfff
    esp dw estack_top    ;alt stack pointer storage
    tsp dw #0000         ;main stack pointer temp storage
    
    
    data_end
    ;DATA }			
    		
    		savesna "try_catch_sample.sna",#6000
        display "program lenght", /a, program_end - init
        display "data lenght", /a, data_end - data_start
    Ну, то есть идея проста: по инструкции try запомнить текущий адрес основного стека на альтернативном стеке, там же на альтернативном стеке сохранить адрес процедуры catch.

    В случае если всё ок, и мы без приключений добрались до инструкции endtry - поднимаем указатель альтернативного стека на 4 (2 байта - адрес указателя основного стека и 2 байта - адрес процедуры catch).

    По инструкции raise - забираем с альтернативного стека указатель основного стека на момент инструкции try, а также адрес процедуры catch, на которую и совершаем безусловный переход, предварительно поместив в регистр A - код исключения.

    Соответственно инструкции try-catch могут быть вложенными - достаточно лишь предусмотреть необходимую глубину альтернативного стека. Адрес которого задаётся двухбайтовым словом по адресу esp. (В примере это estack_top equ #bfff).

    Есть ли более короткий/эффективный/разумный способ обработки исключений на асме z80? =)

    И насколько оправданно пользоваться описанным выше способом? =)
    oisee.

  2. #1
    С любовью к вам, Yandex.Direct
    Размещение рекламы на форуме способствует его дальнейшему развитию

  3. #2
    --- Аватар для Shadow Maker
    Регистрация
    01.03.2005
    Адрес
    Саранск
    Сообщений
    5,823
    Спасибо Благодарностей отдано 
    0
    Спасибо Благодарностей получено 
    235
    Поблагодарили
    100 сообщений
    Mentioned
    4 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Не могу придумать, зачем в Z80 использовать эксепшены таким образом. Всегда проще тупо сделать call exception или jp exception, и там установить или стек или еще чего.
    Свирепый агрессивно-депрессивный мордовец!
    Не уверен - не напрягай!

    Не сдавайся. Дыши?

    Virtual TR-DOS

  4. #3
    Master Аватар для siril
    Регистрация
    01.02.2005
    Адрес
    perm/ru
    Сообщений
    520
    Записей в дневнике
    1
    Спасибо Благодарностей отдано 
    0
    Спасибо Благодарностей получено 
    0
    Поблагодарили
    0 сообщений
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Цитата Сообщение от Shadow Maker Посмотреть сообщение
    Не могу придумать, зачем в Z80 использовать эксепшены таким образом. Всегда проще тупо сделать call exception или jp exception, и там установить или стек или еще чего.
    ну, тут может быть из-за макросов запутанно выглядит, на самом деле-то всего ничего: сохранение регистров на альтернативном стеке.

    доп-стек даёт возможность вложенных try-catch'ей с проверкой в catch'е а умеем ли мы обрабатывать данный exception или нет. если нет, то raise exception этажом выше.

    и даёт возможность сделать кучу raise'ов, в заранее неизвестных местах.

    хотя, конечно, если мы знаем где raise exception, и если если он у нас один, то огород городить не нужно - достаточно прописать по нужным адресам значение sp и адрес catch:

    Код:
    ;try
             ld (raise_0+1),sp
             ld hl,catch_0
             ld (raise_0+4),hl
             call something
    ;endtry
             ld a,'A' ; plan "a"
             ret
    ;catch
    catch_0  ld a,'B' ; plan "b" =)
             ret
    
    something
             ;do something
    ;{raise exception
    raise     ld sp,#0000 ; will be modified by "try" - sp
              jp #0000 ; will be modified by "try" - catch_0
              
    ;}raise exception
    Что можно ещё придумать?
    Последний раз редактировалось siril; 24.10.2012 в 10:17.
    oisee.

  5. #4
    Guru Аватар для jerri
    Регистрация
    01.03.2005
    Адрес
    Samara
    Сообщений
    4,751
    Спасибо Благодарностей отдано 
    256
    Спасибо Благодарностей получено 
    266
    Поблагодарили
    200 сообщений
    Mentioned
    12 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    siril, а пример нормальный есть?
    в виде даже С исходника
    С уважением,
    Jerri / Red Triangle.

  6. #5
    --- Аватар для Shadow Maker
    Регистрация
    01.03.2005
    Адрес
    Саранск
    Сообщений
    5,823
    Спасибо Благодарностей отдано 
    0
    Спасибо Благодарностей получено 
    235
    Поблагодарили
    100 сообщений
    Mentioned
    4 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Да, мне тоже интересно, ибо я реально не могу придумать пример, где действительно ОПРАВДАНО было бы использование таких эксепшенов.
    Свирепый агрессивно-депрессивный мордовец!
    Не уверен - не напрягай!

    Не сдавайся. Дыши?

    Virtual TR-DOS

  7. #6
    Guru Аватар для jerri
    Регистрация
    01.03.2005
    Адрес
    Samara
    Сообщений
    4,751
    Спасибо Благодарностей отдано 
    256
    Спасибо Благодарностей получено 
    266
    Поблагодарили
    200 сообщений
    Mentioned
    12 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    все эксцепшены на спеке обычно сводятся к

    Код:
    начало программы
      ld (store_sp),sp
      call programm
    exit
      ld sp,(store_sp)
      ret
    programm
      call process
      call keys
      jr programm
    
    и где нибудь дальше
      если надо прекратить изза ошибок
      jp exit
      
      или пользователь нажал нужную кнопку
      jp exit
    С уважением,
    Jerri / Red Triangle.

  8. #7
    --- Аватар для Shadow Maker
    Регистрация
    01.03.2005
    Адрес
    Саранск
    Сообщений
    5,823
    Спасибо Благодарностей отдано 
    0
    Спасибо Благодарностей получено 
    235
    Поблагодарили
    100 сообщений
    Mentioned
    4 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Ну да, я так и сказал.
    Свирепый агрессивно-депрессивный мордовец!
    Не уверен - не напрягай!

    Не сдавайся. Дыши?

    Virtual TR-DOS

  9. #8
    Veteran
    Регистрация
    08.05.2007
    Адрес
    Dnepropetrovsk
    Сообщений
    1,055
    Спасибо Благодарностей отдано 
    219
    Спасибо Благодарностей получено 
    47
    Поблагодарили
    31 сообщений
    Mentioned
    3 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Я думаю, все можно хранить на одном и том же стеке. В макросе "try" делать следующее:
    1) сохранить на стек содержимое переменных save_sp и catch_addr
    2) записать в переменную save_sp новое значение стека
    3) записать в переменную catch_addr новый адрес catch-блока
    4) выполнять код, в котором может возникнуть исключение
    5) в случае исключения:
    5.1) установить адрес стека на содержимое переменной save_sp
    5.2) выполнить переход на адрес catch_addr
    6) необходим блок finally, который исполняется независимо от того, было ли исключение, по окончании try-блока. В блоке finally восстанавливается значение переменных save_sp и catch_addr со стека, то есть выполняются действия, обратные выполненным в п. 1).

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

  10. #9
    Vitamin C++ Аватар для Vitamin
    Регистрация
    14.01.2005
    Адрес
    Таганрог, Россия
    Сообщений
    4,254
    Спасибо Благодарностей отдано 
    9
    Спасибо Благодарностей получено 
    80
    Поблагодарили
    34 сообщений
    Mentioned
    7 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Такие вот конструкции (try/catch/finally) обычно используются для предотвращения утечек динамически выделяемых ресурсов. На спеке такая модель не используется, отсюда и затруднения с придумыванием кейса использования.

  11. #10
    Guru Аватар для jerri
    Регистрация
    01.03.2005
    Адрес
    Samara
    Сообщений
    4,751
    Спасибо Благодарностей отдано 
    256
    Спасибо Благодарностей получено 
    266
    Поблагодарили
    200 сообщений
    Mentioned
    12 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Barmaley_m, в любом случае этот гемор нужен если памяти немерянно
    а тут всего 48 кб и вся подсчитана
    С уважением,
    Jerri / Red Triangle.

Страница 1 из 3 123 ПоследняяПоследняя

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Похожие темы

  1. Арифметические процедуры на ассемблере
    от spensor в разделе Программирование
    Ответов: 27
    Последнее: 13.05.2017, 20:56
  2. Пишем на ассемблере под эмулятором
    от GM BIT в разделе Для начинающих
    Ответов: 76
    Последнее: 15.07.2016, 20:04
  3. Ответов: 6
    Последнее: 07.02.2016, 11:55
  4. Ответов: 30
    Последнее: 14.01.2011, 15:13
  5. Подпрограмма на ассемблере в памяти?
    от jimled в разделе Программирование
    Ответов: 1
    Последнее: 29.11.2009, 06:46

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •