Инкрементное связывание вызывает неожиданную дизассемблирование программы MASM.

Некоторое время назад я опубликовал этот вопрос о странном поведении Я испытывал, пытаясь пройти через программу MASM.

По сути, учитывая следующий код:

; Tell MASM to use the Intel 80386 instruction set.
.386
; Flat memory model, and Win 32 calling convention
.MODEL FLAT, STDCALL
; Treat labels as case-sensitive (required for windows.inc)
OPTION CaseMap:None

include windows.inc
include masm32.inc
include user32.inc
include kernel32.inc
include macros.asm

includelib masm32.lib
includelib user32.lib
includelib kernel32.lib

.DATA
    BadText     db      "Error...", 0
    GoodText    db      "Excellent!", 0

.CODE
main PROC
        int 3
        mov eax, 6
        xor eax, eax
_label: add eax, ecx
        dec ecx
        jnz _label
        cmp eax, 21
        jz _good
_bad:   invoke StdOut, addr BadText
        jmp _quit
_good:  invoke StdOut, addr GoodText
_quit:  invoke ExitProcess, 0
main ENDP
END main

Я не смог запустить инструкцию int 3. Стало понятно, почему нет, изучив разборку:

00400FFD  add         byte ptr [eax],al  
00400FFF  add         ah,cl  
--- [User path]\main.asm 
        mov eax, 6
00401001  mov         eax,6  
        xor eax, eax
00401006  xor         eax,eax  
_label: add eax, ecx

Инструкция int 3 была заменена на add al,cl, но я понятия не имел почему. Мне удалось отследить проблему, была ли включена добавочная связь. Вышеупомянутая дизассемблирование было сгенерировано с отключенным добавочным связыванием (параметр /INCREMENTAL:NO в командной строке). Повторное включение приведет к примерно следующему:

.CODE
main PROC
        int 3
00401010  int         3  
        mov eax, 6
00401011  mov         eax,6  
        xor eax, eax
00401016  xor         eax,eax 

Я должен отметить, что чередующиеся строки являются ссылками на исходный код (я думаю, это особенность окна дизассемблирования Visual Studio). При включенной инкрементной компоновке дизассемблирование точно соответствует тому, что я написал в программе, и я ожидал, что она будет вести себя все это время.

Итак, почему отключение добавочного связывания может привести к изменению дизассемблирования моей программы? Что может происходить за кулисами, что на самом деле может изменить выполнение программы?


person kevintodisco    schedule 05.12.2012    source источник


Ответы (1)


Инструкция «добавить» — это двухбайтовая инструкция, вторая из которых — это 1-байтовый код операции вашего int3. Первый байт двухбайтовой инструкции добавления, вероятно, представляет собой какой-то мусор непосредственно перед точкой входа. Адрес инструкции добавления, вероятно, на 1 байт раньше, чем адрес инструкции int3.

Я быстро собрал, а затем разобрал эти две инструкции с помощью GNU as en objdump, и результат такой:

  8:    00 cc                   add    %cl,%ah
  a:    cc                      int3   

Здесь хорошо видно, что инструкция add содержит второй байт 0xcc, а int3 — 0xcc.

IOW убедитесь, что вы начинаете дизассемблирование в точке входа, чтобы избежать этой проблемы.

person Marco van de Voort    schedule 05.12.2012
comment
Как я могу гарантировать, что дизассемблирование начнется с точки входа? Это не объясняет, как это может произойти из-за неинкрементной компоновки. - person kevintodisco; 05.12.2012
comment
1) Я не владею тулчейном MS, поэтому не могу сказать как. 2) Изменение связывания может изменить то, что находится непосредственно перед точкой входа, путем изменения порядка сегментов. - person Marco van de Voort; 06.12.2012
comment
Ничего не произошло, он скомпилирован корректно, просто дизассемблер сработал по неверному адресу - видите ли, это xxxxFF, а очевидно ваш прок выровнен по адресу xxxxx00, так что у него все еще нормальный int3 (cc). Отвечая на ваш последний вопрос в 1-м посте, что может произойти? - прокладка, выравнивание. Используйте OllyDbg или WinDbg, они должны выполнять дизассемблирование правильным и умным способом. Скорее всего у вашей программы стандартная база - 400000; следовательно, имея в виду 1000h для PE-заголовка, 401000h должен быть точкой входа. Почему во втором случае есть 10-часовой зазор - взгляните на параметр align и разделы, которые могут предшествовать. - person Aleksey Ivchenko; 06.12.2012
comment
Спасибо за вашу помощь, ребята, я гораздо лучше понимаю, что происходит сейчас. - person kevintodisco; 06.12.2012