Объясните начинающему

Тема в разделе "WASM.HEAP", создана пользователем device, 3 июн 2008.

  1. device

    device Reflection

    Публикаций:
    0
    Регистрация:
    26 апр 2007
    Сообщения:
    1.198
    Адрес:
    RF
    Написал на паскале hello world и решил посмотреть её ассемблерный вариант.
    Ограничиваясь набором инструментов, я получил такой вот код с At&T синтаксисом
    Код (Text):
    1.     .file "hello.pas"
    2.  
    3. .section .text
    4.  
    5. .section .text
    6.     .balign 16
    7.     .balign 16
    8. # [hello.pas]
    9. # [4] begin
    10. .globl  PASCALMAIN
    11.     .type   PASCALMAIN,@function
    12. PASCALMAIN:
    13. .globl  main
    14.     .type   main,@function
    15. main:
    16. # Temps allocated between ebp-4 and ebp+0
    17.     pushl   %ebp
    18.     movl    %esp,%ebp
    19.     subl    $4,%esp
    20.     movl    %ebx,-4(%ebp)
    21.     call    FPC_INITIALIZEUNITS
    22. # [5] writeln(msg);
    23.     call    fpc_get_output // получаем что-то
    24.     movl    %eax,%ebx // из eax это что-то пересылаем в ebx
    25.     movl    $_$PROGRAM$_L7,%ecx // это наше сообщение "hello" отправляется в ecx
    26.     movl    %ebx,%edx // ЭТО ДЛЯ ЧЕГО?
    27.     movl    $0,%eax // А xor eax, eax не катит?
    28.     call    fpc_write_text_shortstr // тааак... в eax у нас ноль, в ecx сообщение, что же передается функции?
    29.     call    FPC_IOCHECK
    30.     movl    %ebx,%eax
    31.     call    fpc_writeln_end
    32.     call    FPC_IOCHECK
    33. # [6] end.
    34.     call    FPC_DO_EXIT
    35.     movl    -4(%ebp),%ebx
    36.     leave
    37.     ret
    38.  
    39.  
    40. .section .data
    41.     .balign 4
    42. .globl  _$PROGRAM$_L7
    43. _$PROGRAM$_L7:
    44.     .ascii  "\005hello\000"
    45.  
    46. .section .data
    47.  
    48. .section .data
    49.  
    50. .section .bss
    Скажите, откуда берутся вызовы к таким ф-циям как FPC_что-то?
    В какой это библиотеке?
    Что за странности в процедуре main?
     
  2. trash_master

    trash_master New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2006
    Сообщения:
    319
    Адрес:
    Україна
    имхо участь этой темы будет аналогична твоей предыдущей ;)
     
  3. T800

    T800 Member

    Публикаций:
    0
    Регистрация:
    7 дек 2006
    Сообщения:
    293
    Адрес:
    Moscow
    1) FPC_INITIALIZEUNITS выполняется секция initialization
    2) fpc_get_output получаем хэндл устройства для вывода
    3) fpc_write_text_shortstr параметры передаётся через регистры

    ЗЫ. Компилятор FPC это конечно жесть...
     
  4. Barbos

    Barbos Slavon

    Публикаций:
    0
    Регистрация:
    13 ноя 2007
    Сообщения:
    280
    Адрес:
    Kharkov
    я тоже натыкался на подобные вещи. Кажется это связано с фичами компилятора, типа выравнивание и все такое.
    Когда то не много юзал ARM7, просматривал дизасм сишного текста в отладчике, на инструкции "int i=-1" увидел что то типа
    Код (Text):
    1. mov dword ptr xxx,0xFF0000FF
    2. or dowrd ptr xxx,0x00FFFF00
    много думал, пришел к выводу, что либо особенности работы с памятью, о которых не ведаю, либо маркетинговая фишка компилятора (среда разработки бесплатная, тестовая)
     
  5. crypto

    crypto Active Member

    Публикаций:
    0
    Регистрация:
    13 дек 2005
    Сообщения:
    2.533
    device
    в eax - хэндлер выходного потока
    этот хэндлер сохраняется в ebx
    в edx хэндлер выходного потока
    Может и не катит, от компилятора зависит, в частности
    А функции передаются через регистры три параметра: eax - 0 (если честно, не знаю, что это за параметр, нужно смотреть прототип функции, либо исходники), edx - хэндлер выходного потока, ecx - указатель на выводимую в поток строку.
    ЗЫ
    Если бы ты посмотрел на файл, созданный Дельфи, увидел бы очень похожие вещи.
    Barbos
    Странные какие-то инструкции... Вот для процессоров архитектуры RISC константы могут формироваться "необычным" образом (все-таки длина инструкции ограничена). А здесь - х.з.
     
  6. diamond

    diamond New Member

    Публикаций:
    0
    Регистрация:
    21 май 2004
    Сообщения:
    507
    Адрес:
    Russia
    FPC по-настоящему оптимизировать не умеет. Так что "movl $0,%eax" вместо "xorl %eax,%eax" - это следствие тупого компилятора.
    Код с разбивкой на функциональные блоки с комментариями:
    Код (Text):
    1. # Temps allocated between ebp-4 and ebp+0
    2.     pushl   %ebp
    3.     movl    %esp,%ebp
    4.     subl    $4,%esp
    Вход в функцию, создание стекового фрейма на 4 байта - это одна переменная [ebp-4].
    Код (Text):
    1. movl    %ebx,-4(%ebp)
    Сохранение в этой переменной значения регистра ebx. Сам регистр ebx будет использован для хранения неких данных.
    Код (Text):
    1. call    FPC_INITIALIZEUNITS
    Вызов, вставляемый компилятором в функцию main. Тут дело в следующем: в паскале перед выполнением собственно main() должны вызваться инициализирующие функции других модулей (тех, у которых такие функции есть), в их число всегда входит неявный System. Вот и вызывается специальная функция FPC_INITIALIZEUNITS из библиотеки FPC (кстати, вся библиотека написана на самом FPC). В Си несколько похожие процессы организованы по-другому.
    Код (Text):
    1. # [5] writeln(msg);
    2.     call    fpc_get_output // получаем что-то
    3.     movl    %eax,%ebx // из eax это что-то пересылаем в ebx
    На псевдо-Си это присваивание "ebx = stdout;"
    Код (Text):
    1.     movl    $_$PROGRAM$_L7,%ecx // это наше сообщение "hello" отправляется в ecx
    2.     movl    %ebx,%edx // ЭТО ДЛЯ ЧЕГО?
    3.     movl    $0,%eax // А xor eax, eax не катит?
    4.     call    fpc_write_text_shortstr // тааак... в eax у нас ноль, в ecx сообщение, что же передается функции?
    5.     call    FPC_IOCHECK
    На псевдо-Си первые 4 строчки - это вызов функции "fpc_write_text_shortstr(0,ebx,$_$PROGRAM$_L7);" FPC (по дефолту; а библиотеки fpc именно так и компилятся) использует схему вызова fastcall - первые 3 параметра передаются в регистрах eax,edx,ecx, ну а если параметров больше, включается стек.
    Последний вызов - вставлен компилятором и отвечает за реализацию директивы {$I+} - I/O checking - если произошла ошибка, будет ругательство со стороны библиотеки, и за это как раз и отвечает FPC_IOCHECK.
    Код (Text):
    1.     movl    %ebx,%eax
    2.     call    fpc_writeln_end
    3.     call    FPC_IOCHECK
    Соответственно, "fpc_writeln_end(ebx);"
    Код (Text):
    1. # [6] end.
    2.     call    FPC_DO_EXIT
    Опять же вставленный компилятором код - на сей раз корректно обрабатывающий выход из программы и вставляющийся в конце main(). Кстати, функция не возвращает управления, но компилятор этого не замечает и
    Код (Text):
    1.     movl    -4(%ebp),%ebx
    2.     leave
    3.     ret
    Восстанавливаем ebx, отключаем кадр стека, выходим из функции.
    В RTL от FreePascal'я. Библиотека поставляется вместе с компилятором.
     
  7. device

    device Reflection

    Публикаций:
    0
    Регистрация:
    26 апр 2007
    Сообщения:
    1.198
    Адрес:
    RF
    Ответ счерпывающий. Многое проясняется.
    Вообще, интересно смотреть, что выводят компилеры разные.
    Вот, та же программа hello, собраная ГНАТом.
    Рабочих там от силы 10 строк, а дальше - не понятно что идет.
    Код (Text):
    1.     .long   0x0
    2.     .byte   0x1
    3.     .string "zP"
    4.     .uleb128 0x1
    5.     .sleb128 -4
    6.     .byte   0x8
    7.     .uleb128 0x5
    8.     .byte   0x0
    9.     .long   __gnat_eh_personality
    10.     .byte   0xc
    11.     .uleb128 0x4
    12.     .uleb128 0x4
    13.     .byte   0x88
    14.     .uleb128 0x1
    15.     .align 4
    16. .LECIE1:
    17. .LSFDE1:
    18.     .long   .LEFDE1-.LASFDE1
    19. .LASFDE1:
    20.     .long   .LASFDE1-.Lframe1
    21.     .long   .LFB3
    22.     .long   .LFE3-.LFB3
    23.     .uleb128 0x0
    24.     .byte   0x4
    25.     .long   .LCFI0-.LFB3
    26.     .byte   0xc
    27.     .uleb128 0x1
    28.     .uleb128 0x0
    29.     .byte   0x9
    30.     .uleb128 0x4
    31.     .uleb128 0x1
    32.     .byte   0x4
    33.     .long   .LCFI1-.LCFI0
    34.     .byte   0xc
    35.     .uleb128 0x4
    36.     .uleb128 0x4
    37.     .byte   0x4
    38.     .long   .LCFI2-.LCFI1
    39.     .byte   0xe
    40.     .uleb128 0x8
    41.     .byte   0x85
    42.     .uleb128 0x2
    43.     .byte   0x4
    44.     .long   .LCFI3-.LCFI2
    45.     .byte   0xd
    46.     .uleb128 0x5
    47.     .byte   0x4
    48.     .long   .LCFI4-.LCFI3
    49.     .byte   0x84
    50.     .uleb128 0x3
    51.     .align 4
    52. .LEFDE1:
    53.     .ident  "GCC: (GNU) 4.1.1 20061011 (Red Hat 4.1.1-30)"
    Что это за фигня? Вижу, что данные, но для чего они нужны - не пойму. В LASFDE1 вычисляется размер каких-то фреймов.
    Что внутри этих фреймов, я показывать не буду, ибо цензура не пропустит.