Трюки программирования или PrintHex во всей красе

Тема в разделе "WASM.ASSEMBLER", создана пользователем PROFi, 25 май 2006.

  1. PROFi

    PROFi New Member

    Публикаций:
    0
    Регистрация:
    13 июл 2003
    Сообщения:
    690
    Вообще я давно интерисуюсь короткими и изящными отрывками кода на ассемблере. Думаю каждый кто хоть как-то знаком с asm имеет у себя в запасе следующую функции (отрывок):
    Код (Text):
    1.  
    2. PrintHex:
    3. next_bit:       ; 25 байт
    4.   push eax      ; cl = 04h - 1 байт
    5.   ror eax,cl        ; cl = 08h - 12 бит
    6.   call print_4_bit  ; cl = 0Ch - 2 байта
    7.   pop eax           ; cl = 10h - 20 бит
    8.   sub cl,4      ; cl = 14h - 24 бит
    9.   jnz next_bit      ; cl = 18h - 28 бит
    10. print_4_bit:        ; cl = 1Ch - 4 байта
    11.   and al,0fh        ; jc exit_pr    - cl = 00h - 8 бит
    12.   daa
    13.   add al,0f0h
    14.   adc al,40h
    15.  
    16.  
    17.   ... функция Print типа stosb например
    18.   retn
    19.  


    Поделитесь у кого как она реализованна.
     
  2. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    PROFi

    Если красота этого шедевра заключается только в компактности, то call wsprintf в винде ещё компактнее. По скорости тоже далеко не предел: call, stosb, стек, партиальные регистры и зависимости пагубно сказываются на скорости.
     
  3. PROFi

    PROFi New Member

    Публикаций:
    0
    Регистрация:
    13 июл 2003
    Сообщения:
    690
    Quantum



    Я не притендую ни на компактность, ни на скорость, просто wsprintf как-то си отдает, да еще и не всегда применим.
     
  4. _5354

    _5354 New Member

    Публикаций:
    0
    Регистрация:
    26 май 2006
    Сообщения:
    1
    Вот моя Quine... тока предполагается, что это не на асме, а в хекскодах надо вводить :)
    Код (Text):
    1.     org 100h
    2.  
    3.     mov     ax, 0xb800
    4.     mov     es, ax
    5.     mov     di, 2*80*2
    6.     mov     si, 0x100
    7. b:  lodsb
    8.     push    ax
    9.     push    ax
    10.     shr     al, 4
    11. @@: and     al, 0x0f
    12.     cmp     al, 10
    13.     sbb     al, 0x69
    14.     das
    15.     mov     ah, 0x0f
    16.     stosw
    17.     pop     ax
    18.     test    di, 2
    19.     jnz     @b
    20.     dec     ax
    21.     cmp     al, 0xc2
    22.     jnz     b
    23. exit:
    24.     ret
    наверняка можно и меньше 40 байт, но какие в ДОСе значения регистров при старте хз, а других идей нет :-(
     
  5. trash

    trash New Member

    Публикаций:
    0
    Регистрация:
    9 апр 2006
    Сообщения:
    143
    Адрес:
    х.з.
    Код который пашет как 16бит RM/PM так 32-бит FLat моде..
    Код (Text):
    1.  
    2. procedure PrintHEX(val:integer);
    3. asm
    4.    MOV DH,4   {кол-во выводимых цифр}  
    5.    ROR EAX,12 {установить позицию}
    6.    @@TOP:
    7.    PUSH EAX
    8.  
    9.    MOV DL, '0'
    10.    AND AL, $F  {стереть старшие  биты}
    11.    OR  DL, AL  {логически прибавить}
    12.    CMP DL,$39  {IF DL> 39 THEN DL+7}
    13.    JBE @@NO
    14.    ADD DL,7    {скоректировать символ}
    15.    @@NO:
    16.    MOV AH,2    {распечатать на экран}
    17.    INT $21     {DOS-вывод симв DL=симв}
    18.  
    19.    POP EAX
    20.    ROL EAX,4
    21.    DEC DH      {уменьшить счетчик цикла}    
    22.    JNZ @@TOP
    23.  
    24.  
     
  6. Rockphorr

    Rockphorr Well-Known Member

    Публикаций:
    0
    Регистрация:
    9 июн 2004
    Сообщения:
    2.622
    Адрес:
    Russia
    на основе примера из книги Зубкова - ничего интересного
     
  7. trash

    trash New Member

    Публикаций:
    0
    Регистрация:
    9 апр 2006
    Сообщения:
    143
    Адрес:
    х.з.
    Rockphorr - то что нинтересна - да!канечна!

    код-в-студию.. а то я фик его знает как там у зубкова...
     
  8. PROFi

    PROFi New Member

    Публикаций:
    0
    Регистрация:
    13 июл 2003
    Сообщения:
    690
    Итак триварианта (я выделил самое важное)

    Вариант 1 = 8 байт
    Код (Text):
    1.  
    2. print_4_bit:       
    3.   and al,0fh       
    4.   daa
    5.   add al,0f0h
    6.   adc al,40h
    7.  


    Вариант 2 = 8 байт
    Код (Text):
    1.  
    2. @@: and     al, 0x0f
    3.     cmp     al, 10
    4.     sbb     al, 0x69
    5.     das
    6.  


    Вариант 3 = 12 байт
    Код (Text):
    1.  
    2.    MOV DL, '0'
    3.    AND AL, $F  {стереть старшие  биты}
    4.    OR  DL, AL  {логически прибавить}
    5.    CMP DL,$39  {IF DL> 39 THEN DL+7}
    6.    JBE @@NO
    7.    ADD DL,7    {скоректировать символ}
    8.    @@NO:
    9.  




    Уже неплохо и довольно оригинально
     
  9. alexus

    alexus New Member

    Публикаций:
    0
    Регистрация:
    9 май 2005
    Сообщения:
    11
    Код (Text):
    1. DataSeg
    2. change_buf db '0123456789ABCDEF'
    3. out_buf    db 8 dup ('0')
    4.  
    5. CodeSeg
    6.      lea ebx,change_buf
    7.      lea ecx,out_buf + 8
    8. @@1: mov eax,edx
    9.      shr edx,4
    10.      and al,0Fh
    11.      xlat
    12.      mov [ecx],al
    13.      dec ecx
    14.      or edx,edx
    15.      jnz @@1
    16.  
     
  10. Rockphorr

    Rockphorr Well-Known Member

    Публикаций:
    0
    Регистрация:
    9 июн 2004
    Сообщения:
    2.622
    Адрес:
    Russia
    trash

    Второй вариант в описании инструкции DAS

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

    Первая потом пригодится еще раз когда будешь BCD в строку преобразовывать
     
  11. PROFi

    PROFi New Member

    Публикаций:
    0
    Регистрация:
    13 июл 2003
    Сообщения:
    690
    А кто предложит вариант обрабатывающий сразу 2 символа?
     
  12. Rockphorr

    Rockphorr Well-Known Member

    Публикаций:
    0
    Регистрация:
    9 июн 2004
    Сообщения:
    2.622
    Адрес:
    Russia
    если не считать обертку вызывающую преобразования байтов - без вариантов
     
  13. Rockphorr

    Rockphorr Well-Known Member

    Публикаций:
    0
    Регистрация:
    9 июн 2004
    Сообщения:
    2.622
    Адрес:
    Russia
    продемонстрируйте класс
     
  14. SII

    SII Воин против дзена

    Публикаций:
    0
    Регистрация:
    31 окт 2007
    Сообщения:
    1.483
    Адрес:
    Подмосковье
    PROFi
    Если склероз не изменяет, в 64-разрядном режиме DAA/DAS и прочие команды десятичной коррекции похерили...
     
  15. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    SII
    в 64-х разрядном режиме они всю систему команд похерили!
     
  16. SII

    SII Воин против дзена

    Публикаций:
    0
    Регистрация:
    31 окт 2007
    Сообщения:
    1.483
    Адрес:
    Подмосковье
    Почему ж всю, основная масса команд никуда не делась.
     
  17. 0136

    0136 New Member

    Публикаций:
    0
    Регистрация:
    19 апр 2007
    Сообщения:
    112
    O! мне как раз нужна ф-я вывода слова на экран, а то я два раза вызываю функцию:

    mov bh, bl ; вход BL, сохраним
    shr bl, 4 ; выделим старший разряд
    add bl, 30h
    cmp bl, 39h
    jbe nemenbwe_neravno_go
    add bl,7
    nemenbwe_neravno_go:
    xchg bh, bl ; старший разряд готов
    and bl, 0fh ; выделим младший разряд
    add bl, 30h
    cmp bl, 39h
    jbe nemenbwe_neravno_go2
    add bl, 7
    nemenbwe_neravno_go2: ; BL = младший байт, BH = старший байт
    mov es:[edi+0b8000h], bh
    add edi, 2
    mov es:[edi+0b8000h], bl

    Какие идею чтобы не вызывать ф-ю два раза?
     
  18. Mikl___

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

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

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

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.792
    Quine предложенный _5354
    можно сделать на 5 байт короче :)
    Код (Text):
    1. .model tiny
    2. .286
    3. .code
    4. start: push 0B800h
    5.     pop es
    6.     mov di,2*80*2
    7.     mov ah,0Fh
    8. b:  lodsb
    9.     push ax
    10.     push ax
    11.     shr al,4
    12. @@: and al,0Fh
    13.     cmp al,10
    14.     sbb al,69h
    15.     das
    16.     stosw
    17.     pop ax
    18.     test di,2
    19.     jnz @b
    20.     add al,3Dh; проверяю на код retn (0C3h)
    21.     jnz b
    22. exit:  ret
    23. end start
     
  20. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    SII
    потому что те же inc eax можно было записать как 0x40 и 0xFF 0xC0, а осталось только последнее+появилось куча префиксов и половина регистров стала адресоваться через них