Хранение данных в сегментах со сборкой - PullRequest
1 голос
/ 23 октября 2009

Я изучаю язык ассемблера x86 и понимаю назначение и использование сегментов. Сегменты содержат важные данные, а также могут использоваться для хранения дополнительных данных (т. Е. Модель сегментации памяти). Вот мой вопрос, хотя. Если сегменты можно использовать для хранения дополнительных данных, как я могу убедиться, что мои данные, хранящиеся в них, не будут перезаписывать существующие данные?

Например, регистр CS указывает на сегмент кода. Сегмент кода содержит код программы. Если бы я использовал регистр CS со смещением для хранения некоторых данных, как бы я узнал, куда поместить мои данные, чтобы не перезаписывать код, который они хранят?

Пожалуйста, дайте мне знать. Я использовал сборку синтаксиса Intel и сборку с NASM.

Спасибо

Ответы [ 4 ]

2 голосов
/ 23 октября 2009

Сегменты никогда хранят любые данные. Сегментные регистры - это просто «базовые» адресные указатели, которые используются для создания 20-битных указателей с использованием только 16-битных регистров. Например:

MOV DS, 0001
MOV DI, 0013
MOV AL, DS:[DI]  ' this reads from address x00023 in memory

MOV DS, 0002
MOV DI, 0003
MOV AL, DS:[DI]  ' this too reads from address x00023 in memory

MOV DS, 0000
MOV DI, 0023
MOV AL, DS:[DI]  ' this too reads from address x00023 in memory

Что касается вашего вопроса, как убедиться, что вы не перезаписываете код данными: все зависит от вас, чтобы вы точно знали, где в памяти вы храните свой код и данные!

0 голосов
/ 23 октября 2009

Как уже упоминалось, регистр сегмента содержит только 16-битный указатель. Этот указатель внутренне умножается на 16, чтобы процессор мог адресовать 20-битное пространство большой адресной памяти.

1) Если у вас достаточно памяти, вы можете выбрать 64 КБ ОЗУ для стека, 64 КБ для памяти данных и оставшуюся часть для памяти кода. Предположим, что SS (регистр сегмента стека) равен 0x0400, а DS (регистр сегмента данных) равен 0x0800, а CS (регистр сегмента кода) равен 0x1B00. В этом случае ваш код не может переопределить любой другой сегмент памяти. Если вам требуется еще 64 КБ памяти данных, вы можете просто расширить ее, используя сегмент ES и префикс ES.

2) Если вам не хватает места в памяти (компактная программа), вы должны предсказать границы памяти.

3) Если ваша программа использует внешние вызовы с указателями памяти, вы должны проверить границы. Для этого в x86 существует мнемоника BOUND инструкция.

0 голосов
/ 23 октября 2009

В дополнение к тому, что уже было сказано, я хотел бы добавить, что вы обычно не захотите хранить какие-либо «данные» в сегменте кода. Вот почему у вас есть сегмент данных (база указана DS) или даже «дополнительный» сегмент данных (-> ES). Очевидно, поскольку ваше основное предположение должно заключаться в том, что все, что находится в сегменте кода, будет выполнено, было бы очень неразумно записывать в него случайные значения данных.

Если вам необходимо хранить данные в сегменте кода, убедитесь, что они никогда не будут выполнены, как показано ниже:

<code>
..some code here..
jmp AfterDataDeclaration
  db 12  ; declare some data here
AfterDataDeclaration:
..some more code here..

[edit:] Если вы хотите получить доступ к каким-либо конкретным данным, вам всегда понадобится контрольная точка, которую вы обычно наиболее удобно объявляете с помощью метки. Ассемблер позволит вам получить доступ к этому символически, без необходимости знать его фактический адрес.

Единственный случай, когда вы можете захотеть что-то записать в сегмент кода, это если вы хотите патчить там машинный код (то есть, самоизменяющийся код).

0 голосов
/ 23 октября 2009

Это сборка, поэтому вы несете ответственность за все . Хранить код и данные отдельно, так же просто, как хранить два числа отдельно. Просто используйте каждую ячейку памяти не более одного раза.

...