Как работает этот код?

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

  1. device

    device Reflection

    Публикаций:
    0
    Регистрация:
    26 апр 2007
    Сообщения:
    1.198
    Адрес:
    RF
    Официально записываюсь в бегиннерсы по сис кодингу на асме (заболел чето этим).
    Так что сильно матом не ругайтесь.

    Прошу помочь вот с чем.
    Написал я на СИ маленькую прогу да связывания. НУ, прога простая, и решил узнать, как бы это реализовать на асме?

    Нашел в гугле кое чего и вот что получилось

    Код (Text):
    1. extern dlopen
    2. extern dlsym
    3. extern dlerror
    4.  
    5.  
    6. global main
    7.  
    8.  
    9.  
    10. section .text
    11. main:
    12.     xchg eax,esp
    13.         push eax
    14.         mov byte[edx+ebx],0
    15.         push 0x00002 ;ВМЕСТО $101 (так работает)
    16.         push CALL_TABLE_SYM ; грузим символ из таблицы
    17.         call dlopen; ну и пытаемся его использовать.
    18.     jmp cleanup ; в гугле написан вызов cleanup.
    19. ; прога дальше ниче не делает, а просто запускается... с segfault:)
    20.  ret 0
    21. ; не моё
    22. cleanup:
    23.     xor eax,eax ;
    24.     jz LD_LINK_ERROR ; нафига, если там и так 0?
    25.         add esp,8 ; тогда это теряет смысл?
    26.         mov ebx,eax
    27.         pop eax
    28.         pop edx
    29.         xchg eax,esp
    30.         ret
    31.  
    32. ; НЕ МОЁ:)
    33. ; как работает - не знаю.
    34. LD_LINK_ERROR:
    35.     call dlerror  ; тут ясно все
    36.         mov esi,eax ; а вот дальше - объясните плиз.
    37.         mov edi,ebp
    38.     stosb
    39.         lodsb
    40.         or al,al
    41.         sub edi,ebp
    42.         lea eax,[edi-1]
    43.         mov [ebp],al
    44.         mov ebx,ebp
    45.     ret
    46.  
    47. section .data
    48. CALL_TABLE_SYM: DB 'showmsg'
    49. CALL_MD: DB './dlcurrent'
    сам я писал примерно такой код (без гугла)
    Код (Text):
    1. push 0x00002
    2. push CALL_TABLE_SYM
    3. call dlopen
    4. pop eax
    5. pop eax
    6. ret
    Тут все ясно, но после загрузки символа из разделяемого объекта дальше ниче не работает.
    Просвятите пожалуйста а то я уже глаза об монитор сломал.
     
  2. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    device
    ...
    cleanup:
    xor eax,eax ;
    jz LD_LINK_ERROR ; нафига, если там и так 0?
    ...

    Там, откуда ты это взял, например, fflinio.asm, написано OR eax,eax.

    ...
    call dlerror ; тут ясно все
    mov esi,eax ; а вот дальше - объясните плиз.
    mov edi,ebp
    stosb
    lodsb
    or al,al
    sub edi,ebp
    lea eax,[edi-1]
    mov [ebp],al
    mov ebx,ebp
    ret
    ...

    Функция dlerror вернула указатель на строку, завершающуюся нулем, из _своего_ буфера. Код копирует эту строку _себе_ и добавляет первым байтом ее размер, т.е. делает pascal-like string. Итого перед ret в EBX адрес _своей_ строки.

    ps по поводу "xchg eax,esp ... mov byte[edx+ebx],0 ... 0x00002 ;ВМЕСТО $101 ... mov edi,ebp" - ты точно представляешь с чем имеешь дело?
     
  3. device

    device Reflection

    Публикаций:
    0
    Регистрация:
    26 апр 2007
    Сообщения:
    1.198
    Адрес:
    RF
    Да, дело в том что мне нужна RTLD_NOW а не то что там написано, в файле dlfcn.h RTLD_NOW=0x00002
     
  4. device

    device Reflection

    Публикаций:
    0
    Регистрация:
    26 апр 2007
    Сообщения:
    1.198
    Адрес:
    RF
    А вот такой еще вопрос.
    Допустим, мы что-то втолкнули в стек, например:

    push слово
    call printf

    Для чего необходимо очищать стек? То есть если после printf не записать что-то типа pop eax, то получим Segmentation Fault. Почему?
     
  5. Mikl_

    Mikl_ New Member

    Публикаций:
    0
    Регистрация:
    14 ноя 2006
    Сообщения:
    907
    device
    Вроде большой уже а такие вещи спрашиваешь:) из всех функций wsprintfA требует чтобы прогер сам после нее вычистил стек
    Код (Text):
    1. ; может быть такой вариант
    2. push eax
    3. push offset format; формат вывода "%04d американских рублей"
    4. push offset buffer; куда вывести
    5. call _imp__wsprintfA
    6. pop eax
    7. pop eax
    8. pop eax
    9. ; очищаем от трех параметров (сама переменная и указатели на формат и буфер)
    10. ; а может быть такой
    11. push eax
    12. push ebx
    13. push edi
    14. push esi
    15. push offset format
    16. ; формат вывода "%04d рублей, %04d евро, %04d йен, %04d гривен"
    17. push offset buffer; куда вывести
    18. call _imp__wsprintfA
    19. add esp, 6*4
    20. ;очищаем от шести параметров (четыре переменных и указатели на формат и буфер)
    ибо сколько он туда загонит параметров он и сам может не знать, а что взять с бедной API?
     
  6. device

    device Reflection

    Публикаций:
    0
    Регистрация:
    26 апр 2007
    Сообщения:
    1.198
    Адрес:
    RF
    Я в Асме еще ооочень маленький. Под стол хожу.
     
  7. Mikl_

    Mikl_ New Member

    Публикаций:
    0
    Регистрация:
    14 ноя 2006
    Сообщения:
    907
    [offtop]главное, что бы не под себя:)[/offtop]
     
  8. device

    device Reflection

    Публикаций:
    0
    Регистрация:
    26 апр 2007
    Сообщения:
    1.198
    Адрес:
    RF
    В общем, сделал так.
    Откомпилил прогу на си, взял ассемблерный листинг.
    Стал его ковырять.
    Доковырял вот до чего:
    Код (Text):
    1.     lea ecx, [esp + 4]
    2.     and esp, -16
    3.     push    ecx
    4.     push    ebp
    5.     mov ebp,esp
    6.     push    ecx
    7.     sub esp, 36
    8.     push    2
    9.     mov esp, CALL_MD
    10.     call    dlopen
    11.     mov [ebp-8], eax
    12.     push    CALL_TABLE_SYM
    13.     mov eax, [ebp - 8]
    14.     mov [esp], eax
    15.     call    dlsym
    16.     mov [ebp-12], eax
    17.     mov [ebp-12], eax
    18.     call    eax
    19.     mov eax,0
    20.     add esp, 36
    21.     pop ecx
    22.     pop ebp
    23.     lea esp, [ecx - 4]
    Где-то ошибка, но где?
     
  9. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    device
    взял ассемблерный листинг. Стал его ковырять
    Смотреть/анализировать или еще менять?

    Где-то ошибка
    Покажи "прогу на си".
     
  10. device

    device Reflection

    Публикаций:
    0
    Регистрация:
    26 апр 2007
    Сообщения:
    1.198
    Адрес:
    RF
    Код (Text):
    1. int main()
    2. {
    3.  
    4. void (*sendm)(char *msg);
    5. void * module;
    6. module = dlopen ("dlcurrent.o", RTLD_NOW);
    7.  
    8. sendm = dlsym(module, "sendm");
    9. sendm("---> FROM ./dlcurrent.o - hi:)");
    10. return 0;
    11. }
     
  11. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    device
    Код (Text):
    1. ...
    2.     sub esp, 36
    3.     push    2       ;; надо так  mov [esp+4],2
    4.     mov esp, CALL_MD    ;; надо так  mov [esp],CALL_MD
    5. ...
    6.     push    CALL_TABLE_SYM  ;; надо так  mov [esp+4],CALL_TABLE_SYM
    7.     mov eax, [ebp - 8]  ;; это лишнее, EAX еще содержит handle
    8. ...
    9.     mov [ebp-12], eax   ;; это пусть останется, вдруг захочешь повторно вызвать sendm
    10.     mov [ebp-12], eax   ;; это лишнее
    11.     call    eax     ;; тут потерял параметр sendm, надо так
    12.                 ;;  mov [esp],тут_адрес_строки_"---> FROM ./dlcurrent.o - hi:)"
    13.                 ;;  call    eax
    14. ...
    + нет проверки успешного завершения ни dlopen ни dlsym

    + imho лучше писать так
    Код (Text):
    1. ...
    2. typedef void (*sendm_t)(char*);
    3. ...
    4. sendm_t sendm = (sendm_t) dlsym(module, "sendm");
    5. ...
    ps компилятор gcc?