Если Вы работаете со строками, то Строка. Соединение , вероятно, что Вы ищете.
Как писали другие люди, существуют инструкции относительного перехода и относительного вызова, которые по существу добавляют фиксированное значение к eip
и, следовательно, не зависят от расположения программы в памяти; компиляторы предпочитают использовать их, когда это возможно. Вы можете посмотреть байты кода, чтобы узнать, какие именно инструкции использовал ваш компилятор. Однако я предполагаю, что вы спрашиваете о переходах / вызовах к абсолютным адресам.
Когда компоновщик генерирует исполняемый файл, он генерирует абсолютные адреса, предполагая конкретный базовый адрес ; Компоновщик Microsoft обычно использует 400000h
. Когда ОС загружает исполняемый файл или dll, она «исправляет» все абсолютные адреса, добавляя разницу между адресом, по которому исполняемый файл был фактически загружен, и адресом, на котором он был основан компоновщиком. Все исполняемые форматы, кроме .com
, определяют своего рода таблицу исправлений, в которой перечислены все места в исполняемом файле, которые должны быть исправлены таким образом. Следовательно, после того, как ОС загрузит ваш исполняемый файл в память по базовому адресу, скажем, 1500000h
, ваш переход будет выглядеть как jmp 1511395h
. Вы можете проверить это, посмотрев на фактические байты кода с помощью отладчика.
Старые системы Windows предпочитали загружать исполняемые файлы по базовому адресу, используемому компоновщиком; это создавало угрозу безопасности, поскольку злоумышленник заранее знал, где находится память. Вот почему в новых системах используется рандомизация базовых адресов.
после того, как ОС загрузит ваш исполняемый файл в память по базовому адресу, скажем, 1500000h
, ваш переход будет выглядеть как jmp 1511395h
. Вы можете проверить это, посмотрев на фактические байты кода с помощью отладчика.
Старые системы Windows предпочитали загружать исполняемые файлы по базовому адресу, используемому компоновщиком; это создавало угрозу безопасности, поскольку злоумышленник заранее знал, где находится память. Вот почему в новых системах используется рандомизация базовых адресов.
после того, как ОС загрузит ваш исполняемый файл в память по базовому адресу, скажем, 1500000h
, ваш переход будет выглядеть как jmp 1511395h
. Вы можете проверить это, посмотрев на фактические байты кода с помощью отладчика.
Старые системы Windows предпочитали загружать исполняемые файлы по базовому адресу, используемому компоновщиком; это создавало угрозу безопасности, потому что злоумышленник заранее знал, где находится память. Вот почему в новых системах используется рандомизация базовых адресов.
потому что злоумышленник заранее знает, что находится в памяти. Вот почему в новых системах используется рандомизация базовых адресов. потому что злоумышленник заранее знает, что находится в памяти. Вот почему в новых системах используется рандомизация базовых адресов.Нет, здесь, возможно, играют две вещи - вы не указываете ОС, поэтому я дам общий ответ.
Во-первых, исполняемый файл является редко в окончательном формате. Для упрощения компиляция превращает исходный код в объектные файлы, а связывание объединяет объектные файлы в исполняемый файл.
Но исполняемый файл должен быть загружен в память, и на этом этапе может быть выполнено еще больше изменений. . Одна из этих модификаций может заключаться в исправлении ссылок на память в исполняемом файле, чтобы они указывали на память, которая была загружена в разные места.
Это может быть достигнуто с помощью исполняемого файла, содержащего внутри себя список адресов, которые необходимо исправить. во время выполнения.
Существует также разрыв между виртуальной памятью и физической памятью во многих современных операционных системах.
Когда ваш процесс запускается, вы получаете собственное (4G для 32-битной Windows) адресное пространство, в которое загружается ваш процесс. Адреса в этом адресном пространстве мало связаны с вашими фактическими адресами физической памяти, и преобразование между ними выполняется блоком управления памятью (MMU).
Фактически, ваш процесс может перемещаться по всему физическому адресному пространству как он выгружается и вводится. Однако виртуальные адреса не изменятся.
Нет. На x86 (и других архитектурах тоже) большинство инструкций перехода IP-относительны : двоичные машинные коды для инструкций представляют собой смещение от текущего указателя инструкции. Таким образом, независимо от того, по какому виртуальному адресу загружается код, инструкции перехода работают правильно.
Ячейки памяти относятся к процессу. main
всегда находится в одном и том же месте в памяти относительно начала программы.
Относительные переходы берут адрес текущей машинной инструкции (называемой указателем инструкции) и добавляют смещение для вычисления адреса, на который нужно перейти.
Если вы посмотрите на свой код
004113B3 jmp main+25h (411395h)
004113B5 jmp main+25h (411395h)
004113B7 xor eax,eax
вы заметите, что инструкция jmp имеет длину 2 байта (1 байт для jmp, 1 байт для смещения) и не может хранить абсолютный 4-байтовый адрес.
Относительные переходы - это базовая функциональность ЦП (насколько я знаю около 65xx, Z80, 8086, 68000) и не связаны с такими расширенными функциями, как виртуальная память, отображение памяти или рандомизация адресного пространства.
Большинство микросхем имеют относительные переходы (относительно текущего местоположения) и виртуальную адресацию.