mov [ebp+var_4], eax/mov eax, [ebp+var_4]

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

  1. Tiro

    Tiro New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2006
    Сообщения:
    49
    Адрес:
    Russia
    Исходный текст транслирован NASM-мом.

    В дизассемблированном тексте встретил такую конструкция:

    .......

    mov [ebp+var_4], eax

    mov eax, [ebp+var_4]

    ......



    В чем смысл?
     
  2. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Например, выравнивание адреса цикла
     
  3. EvilsInterrupt

    EvilsInterrupt Постигающий азы дзена

    Публикаций:
    0
    Регистрация:
    28 окт 2003
    Сообщения:
    2.428
    Адрес:
    Russia
    cresta

    А можно по подробней, что ты имел ввиду?
     
  4. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Адрес, на который часто происходит переход (например начало цикла), желательно иметь кратным 4,8,16.

    Вот и выравнивают компиляторы адрес, вставляя перед циклом команды, ничего не делающие, но позволяющие сдвинуть адрес цикла на ближайшее кратное align'у значение.
     
  5. EvilsInterrupt

    EvilsInterrupt Постигающий азы дзена

    Публикаций:
    0
    Регистрация:
    28 окт 2003
    Сообщения:
    2.428
    Адрес:
    Russia
    cresta

    А к примеру будет такая сутуация:



    mov eax,2d

    jmp metka1

    mov eax,3d

    metka1:



    Сразу видно что выполняться, будет код после metka1, но ведь команда mov eax,3d по идее уже попала, т.к. за 1 проход:

    1. выбор следующей команды

    2. декодирование выбранной прошешим шагом

    3. вполнение текущей



    Мне до сих пор не понятно как процессор умудряется не выполнить подобные mov eax,3d команды?
     
  6. Vasil

    Vasil Василь

    Публикаций:
    0
    Регистрация:
    7 янв 2006
    Сообщения:
    228
    Адрес:
    Ижевск
    EvilsInterrupt



    1. выбор следующей команды

    2. декодирование выбранной прошешим шагом

    3. вполнение текущей



    - этот алгоритм выполняет конвеер команд, только там шагов больше (6).



    "Мне до сих пор не понятно как процессор умудряется не выполнить подобные mov eax,3d команды?"



    Если рассматривать традиционный конвеер команд, то всё очень просто (6 шагов). А если взглянуть на нынешние процессоры с суперконвеерной системой, то там немного сложнее (более 6 шагов).



    А выполнить он их не сможет, так как командой перехода "jmp metka1" адрес следующей команды уже формируется, соответственно "mov eax,3d" на выполнение не попадает.
     
  7. Vasil

    Vasil Василь

    Публикаций:
    0
    Регистрация:
    7 янв 2006
    Сообщения:
    228
    Адрес:
    Ижевск
    cresta

    "Адрес, на который часто происходит переход (например начало цикла), желательно иметь кратным 4,8,16.

    Вот и выравнивают компиляторы адрес, вставляя перед циклом команды, ничего не делающие, но позволяющие сдвинуть адрес цикла на ближайшее кратное align'у значение."




    В таких ситуациях чаще выравнивают командной nop :)
     
  8. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Какой командой выравнивать - это решает компилятор, исходя из заложенных в него шаблонов. У каждого компилятора свои шаблоны, и они зависят от количества байт, на которое надо сдвинуть адрес.

    А лепить кучу nop'ов - этого практически никто не делает.

    Вот выравнивание от ml.exe:

    Вот процедура


    Код (Text):
    1. cicle proc
    2.     xor     eax,eax
    3.     mov     ecx,10000h
    4.   _m:
    5.     mov     eax,ecx
    6.     shl     eax,2
    7.     dec     ecx
    8.     jnz     _m
    9.     ret
    10. cicle endp




    Вот её дизассемблерный лист:


    Код (Text):
    1. 00401030    XOR EAX,EAX
    2. 00401032    MOV ECX,10000
    3. [b]00401037[/b]    MOV EAX,ECX   ;адрес некратный 16
    4. 00401039    SHL EAX,2
    5. 0040103C    DEC ECX
    6. 0040103D    JNZ SHORT ShExp.00401037
    7. 0040103F    RETN




    Вот та же процедура с выравненым циклом:
    Код (Text):
    1. cicle proc
    2.     xor     eax,eax
    3.     mov     ecx,10000h
    4. [b]align 16[/b]
    5.   _m:
    6.     mov     eax,ecx
    7.     shl     eax,2
    8.     dec     ecx
    9.     jnz     _m
    10.     ret
    11. cicle endp




    И её листинг:
    Код (Text):
    1. 00401030    XOR EAX,EAX
    2. 00401032    MOV ECX,10000
    3. 00401037    LEA ESP,DWORD PTR SS:[ESP]
    4. 0040103E    MOV EDI,EDI
    5. [b]00401040[/b]    MOV EAX,ECX
    6. 00401042    SHL EAX,2
    7. 00401045    DEC ECX
    8. 00401046    JNZ SHORT ShExp.00401040
    9. 00401048    RETN




    Во втором коде, чтобы выравнять начало цикла на 16, компилятор вставил две инструкции LEA ESP,DWORD PTR SS:[ESP] и MOV EDI,EDI, которые не влияют на регистры и на флаги. Т.е. они будут выполняться, но фактически ничего не делают, и за счет их длины начало цикла сместилось с некратного 16 адреса 00401037 на 00401040.
     
  9. Vasil

    Vasil Василь

    Публикаций:
    0
    Регистрация:
    7 янв 2006
    Сообщения:
    228
    Адрес:
    Ижевск
    Может я и не прав по NOP'ам (много nop'ов - много выборки).



    Но та конструкция выравнивает по 6, а не по 4, 8, 16, ...



    Хотя, возможно, что это ЧАСТЬ конструкции, которая выравнивает по 4, 8 или 16.
     
  10. cresta

    cresta Active Member

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




    Это какая конструкция? Которую привел автор?

    Сказать на сколько невозможно не имея окружающего кода. Смещать может на 6 байт, а вот выравнивать следующую - это на адрес+6
     
  11. Vasil

    Vasil Василь

    Публикаций:
    0
    Регистрация:
    7 янв 2006
    Сообщения:
    228
    Адрес:
    Ижевск
    УПС, что-то я не подумал об этом :~|
     
  12. Quantum

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

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



    Код скомпилирован без оптимизации.



    cresta



    Для выравнивания используются инструкции типа nop, mov edi,edi и т.д. "mov eax, [ebp+var_4]" после "mov [ebp+var_4], eax" будет только тормозить.
     
  13. captain cobalt

    captain cobalt New Member

    Публикаций:
    0
    Регистрация:
    21 дек 2003
    Сообщения:
    222
    Адрес:
    /ru/perm
    Tiro

    Вторая инструкция возможно является целевым адресом перехода и может выполняться не только непосредственно после первой.



    Также возможно код был сгенерирован из "тупых макросов".
     
  14. Tiro

    Tiro New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2006
    Сообщения:
    49
    Адрес:
    Russia
    Компилятор я указал поспешно. Возможно это C.

    Вся процедура:



    push ebp

    mov ebp, esp

    push ecx

    push ebx

    call _dsGetCurSmp@0

    sub eax, ds:dword_1D5A

    mov [ebp+var_4], eax

    mov eax, [ebp+var_4]

    mov ebx, 3E8h

    imul ebx

    mov ebx, 2B110h

    idiv ebx

    mov [ebp+var_4], eax

    mov eax, [ebp+var_4]

    pop ebx

    leave

    retn



    .bss:00001D5A dword_1D5A dd ?
     
  15. OLS

    OLS New Member

    Публикаций:
    0
    Регистрация:
    8 янв 2005
    Сообщения:
    322
    Адрес:
    Russia


    push ecx

    push ebx

    call _dsGetCurSmp@0

    sub eax, ds:dword_1D5A

    mov [ebp+var_4], eax



    mov eax, [ebp+var_4]

    mov ebx, 3E8h

    imul ebx





    Налицо просто явное отсутствие оптимизации между двумя высокоуровневыми конструкциями (call и imul) - больше никакого тайного смысла здесь нет.



    Во втором случае - то же самое. Исходно программистом код был написан с задействованием локальной переменной, а компилятор не смог понять, что можно обойтись без нее.
     
  16. Tiro

    Tiro New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2006
    Сообщения:
    49
    Адрес:
    Russia
    Понятно. Спасибо всем.
     
  17. crypto

    crypto Active Member

    Публикаций:
    0
    Регистрация:
    13 дек 2005
    Сообщения:
    2.533
    Скорее всего, исходный код выглядел так:

    return (dsGetCurSmp() - dword_1D5A)*1000/176400;

    Компилятор при этом заводит временную локальную переменную (или кладет в стек временное значение). Поэтому заморочек, связанных с выравниванием, здесь нет.