Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.146.35.203] |
|
Сообщ.
#1
,
|
|
|
Когда программа загружается в память операционной системой (например DOS, но это не важно), то насколько я знаю (может я ошибаюсь?) сама операционная система записывает адрес сегмента кода в регистр CS и соответственно по этим адресам и загружает соответствующую программу. Вопрос, как записать адрес в регистр CS если я загружаю программу в память собственноручно написанным загрузчиком без какой бы то ни было операционной системы?
Я так понял (может я опять ошибаюсь) инструкции вида: PROG segment assume cs:PROG на самом деле ничего в CS не пишут. И ещё, вот такой код: PROG segment assume cs:PROG, ds:PROG, ss:PROG, es:PROG говорит о том, что регистры cs, ds, ss, es будут иметь одинаковые адреса и стоит записать адрес только в один, а в остальных он появиться автоматически? Если ничего не записал в CS (я так пробовал и всё работало), то сам компилятор ассемблера - например MASM, пишет в CS ноль - хотя это бред скорее всего? Я программу загружал в начало памяти, а в CS ничего не писал и программа, повторяю без операционной системы, работала. Как быть если программа не вмещается в сегмент? Первый момент, как узнать что программа не вмещается в сегмент? Просто компильнуть код и посмотреть поместиться по размеру в 65536 байт (почему не 65535? 65535 + один первый нулевой байт) или нет? Далее, если мне в процессе работы надо прыгнуть на участок кода который находится в другом сегменте кода и он не в начале этого сегмента, при этом такие прыжки мне надо совершать неоднократно по ходу выполнения программы, причём в разные места другого сегмента кода. Как быть? Писать в какой то регистр разные числа, потом в самом начале кода программы который находится в другом сегменте, проверять эти числа и в зависимости какое число прыгать на соответствующий участок кода уже в этом сегменте, так как в регистр IP ничего записать напрямую я не могу? Если это так, то тогда не понятно как быть если программа была загружена операционной системой и выполняется вместе с ней. Откуда программа будет знать по каким адресам загрузили вторую часть её кода находящегося в другом сегменте, что бы этот адрес записать в CS? Когда я сам, гружу две части программы самописным загрузчиком, я знаю по каким адресам я её гружу, поэтому знаю, что записать в CS. Да и ещё, когда я поменял адрес в CS, в IP остаётся ведь прежний адрес, а мне надо выйти как то на начало этого сегмента (имеется ввиду вторая часть моей программы которая не влезла в первый сегмент кода), то есть записать в IP ноль, что бы сделать проверку чисел и в зависимости от этого сделать соответствующий прыжок. Как это сделать? Я так думаю, что делается как то совсем по другому, но как? У форумчан может возникнуть вопрос, зачем мне это надо? Просто хочу до тонкостей разобраться. За любую помощь: ссылки на русскоязычный материал, или просто за объяснение вопроса или какой либо его части, буду благодарен! Сам я перерыв интернет на эти вопросы ответа так и не нашёл, поэтому пришлось обратиться за помощью к форумчанам, (может плохо искал). |
Сообщ.
#2
,
|
|
|
Цитата v4567 @ Вопрос как записать адрес в регистр CS? используй: jmp segment:offset ;или call segment:offset |
Сообщ.
#3
,
|
|
|
а куда я тогда прыгну? Мне ведь надо попасть во второй сегмент моего кода и в нём прыгнуть.
|
Сообщ.
#4
,
|
|
|
Цитата v4567 @ Мне ведь надо попасть во второй сегмент моего кода и в нём прыгнуть. Используй FAR jump EB cb JMP rel8 Jump short, relative, displacement relative to next instruction. E9 cw JMP rel16 Jump near, relative, displacement relative to next instruction. E9 cd JMP rel32 Jump near, relative, displacement relative to next instruction. FF /4 JMP r/m16 Jump near, absolute indirect, address given in r/m16. FF /4 JMP r/m32 Jump near, absolute indirect, address given in r/m32. EA cd JMP ptr16:16 Jump far, absolute, address given in operand. EA cp JMP ptr16:32 Jump far, absolute, address given in operand. FF /5 JMP m16:16 Jump far, absolute indirect, address given in m16:16. FF /5 JMP m16:32 Jump far, absolute indirect, address given in m16:32. |
Сообщ.
#5
,
|
|
|
.286 ; разрешаем использование инструкций процессора 80286 ;-- Сегменты кода -------------------------------------------------------------- CODE SEGMENT PARA 'CODE' ASSUME CS:CODE, DS:DATA, SS:STK Start: mov ax,DATA mov ds,ax mov es,ax call MyProc1 ; near call (ip) call MyProc2 ; far call (cs:ip) call MyProc3 ; far call (cs:ip) jmp Exit ; far jump (cs:ip) MyProc1 PROC NEAR mov ah,2 mov dl,'1' int 21h ret ; near ret MyProc1 ENDP CODE ENDS ;--------------------------------------- CODE2 SEGMENT PARA 'CODE' ASSUME CS:CODE2 MyProc2 PROC FAR mov ah,2 mov dl,'2' int 21h ret ; far ret MyProc2 ENDP MyProc3 PROC FAR mov ah,2 mov dl,'3' int 21h ret ; far ret MyProc3 ENDP CODE2 ENDS ;--------------------------------------- CODE3 SEGMENT PARA 'CODE' ASSUME CS:CODE3 Exit LABEL FAR mov ah,2 mov dl,'4' int 21h mov ax,4C00h int 21h ; выход из программы CODE3 ENDS ;-- Сегмент данных ------------------------------------------------------------- DATA SEGMENT PARA 'DATA' DATA ENDS ;-- Сегмент стека -------------------------------------------------------------- STK SEGMENT PARA STACK 'STACK' db 256 dup (?) ; размер стека (256 байт) STK ENDS END Start ; определение точки старта Добавлено И ассемблер сам расставит нужные call и jmp со сменой CS. CS вообще по-разному можно сменить. Дальний jmp far: db 0EAh dw Offset,Segment db 09Ah dw Offset,Segment push Segment push Offset retf |
Сообщ.
#6
,
|
|
|
Цитата Jin X @ CS вообще по-разному можно сменить. Чисто формально - я бы ещё добавил INT и IRET. Они ведь тоже приводят к изменению значения CS. |
Сообщ.
#7
,
|
|
|
Akina, добавь
Чисто формально А также: syscall/sysret, sysenter/sysexit, rsm, into, int1 (aka icebp), int3, bound, div/idiv (на 0), aam 0, ud2 (и прочие недействительные), все версии loadall (там, где они работали), fpu/simd-инструкции, все привилегированные инструкции в не 0-м кольце, а также даже mov (при включенном выравнивании и обращении к невыровненным данным) Что я ещё забыл? |
Сообщ.
#8
,
|
|
|
Akina, Jin X, имхо, вы слишком разогнались! ТСу нужно не просто изменение CS, а установка конкретного значения.
|
Сообщ.
#9
,
|
|
|
Цитата JoeUser @ Все эти методы устанавливают CS во вполне себе конкретное значение, которое можно легко как определить, так и задать перед изменением.ТСу нужно не просто изменение CS, а установка конкретного значения. Цитата Jin X @ А также Пока не указано явно, я стараюсь оставаться в рамках .8086... |
Сообщ.
#10
,
|
|
|
Akina, я думаю, что int и даже iret ему ненужно в данном случае
JoeUser, это так, уже скорее как прикол |