Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 13.04.2017, 19:38   #1
gn,fur
 
Аватар для gn,fur
 
Регистрация: 13.04.2017
Сообщений: 3
По умолчанию Оверлейные функции.

Здравствуйте. Пытаюсь загрузить оверлей в asm8086 под досбоксом, вроде даже грузит, однако при попытке его выполнения просто повисает программа.

В основной программе:

Сегмент данных:
Код:
;Overlay stuff.
o_seg dw ?
o_off dw ?
code_seg dw ?
path db 'C:\div.exe',0
block dd 0
;Overlay stuff.
Загрузка оверлея:
Код:
zseg segment
zseg ends

mov code_seg,cs
mov ax,es
mov bx,zseg
sub bx,ax
mov ah,4ah
int 21h
jc j_error

mov bx,100h
mov ah,48h
int 21h
jc j_error
mov o_seg,ax

mov ax,code_seg
mov bx,o_seg
sub bx,ax
mov cl,4
shl bx,cl
mov o_off,bx

mov ax,seg block
mov es,ax
mov bx,offset block
mov ax,o_seg
mov [bx],ax
mov [bx]+2,ax
lea dx,path
mov ah,4bh
mov al,3
int 21h
jc j_error
Вызов загруженного оверлея:

Код:
call dword ptr o_off
В самом оверлее (больше там кода нет):

Код:
dseg segment
str4 db "Suppie!^^$"
dseg ends

cseg segment para public 'CODE'
start:
overlay proc far
assume cs:cseg,ds:dseg
push ds
mov ax,dseg
mov ds,ax

mov ax,0900h
lea dx,str4
int 21h

pop ds
ret
overlay endp
cseg ends
end start
В одной отдельно взятой фразе не должно быть больше миллиона муравьёв, пусть даже она — научного труда о муравьях.
gn,fur вне форума Ответить с цитированием
Старый 17.04.2017, 12:49   #2
R71MT
Участник клуба
 
Аватар для R71MT
 
Регистрация: 16.06.2011
Сообщений: 1,428
По умолчанию

У тебя что-то много лишнего в коде. Видно, что скоммуниздел исходник из каких-то старых источников, т.к. в таком стиле уже давно никто не пишет. Попробую объяснить на пальцах..

Для DOS-exe выделять память не обязательно, т.к. при запуске файла на исполнение, DOS выделяет для программы сразу всю/свободную память, а это без малого 16-сегментов по 64Кб. Никто не запрещает нам описывать в своих программах столько сегментов, на сколько хватит памяти.

Например, занял ты уже три сегмента по 64Кб: STACK/DATA/CODE, так занимай сразу ещё один и для оверлея, обозвав его к примеру "OVER". Зачем возиться с fn.4Ah - непонятно! Называть сегменты можешь как-угодно, только не заразервированными словами:
Код:
.model small
.stack 256
.data               ; описыавем сегмент данных
;......
;бла-бла-бла

.code               ; сегмент кода
start:
   mov  ax,@data
   mov  ds,ax
   mov  es,ax
;......
;бла-бла-бла

   mov  ax,@overlay
   mov  ds,ax
   mov  es,ax

   mov  ax,4C00h
   int  21h

.over               ; сегмент для оверлея
;......
;бла-бла-бла
Оверлейные части могут быть оформлены просто как дальние(FAR) процедуры, т.к. они загружаются в память основной программы. Различные оверлеи могут загружаться в одно и то-же место, затирая предыдущий код для экономии памяти.

В своём коде, ты вызываешь оверлей как CALL FAR, а возвращаешь управление (из тела оверлея) через RET. Так нельзя делать:
Код:
; в основной программе:
   call  dword ptr o_off
;=========================
; и в оверлее:
   ret
CALL FAR помещает в стек пару CS:IP (4 байта), а RET снимает со-стека только IP (2 байта). Отсюда и глюк. Нужно выходить из оверлея по RETF, который снимает сразу 4 байта, со-значениями CS:IP.

Вот пример более простого варианта на FASM'e..
Обычно, код самого оверлея я оформляю в виде бинарника.
Дальше, копирую его в отведённый сегмент внутри родительской программы, и вызываю на исполнение. По соображению наглядности, проверка на ошибку опущена:

Код:
format  mz                        ; делаем DOS-EXE
stack   100h                      ; 256 байт для стека
entry   @code:start               ; на Entry Point

segment @data                           ; сегмент данных ==============//
mess0   db    13,10,'Overlay Example'   ;
        db    13,10,'---------------$'  ;
fName   db    'myFile.bin',0            ; имя файла
epb     dw    @over                     ; заполняем EPB,
        dw    @over                     ;   ..номером оверлейного сегмента

segment @code                     ; сегмент кода ==================//
start:                            ;
;=== Настраиваем сегментные регистры DS/ES
        mov   ax,@data            ;
        mov   ds,ax               ;
        mov   es,ax               ;

        mov   ah,9                ; мессага!
        mov   dx,mess0            ;
        int   21h                 ;

;=== Загружаем оверлейный код!
        mov   bx,epb              ; ES:BX указывают на блок EPB
        mov   dx,fName            ; DS:DX указывают на путь до файла
        mov   ax, 4B03h           ;
        int   21h                 ; грузим оверлей в свой буфер!

;=== Вызывам его!
        push  ds @over            ;
        pop   ds                  ; настраиваем DS для мессаги (fn.9)
        call  @over:buff          ; CALL FAR с адресом вида SEG:OFFSET
        pop   ds                  ;

;=== Выход в DOS по клавише
        xor   ax,ax               ;
        int   16h                 ;
        mov   ax,4C00h            ;
        int   21h                 ;
;***********************************************************************
segment @over                     ; сегмент для оверлея!!!
label   buff  byte                ; инициируем меткой "BUFF" его начало 

;-------------8<------------------8<--------------------8<--------------
Ну а так будет выглядеть оверлейный файл:

Код:
; обозвать myFile.bin
;--------------------
format  binary                           ; делаю бинарник
        call  begin                      ; запоминаю IP
        db    13,10,"Hi! I'm overlay!$"  ;
begin:  pop   dx                         ; получаю адрес строки в DX
        mov   ah,9                       ;   ..(DS выставлен в родителе)
        int   21h                        ; мессага с текстом DS:DX!
        retf                             ; выхожу по "RET FAR"
Нашедшего выход - затаптывают первым..
R71MT вне форума Ответить с цитированием
Старый 20.04.2017, 18:59   #3
gn,fur
 
Аватар для gn,fur
 
Регистрация: 13.04.2017
Сообщений: 3
По умолчанию

Спасибо. :3
Да, кодец нагло скрал - в моём распоряжении лишь паршивенькая методичка по 8086 с этим примером, да ещё и с опечатками. Гугл знать не знает об оверлеях, да и я тоже.
В одной отдельно взятой фразе не должно быть больше миллиона муравьёв, пусть даже она — научного труда о муравьях.
gn,fur вне форума Ответить с цитированием
Старый 21.04.2017, 05:49   #4
Mikl___
Участник клуба
 
Регистрация: 11.01.2010
Сообщений: 1,162
По умолчанию

gn,fur,
немного об оверлеях -- Р. Джордейн. «Справочник программиста персональных компьютеров типа IBM PC, XT и AT» глава 7.2 "Создание драйвера устройства" на примере ANSI.SYS
Mikl___ вне форума Ответить с цитированием
Старый 26.04.2017, 08:34   #5
Argogo
Пользователь
 
Регистрация: 28.03.2013
Сообщений: 22
По умолчанию

Цитата:
Сообщение от R71MT Посмотреть сообщение
В своём коде, ты вызываешь оверлей как CALL FAR, а возвращаешь управление (из тела оверлея) через RET. Так нельзя делать:
Там процедура оверлея описана как "FAR", ассемблер при этом "RET" превращает в "RETF" (по крайней мере MASM):

Код:
Microsoft (R) Macro Assembler Version 6.11		    04/26/17 08:32:40
1.asm							     Page 1 - 1



 0000				dseg segment
 0000 53 75 70 70 69 65		str4 db "Suppie!^^$"
       21 5E 5E 24
 000A				dseg ends

 0000				cseg segment para public 'CODE'
 0000				start:
 0000				overlay proc far
				assume cs:cseg,ds:dseg
 0000  1E			push ds
 0001  B8 ---- R		mov ax,dseg
 0004  8E D8			mov ds,ax

 0006  B8 0900			mov ax,0900h
 0009  8D 16 0000 R		lea dx,str4
 000D  CD 21			int 21h

 000F  1F			pop ds
 0010  CB			ret
 0011				overlay endp
 0011				cseg ends
				end start
Argogo вне форума Ответить с цитированием
Старый 26.04.2017, 10:10   #6
R71MT
Участник клуба
 
Аватар для R71MT
 
Регистрация: 16.06.2011
Сообщений: 1,428
По умолчанию

Цитата:
Сообщение от Argogo Посмотреть сообщение
по крайней мере MASM
..в полне возможно. масмом не пользуюсь, поэтому не буду утвержать обратное. Я привык в фасму, а у него в досе нет "PROC -> ENDPROC"
Нашедшего выход - затаптывают первым..
R71MT вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Функции в языке С. Передача параметров в функции. Создание многофайловых проектов fifaman Общие вопросы C/C++ 6 28.12.2014 15:30
Табулирование заданной функции и определение максимального и минимального значения функции в таблице Марина1986 C/C++ Сетевое программирование 0 07.05.2013 11:31
Использование подпрограммы-функции: Вычислить значение функции (Турбо паскаль) RealUnited Паскаль, Turbo Pascal, PascalABC.NET 1 05.12.2012 20:34
Построение графика функции, мигание(затухание) шарика в минимумах функции kas1m_rus Паскаль, Turbo Pascal, PascalABC.NET 0 27.05.2012 20:28
Как подменить адрес возврата функции func на адрес функции f используя переполнение буфера buf и функции gets dmitrii6120 Помощь студентам 6 14.11.2011 20:10