Консультация № 144306
18.09.2008, 15:24
0.00 руб.
0 5 1
Здравствуйте, уважаемые эксперты!
1. Помогите с написанием длинного (межсегментного) перехода регистра CS. Меня интересуют способы, приёмы изменения этого сегмента. Если написать:
mov ax,0BF00h
mov es,ax
то сегментный регистр es будет равен 0BF00h. Этим же приёмом можно изменить и другие сегментные регистры: ds и ss, но только не cs! Отладчик напишет: Invalid opcode. Странно, про другие регистры не пишет, а про cs пишет. Неужели всё дело в том, что cs вместе с ip указывает на адрес текущей команды.
2. Я знаю только один способ изменения cs, вот такой:
jmp dword ptr cs:[x]
int 20h
x dd '1234'
Но опять непонятно, почему CS меняется на 3132, ведь я прописал сегмент 12, а смещение 34. В отладчике эта команда пишется: jmp FAR cs:[107], а по адресу 107 - 10А находятся числа 34 33 32 31. Откуда тройки-то взялись?
Заранее спасибо.

Обсуждение

давно
Старший Модератор
31795
6196
18.09.2008, 15:47
общий
это ответ
Здравствуйте, Aistesis!

1)
Да это особенный регистр вместе IP он указывает на адрес следующей исполняемой команды.
Вы не втретите команд типа MOV CS,RR или POP CS , хотя PUSH CS есть. Также как IP его можно изменить только косвенно, командами переходов, вызовами подпрограмм и возвратами из них.

2)
Все правильно Вы записываете строку символов, а это не числа. Если посмтрите на кодовую таблицу символов,то увидете, что "0"=30h, "1"=31h, "2"=32h и т.д.
Вот и всё, спрашивайте в мини-форуме.
Удачи!
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Неизвестный
19.09.2008, 08:54
общий
Вот первый пример:
jmp dword ptr cs:[x]
int 20h
x dw 1234h
Первоначально все сегментные регистры = 26СС, после межсегментного перехода IP=1234h, а CS=DE86.
1. Почему 1234h будет относиться к IP, а не к CS, как я хотел бы?
2. А разве это правильно, что переменную Х я сначала определил как слово Х dw ... , а потом переопределил её как двойное слово dword ptr? В учебниках, что я читал, все примеры носят обратный характер: как раз переменная или равна, или больше по размеру, чем её потом переопределяют. Например, если X dw ..., то или word ptr ..., или byte ptr ..., но ни разу dword ptr ...
3. Почему CS равняется именно DE86, может, потому, что данный сегмент на данный момент свободен? Но при следующем включении он может быть чем-то уже занят, и тогда программа зависнет.
Вот ещё второй пример:
jmp dword ptr cs:[x]
int 20h
x dd 1234h
1. Здесь в переменной Х я заменил dw на dd, и регистр CS после межсегментного перехода тоже изменился на другой. Он стал равен 0000. В чём причина такого изменения. В том, что слово 1234h благодаря директиве dd автоматически расширяется до двойного слова?
2. И ещё. Почему компилятор не выдал ошибку, когда двойному слову dd я приписал слово 1234h, здесь же несовпадение типов (размера).
Заранее спасибо.
давно
Старший Модератор
31795
6196
19.09.2008, 12:42
общий
Начнем с последних вопросов:
Когда Вы пишете x dd 1234h в памяти это число хранится как db 34h,12h,00h,00h именно поэтому у Вас там CS=0000.
Первым в памяти расположен IP, вторым CS. Это из-за команд RETN и RETF в обоих случаях извлекается IP и только в последней(дальний возврат) ещё извлекается CS, механизм изменения этих регитров ( CS:IP ) он одинаков для всех колманд переходов, вызова п/п и возврата из них.

Деректива dword ptr указывает компилятору, что нужно сгенерировать команду которая читает двойное слово по адресу Х,
если после строки x dw 1234h Вы поставите x dw 0000h у Вас будет такойже результат как выше.

В ассемблере нет такого понятия как переменная или тип данных. Любая переменная в ассемблере описыватся адресом(сегмент:смещение) и количеством байт, а процессору без разницы, что там код или данные, а может ещё что-то, он просто выполняет команды. Директивы DB,DW,DD,DF,DQ,DT определяют количество байт которые должен зарезервировать компилятор. И если указано значение, то записать его туда.

К примеру:
db 9ah
dw 2034h;'4 '
dw 0000h
так в памяти выглядит команда CALL 0000:2034 , а могли быть и данные.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Неизвестный
19.09.2008, 18:32
общий
Цитата:
"Директива dword ptr указывает компилятору, что нужно сгенерировать команду, которая читает двойное слово по адресу Х,
если после строки x dw 1234h Вы поставите x dw 0000h, у Вас будет такой же результат как выше".
Это понятно, что так и будет, но дело в том, что я после строки x dw 1234h в первом примере не ставлю x dw 0000h, тем не менее регистр меняется и меняется не на 0000h, а на случайный DE86.
2. Откомпилировал
db 9ah
dw 2034h
dw 0000h
Всё точно, отладчик показывает: 0100 9A34200000 CALL 0000:2034
За ответ спасибо!
давно
Старший Модератор
31795
6196
19.09.2008, 19:59
общий
а на случайный DE86

Подобный мусор туда могла запихнуть система когда загружала программу в лобой рание использовавшийся сегмент или отладчик, когда загружает в своё адресное пространство проверяемую программу.
Компиляторы тоже могут, но только в ЕХЕ-файлы.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Форма ответа