Вычислить сегмент: смещение от абсолютного адреса

Я могу вычислить адрес Segment:Offset как Segment * 0x10 + Offset. Но как рассчитать обратное?

Например. как мне перейти с 0xF4170 на F400:0170 и с 0xACF04 на ABCD:1234?


person muffel    schedule 27.02.2012    source источник


Ответы (1)


Вам потребуется для начала либо база, либо смещение, а также линейный адрес, поскольку несколько пар Segment:Offset могут отображаться на один и тот же линейный адрес.

поэтому, если у нас есть сегмент 0xF400 и линейный адрес 0xF4170, мы получаем смещение 0xF4170 - (0xF400 << 4), которое равно 0x170.


Выполнение этого, зная только, что линейный адрес не имеет уникального решения, поэтому вам нужно выбрать соглашение для разделения 20-битного адреса на 16-байтовую часть seg и байтовое смещение. Одна из возможных функций такова:

  • Segement = linear >> 4 (старшие 16 бит)
  • offset = linear & 0x0F (младшие 4 бита)

Вы можете выбрать каноническую форму с 12: 8 битами, оставив место для будущего расширения за счет более широких линейных адресов.

person Necrolis    schedule 27.02.2012
comment
спасибо за такой ответ. Во всяком случае, меня не волнует, есть ли несколько возможностей пар Сегмент: Смещение. Вы знаете какой-либо способ вычислить только один из них, не зная также сегмент, как смещение, и без какого-либо перебора? - person muffel; 27.02.2012
comment
@muffel: см. мой обновленный ответ. это одна из проблем, когда вам нужно более одного уравнения или некоторый заданный побочный эффект, который позволяет вам решить для двух неизвестных. - person Necrolis; 27.02.2012
comment
Разделение линейного адреса на seg:off является точным, но не уникальным. Есть много возможных решений. @muffel: наиболее очевидный выбор для канонической формы - с 4-битным смещением или с 4-битным значением сегмента, помещая остальные 16 бит 20-битного линейного адреса в другой компонент seg: off. В связанном вопросе Найти адрес сегмента по заданному физическому и эффективному адресу часть off известна, поэтому мы можем просто решить для сегмента. - person Peter Cordes; 10.05.2019
comment
не должно быть достаточно сильным словом для линейного адреса seg:. Он автоматически выравнивается по определению того, как он учитывается в расчетах. У вас может быть сегмент данных или кода в исходном коде, который не выровнен по (16-байтовому) абзацу, но тогда самый низкий OFFSET в этом сегменте программы не обязательно будет равен 0. Не путайте разделы исходного кода asm, которые вызывают сами сегменты с фактическими значениями регистров сегментов. - person Peter Cordes; 10.05.2019
comment
Это потребовало серьезного редактирования; если только я чего-то не понял, это выглядело неправильно. Функция с & ~16 не имеет смысла, она очищает один бит. - person Peter Cordes; 10.05.2019
comment
@PeterCordes, который, кажется, был опечаткой с моей стороны, должен был быть ~15. хороший улов - person Necrolis; 14.05.2019