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

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

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

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 01.12.2018, 01:31   #1
Vlad Kom
 
Регистрация: 01.12.2018
Сообщений: 8
По умолчанию Объединение 2-х модулей

Привет, коллеги. Просьба, помочь в решении одного вопроса.
Сейчас изучаю тему раздельного ассемблирования.

Задача: объединить 2 объектных файла *.obj так, чтобы получился исполнительный *.com файл.

Т.к. файл .com, значит разделенная на части программа (написанная в двух разных *.asm файлах), после компилирования должна находится в одном сегменте кода (CS:смещение). В асм файлах пишу одно и то же имя сегмента кода. Пишу псевдооператор public. Однако после компиляции, ком файл не может быть создан линкером tlink. Причина - не может найти точку входа. Смотрю в дебаггер и вижу, что ip указывает не на CS:0100H (как в стандартных *.com программах), а на CS:0110H. Т.е. что-то смещает поинтер (ip) на 10H (т.к. в программе пишу org 100H). Дебаггером выявил, что это программа, которая написана в одном из *.asm файлов. Она занимает 2 байта (int 20H). И т.к. сегменты располагаются на границе параграфа, по умолчанию, следующий код идет по адресу CS:0110Н. Подозреваю, что при объединении, что то идет не так и программы располагаются в разных сегментах. Помогите разобраться. Как объединить правильно куски кода, разнесенные по разным исходникам. Спасибо!
Прикладываю исходники:

Файл 1.asm:

CODE_SG SEGMENT PUBLIC
ASSUME CS:CODE_SG
ORG 100H

EXTRN QWERTY:NEAR

START PROC NEAR
MOV AX,0FFFFH
CALL QWERTY
INT 20H
START ENDP

CODE_SG ENDS

END START

Файл 2.asm:

CODE_SG SEGMENT PUBLIC
ASSUME CS:CODE_SG

PUBLIC QWERTY

QWERTY PROC NEAR
INT 20H
QWERTY ENDP

CODE_SG ENDS

END

Компиляция:
tasm 1
tasm 2
tlink /t 1 2 - выдает ошибку - fatal: cannot generate COM file: invalid initial entry point adress

Тогда делаю по другому
tasm 1
tasm 2
tlink 1 2 - создает exe файл. Далее его и смотрю в дебаггере.
Vlad Kom вне форума Ответить с цитированием
Старый 01.12.2018, 08:17   #2
R71MT
Участник клуба
 
Аватар для R71MT
 
Регистрация: 16.06.2011
Сообщений: 1,428
По умолчанию

На этапе ассемблирования, компилятор сначала транслирует адреса всех относительных переходов и меток, а потом (исходя из этих адресов) линкует исходник в исполняемый файл. Таким образом, два отдельно-скомпанованных файла нельзя загрузить в одно адресное пространство, т.к. у них будет конфликт адресов.

Если сильно нужно, то применяют оверлейный механизм, когда есть один СОМ-родитель и несколько бинарных модулей. Занимается этим функция DOS AH=4b03h - загрузка и исполнение файлов. Функцией AH=4b00h можешь подгружать в своё пространство и законченные COM/EXE, которые по-окончании вернут управление опять родителю.

Другой вариант, установить родителю ORG-100h, а ребёнку например ORG-400h. В этом случае ребёнок получится бинарным, и транслятор ассемблера сгенерит NEAR-адреса меток, относительно базы 400h. Это предотвратит коллизию адресов, ..но считается извратом. DOS рекомендует оверлей.
Нашедшего выход - затаптывают первым..
R71MT вне форума Ответить с цитированием
Старый 02.12.2018, 00:15   #3
Vlad Kom
 
Регистрация: 01.12.2018
Сообщений: 8
По умолчанию

Как же тогда реализовать раздельное ассемблирование? Чтобы одни программисты писали процедуры, а другие основную программу? Только *.exe файл?
Vlad Kom вне форума Ответить с цитированием
Старый 02.12.2018, 09:46   #4
FPaul
Форумчанин
 
Регистрация: 25.01.2015
Сообщений: 472
По умолчанию

Скорее всего что-то пропущено в описании сегмента - оно же гораздо больше, чем представлено у вас.
Я попробовал
Код:
_TEXT	segment	word	public	'CODE'
но не получилось.

Далее попробовал упрощённую сегментацию - и всё получилось
Код:
.model  tiny
.code
        org     100h
start:
        jmp     main
extrn   MyProc:near

main:
        lea     dx,     [asHello]
        call    MyProc

        int     20h
;---------------------------------------
; данные
;---------------------------------------
        CrLf    db      0Dh, 0Ah, '$'
        asHello db      'Hello, World!', 0Dh, 0Ah, '$'


        end     start
Код:
.model	tiny
.code
	public	MyProc

MyProc	proc	near
	mov	ah,	09h
	int	21h
	ret
MyProc	endp

	end
Компилировал такой последовательностью
Код:
tasm com1asm.asm
tasm com2asm.asm
tlink /Tdc com1asm.obj+com2asm.obj
FPaul вне форума Ответить с цитированием
Старый 02.12.2018, 10:25   #5
R71MT
Участник клуба
 
Аватар для R71MT
 
Регистрация: 16.06.2011
Сообщений: 1,428
По умолчанию

Цитата:
Сообщение от Vlad Kom Посмотреть сообщение
Только *.exe файл?
ком-файл ограничен 64K-байтным диапазоном. что в нём можно сделать?
Хотя для доса это и огромный материк, всё-равно пора выбираться из него и как-минимум юзать экзе. Пусть "другие программисты" пишут только процедуры, из которых ты соберёшь свою/бинарную библиотеку. Тогда основной программой-оболочкой можно будет подгружать эту библиотеку в память, как отдельный оверлей. Только здесь есть нюансы:

1. Оверлейный принцип загрузки применяют в том случае, когда твоя программа слишком большая и вся не помещается в память. Тогда эту программу кромсают на несколько кусков, и подгружают эти куски по-очереди в один регион памяти. Например загрузил один кусок, и как он отработает - подгружаешь на его место другой, и т.д..

2. В твоём случае, код бинарных процедур нужно оформлять таким способом, чтобы переходы внутри кода не выходили за 127-байтные границы, т.е. были ближними типа Near. Тогда этот код получится переносимым и не будет привязан к конкретному адресу в памяти.

Нужно сказать, что виндовая "система подкачки страниц" и виртуальная память, берёт своё начало именно от досовских оверлеев. Таким-же образом и ты в своей досе можешь работать хоть с гигабайтными файлами, отображая отдельные его участки по-очереди, всего в одном сегменте памяти размером 64К.

А если брать глобально, то советую вообще забыть про MS-DOS, и расходовать своё время и потенциал на обуздание Windows. DOS давно труп и никому не нужен, а Win - это хоть какие-то перспективы на будущее. Открой для себя ассемблер FASM, который имеет простой синтаксис и компилит по одной клавиши [F9] без каких-либо батников. На нём можно кодить начиная от доса и до виндовых драйверов - самое "то" как для новичков, так и для профи.
Нашедшего выход - затаптывают первым..
R71MT вне форума Ответить с цитированием
Старый 02.12.2018, 15:56   #6
Vlad Kom
 
Регистрация: 01.12.2018
Сообщений: 8
По умолчанию

Спасибо, R71MT. Я планирую освоить программирование под винду. Но селекторы и дискрипторы нужно будет понять. Не просто они мне ранее давались... Думаю, сейчас разберусь

Последний раз редактировалось Vlad Kom; 02.12.2018 в 15:59.
Vlad Kom вне форума Ответить с цитированием
Старый 02.12.2018, 15:57   #7
Vlad Kom
 
Регистрация: 01.12.2018
Сообщений: 8
По умолчанию

Спасибо, FPaul. Тоже попробую тогда упрощенную сегментацию)

Последний раз редактировалось Vlad Kom; 02.12.2018 в 15:59.
Vlad Kom вне форума Ответить с цитированием
Старый 02.12.2018, 17:33   #8
R71MT
Участник клуба
 
Аватар для R71MT
 
Регистрация: 16.06.2011
Сообщений: 1,428
По умолчанию

Цитата:
Сообщение от Vlad Kom Посмотреть сообщение
Но селекторы и дискрипторы нужно будет понять.
..а зачем тебе дескрипторы?
они нужно только тем, кто пишет свою ОС.
Под виндой у тебя нет к ним доступа, т.к. ты будешь прогать в пространстве юзера. Можно прочитать селектор с сегментного дескриптора, но изменить его ты всё-равно не сможешь. А дескриптор - так вообще не доступен обычными средствами.
Нашедшего выход - затаптывают первым..
R71MT вне форума Ответить с цитированием
Старый 02.12.2018, 18:12   #9
Vlad Kom
 
Регистрация: 01.12.2018
Сообщений: 8
По умолчанию

Цитата:
Сообщение от Vlad Kom Посмотреть сообщение
Спасибо. Я планирую освоить программирование под винду. Но селекторы и дискрипторы нужно будет понять. Не просто они мне ранее давались... Думаю, сейчас разберусь

Цитата:
Сообщение от R71MT Посмотреть сообщение
..а зачем тебе дескрипторы?
они нужно только тем, кто пишет свою ОС.
Под виндой у тебя нет к ним доступа, т.к. ты будешь прогать в пространстве юзера. Можно прочитать селектор с сегментного дескриптора, но изменить его ты всё-равно не сможешь. А дескриптор - так вообще не доступен обычными средствами.
Просто, если прогать, то прогать с полным пониманием. Ну это моя заморочка...
Кстати, решил свой первоначальный вопрос!
Я просто добавил 3-й файл 3.asm который просто пустой
code_sg segment public
assume cs:code_sg
code_sg ends
end

Скомпилировал так
tasm 1
tasm 2
tasm 3
tlink /t 1 2 3
И все встало на свои места!

Из-за чего такое могло быть? Кривой линкер?
Vlad Kom вне форума Ответить с цитированием
Старый 02.12.2018, 18:54   #10
R71MT
Участник клуба
 
Аватар для R71MT
 
Регистрация: 16.06.2011
Сообщений: 1,428
По умолчанию

причины не знаю, но уверен
что если это *.сом и сумма этих/трёх файлов выйдет за пределы одного сегмента (64К), то прога не запустится. Тогда к чему эти танцы? Не проще-ли запихать всё в один исходник и скомпилировать его по-человечески?
Нашедшего выход - затаптывают первым..
R71MT вне форума Ответить с цитированием
Ответ


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

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

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


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Подключение модулей kitsun Паскаль, Turbo Pascal, PascalABC.NET 2 16.11.2013 15:11
подключение модулей... Teleport Помощь студентам 2 25.06.2008 00:26
подключение модулей... Teleport Помощь студентам 1 13.06.2008 15:04
Объединение GWT-модулей ILester JavaScript, Ajax 0 24.10.2007 14:55