Не-пост про сопрограммы

Персональный блог одноименного форумчанина. Человека и парохода, не побоюсь этого сравнения :)

Модератор: tyomitch

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Не-пост про сопрограммы

Сообщение tyomitch » 10.05.2006 (Ср) 22:52

Это не пост; это, скорее, использование захваченой трибуны в целях ментального эксгибиционизма. Цитируя классику: "Я не жалуюсь, я хвастаюсь!"


Так вот: тема сопрограмм мной уже неявно затрагивалась в статье про фиберы.

Для тех, кому любопытно, как сопрограммы реализуются на чистом и переносимом Си, -- есть статья Саймона Татама. (Авторский комментарий: As far as I know, this is the worst piece of C hackery ever seen in serious production code.)

Я решил перевести пример кода, приведённый в той статье, на ассемблер, чтобы показать, насколько на нём всё выходит просто и естественно. Кроме того, мой код обильно прокомментирован.

Мораль здесь такая: есть некоторые товарищи (кивок в сторону vbnet.ru), которые полагают, что раз в ассемблер x86 встроена поддержка подпрограмм, значит подпрограммы рулят. А между тем, оказываются ситуации, когда от подпрограмм один вред, и самый прозрачный код получается при отказе от них; и на ассемблере писать код, незамутнённый подпрограммами, гораздо легче, чем на ЯВУ.


Код: Выделить всё
.186
model tiny

switch   macro   ; требует установленный кадр стека
local   resume   ; на стеке: ... (старый bp) (адрес возврата) (адрес перехода) ...
   push [bp+4]
   mov [bp+4], offset resume
   ret   ; на стеке: (адрес перехода) ... (старый bp) (адрес возврата) (адрес обратного перехода) ...
resume:   endm

.code
org 100h
start:      ; читаем с клавиатуры строку, кладём её в буфер
   mov ah, 10
   lea dx, buffer
   int 21h
   mov si, dx
   lodsw   ; читаем длину строки
   mov cl, ah
   xor ch, ch
   jcxz quit
   ; si указывает на строку, cx хранит её длину
   lea di, token   ; di указывет на накапливаемую лексему   
   push offset decompressor   ; начальный адрес перехода в сопрограмму
   call parser   ; основной цикл: лексический анализ и вывод на экран лексем
   mov ah, 9
   lea dx, crlf
   int 21h      ; перевод строки в конце вывода
quit:   int 20h

got_token proc near   ; вход: bx -- тип лексемы (_WORD, PUNCT)
         ; вывод на экран;  сохраняет ax
   shl bx, 1
   mov dx, m_table[bx]
   xchg ax, bx
   mov ah, 9
   int 21h      ; вывод типа лексемы
   mov al, '$'
   stosb
   lea dx, token
   int 21h      ; вывод лексемы
   mov di, dx
   xchg ax, bx
   ret
got_token endp

parser   proc near   ; параметр на стеке -- адрес перехода в сопрограмму decompressor
   push bp
   mov bp, sp
next_char:
   switch ;nextchar
   call isalpha
   jc punct

alpha:   stosb  ;add_to_token
   switch ;nextchar
   call isalpha
   jnc alpha
   mov bx, _WORD
   call got_token

punct:   or ah, ah
   jnz break

   stosb  ;add_to_token
   mov bx, PUNCT
        call got_token
       jmp next_char

break:   leave
   ret 2
parser   endp

decompressor proc near   ; выход: ax (-1=EOF)
; вызывается только в качестве сопрограммы; собственного кадра стека не имеет
   inc cx

n3xt_char:
   xor ax, ax
   loop proceed
   dec ax   ; вернуть EOF
   switch
   int 3    ; переключаться на нас после EOF уже нельзя

proceed:
   lodsb
   cmp al, 0FFh
   jnz emit

   push cx
   lodsb
   xchg ax, cx
   lodsb

emit_loop:
   switch
   loop emit_loop

   pop cx
   sub cx, 2
   jmp n3xt_char

emit:   switch
   jmp n3xt_char
decompressor endp

isalpha   proc near   ; вход: al;  вывод: nc=TRUE, cy=FALSE
   cmp al, 'A'
   jb not_alpha
   cmp Z, al
   jnb yes_alpha
   cmp al, 'a'
   jb not_alpha
   cmp z, al
;   jb not_alpha
yes_alpha:
;   clc
not_alpha:
   ret
isalpha endp

crlf   db 13, 10, '$'
m_word   db 13, 10, "WORD: $"
m_punct   db 13, 10, "PUNCT: $"
m_table   dw m_word, m_punct
_WORD   equ 0
PUNCT   equ 1

Z   db 'Z'
z   db 'z'

bufsize   equ 79
buffer   db bufsize, (bufsize+2)dup(?)
token   db (bufsize+1)dup(?)

end start
Изображение

Вернуться в Tyomitch

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 6

    TopList  
cron