2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему На страницу Пред.  1, 2, 3, 4  След.
 
 Re: Hello world
Сообщение09.06.2013, 20:10 
Заслуженный участник


29/04/12
268
Компилятор не знает, что вы собираетесь получить COM. Он просто готовит объектный файл. Объектный файл содержит код, данные и различную служебную информацию (в частности, что в какие сегменты пихать). А вот уже линкер из объектного файла собирает исполняемый файл. Если вы укажите линкеру делать COM, то он тупо проигнорирует всю информацию про сегменты.

 Профиль  
                  
 
 Re: Hello world
Сообщение09.06.2013, 23:46 
Заслуженный участник
Аватара пользователя


03/08/11
1613
Новосибирск
Теперь все понятно, спасибо за разъяснение!

 Профиль  
                  
 
 Re: Hello world
Сообщение10.06.2013, 17:32 
Заслуженный участник
Аватара пользователя


03/08/11
1613
Новосибирск
Опять ступор. :x Написал код
Используется синтаксис ASM
.model small
.data
msg db 'message $'
.code
org 100h
start:
mov ah,09h
mov dx, offset msg
int 21h
ret
end start
Скомпилил .COM файл. Вылетает почти как если бы в dx был 0 (если запихать в dx 0, то в начале выводится еще 2 символа). Если написать
Используется синтаксис ASM
.model small
.code
org 100h
start:
mov ah,09h
mov dx, offset msg
int 21h
ret
msg db 'message $'
end start
то все нормально.
Почему результат разный?

 Профиль  
                  
 
 Re: Hello world
Сообщение10.06.2013, 18:23 
Заслуженный участник


29/04/12
268
Замените модель на tiny, либо линкуйте в exe. В последнем случае нужно ещё вручную инициализировать сегмент данных:
Код:
mov ax,@data
mov ds,ax

(Почему так произошло)

В модели small предполагается, что данные в отдельном сегменте. Поэтому компилятор, видимо, в объектнике указал, что msg лежит в сегменте DATA по адресу 0. Линкер, собирая COM, склеил CODE и DATA, и установил адрес msg на смещение DATA (как в файле). То есть "offset msg" заменился на адрес, на 100h меньший нужного (помним, что система при загрузке COM первые 100h сегмента кода заполняет служебной информацией и только потом идёт программа). Можете ради эксперимента заменить в первом варианте "offset msg" на "offset msg+100h". Но в реальном коде так не надо делать.

 Профиль  
                  
 
 Re: Hello world
Сообщение10.06.2013, 18:42 
Заслуженный участник


11/11/07
1198
Москва
Насколько я помню, компоновщик располагает сегменты в исполняемом файле в порядке их появления в программе. А COM-файл грузится следующим образом. Сначала создается префикс программного сегмента (PSP), который занимает 256 (= 100h) байт. Сразу за PSP копируется информация из файла. Все сегментные регистры устанавливаются на начало PSP, SP устанавливается в FFFEh, а IP - в 100h. А у вас, возможно, по адресу 100h находится строка msg.

PS. Кстати, первые два байта PSP - это CD 20 - код команды int 20h, а в вершине стека записывается 0. Так что COM-программу можно завершать командой ret, что экономит 1 байт.

 Профиль  
                  
 
 Re: Hello world
Сообщение11.06.2013, 15:29 
Заслуженный участник
Аватара пользователя


03/08/11
1613
Новосибирск
lena7 в сообщении #735065 писал(а):
Линкер, собирая COM, склеил CODE и DATA, и установил адрес msg на смещение DATA (как в файле).

У меня какая-то путаница. Гугляж говорит, что ассемблер преобразует исходный код в машинный и составляет таблицу перекрестных ссылок и таблицу сегментов. Сказано, что составление таблицы перекрестных ссылок это значит пометить участки куда, куда надо будет записать адреса внешних ссылок , глобальных функций и глобальных переменных. Составление таблицы сегментов- это значит пометить сегмент кода и сегмент данных. Т.е. этот момент
lena7 в сообщении #735065 писал(а):
Поэтому компилятор, видимо, в объектнике указал, что msg лежит в сегменте DATA по адресу 0.

не понятен, ведь исходя из определния, что я привел выше не видно, чтобы были где-то записаны адреса. Может я не верно понял что значит "пометить участок кода".
При попытки посмотреть объектник ничего не получается, там каша какая-то.
lena7 в сообщении #735065 писал(а):
Код:
Код:
mov ax,@data
mov ds,ax


Не понял, зачем сначала пересылка в ax, почему сразу не в ds?

Я пытался переслать данные из ip в dx, но компилятор выдает ошибку "Undefined symbol: IP". Регистр IP вообще нельзя трогать?

 Профиль  
                  
 
 Re: Hello world
Сообщение11.06.2013, 15:58 
Заслуженный участник


29/04/12
268
Зачем вам знать, как работает tasm, tlink в формат используемых там объектных файлов (с точки зрения изучения ассемблера)?

(Оффтоп)

Грубо говоря, компилятор (ассемблер в вашем случае) берёт исходный код программы и генерирует объектный файл. Объектный файл содержит информацию о сегментах, символах (переменные, функции), машинный код, сгенерированный компилятором (но не все адреса там верно установлены), данные, отладочную информацию и др. Когда в исходном коде есть, скажем, "offset" или ссылка на какие-либо символы, то ассемблер не всегда знает, какими адресами их заменять. Конкретные адреса в конечном исполняемом файле (точнее, в памяти, куда система его загрузит) будут известны лишь линкеру. Поэтому компилятор лишь записывает в объектник некоторую информацию, помогающую линкеру правильно проставить потом адреса. Конкретные детали зависят от реализации компилятора, линкера и формата используемых объектных файлов.

Я уже указала, что надо сделать, чтобы исправить ошибку. Причина ошибки в том, что компилятор хотел сделать DATA отдельным сегментом (что ему диктовала модель small), а линкер -- склеил его с CODE (ибо он делал COM).

(Оффтоп)

Замечу, что tlink не настолько глуп, чтобы даже в этом случае поместить DATA перед CODE в выходном COM-файле. Так что строка msg у вас попала не на адрес 100h, а дальше -- 100h+(размер кода). Однако "offset msg" заменилось на просто (размер кода).

xmaister в сообщении #735417 писал(а):
Не понял, зачем сначала пересылка в ax, почему сразу не в ds?

Не выйдет. Нет инструкции процессора, которая бы записывала в ds сразу непосредственное значение. Но зато есть инструкция, записывающая в ax непосредственное значение и инструкция, копирующая ax в ds.

xmaister в сообщении #735417 писал(а):
Регистр IP вообще нельзя трогать?

Опять же -- нет инструкций, обращающихся к ip напрямую. Однако вытащить ip можно, если вспомнить, что call кладёт в стек адрес следующей инструкции, прежде чем перейти по указанному адресу.

 Профиль  
                  
 
 Re: Hello world
Сообщение11.06.2013, 20:07 


09/05/10
122
Ростов-на-Дону
xmaister в сообщении #735417 писал(а):
При попытки посмотреть объектник ничего не получается, там каша какая-то.

Смотреть нужно .LST, .MAP, не .OBJ. Для этого должна быть включена соответствующая опция компилятора.

 Профиль  
                  
 
 Re: Hello world
Сообщение12.06.2013, 00:32 
Заслуженный участник
Аватара пользователя


03/08/11
1613
Новосибирск

(Оффтоп)

lena7 в сообщении #735425 писал(а):
Зачем вам знать, как работает tasm, tlink в формат используемых там объектных файлов (с точки зрения изучения ассемблера)?

А разве это не нужно знать чтобы понимать что происходит?

Tod Leben в сообщении #735515 писал(а):
Смотреть нужно .LST, .MAP, не .OBJ. Для этого должна быть включена соответствующая опция компилятора.

Вот .LST и теперь действительно видно, каким образом появляется строится объектный файл, в первом приближении
Код:
Turbo Assembler    Version 4.1       06/11/13 15:26:26       Page 1
hello.ASM



      1   0000              .model small
      2   0000              .data
      3   0000  48 65 6C 6C 6F 20   24   msg db 'Hello $'
      4   0007              .code
      5                 org 100h
      6   0100              start:
      7   0100  B4 09           mov ah,09h
      8   0102  BA 0000r           mov dx, offset msg
      9   0105  CD 21           int 21h
     10   0107  C3           ret
     11                 end start
Turbo Assembler    Version 4.1       06/11/13 15:26:26       Page 2
Symbol Table




Symbol Name           Type    Value

??DATE              Text    "06/11/13"
??FILENAME           Text    "hello     "
??TIME              Text    "15:26:26"
??VERSION           Number 040A
@32BIT              Text    0
@CODE              Text    _TEXT
@CODESIZE           Text    0
@CPU              Text    0101H
@CURSEG              Text    _TEXT
@DATA              Text    DGROUP
@DATASIZE           Text    0
@FILENAME           Text    HELLO
@INTERFACE           Text    000H
@MODEL              Text    2
@STACK              Text    DGROUP
@WORDSIZE           Text    2
MSG              Byte    DGROUP:0000
START              Near    _TEXT:0100

Groups & Segments        Bit Size Align  Combine Class

DGROUP              Group
  _DATA              16  0007 Word     Public  DATA
_TEXT              16  0108 Word     Public  CODE

и вот .lst если указать .model tiny
Код:
Turbo Assembler    Version 4.1       06/11/13 15:56:57       Page 1
hello.ASM



      1   0000              .model tiny
      2   0000              .data
      3   0000  48 65 6C 6C 6F 20   24   msg db 'Hello $'
      4   0007              .code
      5                 org 100h
      6   0100              start:
      7   0100  B4 09           mov ah,09h
      8   0102  BA 0000r           mov dx, offset msg
      9   0105  CD 21           int 21h
     10   0107  C3           ret
     11                 end start
Turbo Assembler    Version 4.1       06/11/13 15:56:57       Page 2
Symbol Table




Symbol Name           Type    Value

??DATE              Text    "06/11/13"
??FILENAME           Text    "hello     "
??TIME              Text    "15:56:57"
??VERSION           Number 040A
@32BIT              Text    0
@CODE              Text    DGROUP
@CODESIZE           Text    0
@CPU              Text    0101H
@CURSEG              Text    _TEXT
@DATA              Text    DGROUP
@DATASIZE           Text    0
@FILENAME           Text    HELLO
@INTERFACE           Text    000H
@MODEL              Text    1
@STACK              Text    DGROUP
@WORDSIZE           Text    2
MSG              Byte    DGROUP:0000
START              Near    DGROUP:0100

Groups & Segments        Bit Size Align  Combine Class

DGROUP              Group
  _DATA              16  0007 Word     Public  DATA
  _TEXT              16  0108 Word     Public  CODE

lena7 в сообщении #735425 писал(а):
Я уже указала, что надо сделать, чтобы исправить ошибку. Причина ошибки в том, что компилятор хотел сделать DATA отдельным сегментом (что ему диктовала модель small), а линкер -- склеил его с CODE (ибо он делал COM).

Да, это я уже проделывал и все нормально работает.
lena7 в сообщении #735425 писал(а):
Когда в исходном коде есть, скажем, "offset" или ссылка на какие-либо символы, то ассемблер не всегда знает, какими адресами их заменять.

Но тем не менее, ассемблер все равно проставил msg смещение 0:
Код:
MSG              Byte    DGROUP:0000
. Значит линкер это смещение скорректирует.
lena7 в сообщении #735425 писал(а):
Конкретные адреса в конечном исполняемом файле (точнее, в памяти, куда система его загрузит) будут известны лишь линкеру.

В данном случае, жто смещение msg, а значения DGROUP и _TEXT уже будет проставлено загрузчиком после запуска программы, верно?
lena7 в сообщении #735065 писал(а):
либо линкуйте в exe

линкую в .EXE результат почти тотже
Изображение
тут msg уехала на смещение 0108, хотя инструкция по смещению 0003 запишет в dx 0008A. :facepalm: Если не уберать org 100h то msg уехжает на смещение 0208

 Профиль  
                  
 
 Re: Hello world
Сообщение12.06.2013, 11:25 
Заслуженный участник


29/04/12
268
xmaister в сообщении #735640 писал(а):
А разве это не нужно знать чтобы понимать что происходит?

С точки зрения изучения ассемблера и процессора -- нет. Для меня, компилятор + линкер -- это чёрный ящик, берущий исходный код и делающий исполняемый файл. Детали этого процесса зависят от реализации, причём сильно. Есть ассемблеры, которые даже не делят компиляцию и линковку, а сразу собирают исполняемый файл (именно сразу, а не скрывают этот процесс через временные объектные файлы). Например, fasm.

xmaister в сообщении #735640 писал(а):
Значит линкер это смещение скорректирует.

Да.

xmaister в сообщении #735640 писал(а):
а значения DGROUP и _TEXT уже будет проставлено загрузчиком после запуска программы, верно?

В исполняемом файле нет DGROUP и _TEXT. В COM-файле все адреса устанавливает линкер, система его тупо загружает... вы уже знаете как. EXE загружается сложнее. Если нужно, система откорректирует некоторые адреса в соответствии со специальной таблицей, хранящейся в EXE-файле (relocations).

xmaister в сообщении #735640 писал(а):
тут msg уехала на смещение 0108, хотя инструкция по смещению 0003 запишет в dx 0008A.

Вы опять забыли инициализировать ds?

Запомните:
COM: модель tiny, org 100h, линкова в COM.
EXE: модель small и выше, org 100h не надо, инициализировать используемые сегменты, кроме cs (его инициализирует система), линковка в EXE.

 Профиль  
                  
 
 Re: Hello world
Сообщение13.06.2013, 12:30 
Заслуженный участник
Аватара пользователя


03/08/11
1613
Новосибирск
Так, попробую все собрать в "кучу", прочитайте пожалуйста, если не лень. Хотелось бы услышать ваши замечания. Модель памяти tiny подразумевает использование одного сегмента 64кб куда будет загружено код и данные. Если указать модель памяти tiny, то ассемблер зарезервирует первые 100h байт под PSP. Далее, если линковать .EXE линкер потом это PSP загрузит в исполняемый файл, несмотря на то, что линковка в .EXE. При модели памяти tiny и линковки .COM сначала загружается PSP, потом код, а потом данные. Модель памяти small и линковка .COM точка входа в программу должна быть на 100h байтах, при этом линкер не с корректирует адрес элементов сегмента данных, поэтому они буду загружены на 100h байт дальше. Если линковать .EXE объектник в котором указана модель памяти small и явно не загнать
Код:
mov ax, @data
mov ds,ax

то в ds будет находится непонятно что. Т.е. ассемблер только сделает метки где начинается сегмент данных, кода и где расположен стек. В cs адрес будет загружен системой, ds и ss не будут изменятся.

 Профиль  
                  
 
 Re: Hello world
Сообщение13.06.2013, 13:25 
Заслуженный участник


29/04/12
268
xmaister в сообщении #736248 писал(а):
Если указать модель памяти tiny, то ассемблер зарезервирует первые 100h байт под PSP.

Модель говорят ассемблеру, какие будут сегменты и что в них будет находится. Директива "org 100h" говорит ассемблеру: "это место будет в памяти по адресу 100h (в сегменте кода)". Это заставит ассемблер правильно проставлять адреса (по умолчанию он считает, что первая инструкция находится по адресу 0).

xmaister в сообщении #736248 писал(а):
Далее, если линковать .EXE линкер потом это PSP загрузит в исполняемый файл, несмотря на то, что линковка в .EXE.

Ни ассемблер, ни линкер не знают, что такое PSP и никуда его загружать не будут. PSP формируется системой в памяти при загрузке программы. Система записывает его в первые 100h байт некоторого сегмента в памяти. В случае COM система в тот же сегмент загрузит весь COM-файл, а адрес этого сегмента будет записан в cs. В случае EXE адрес сегмента с PSP будет записан в ds, а сам код будет загружен в другой сегмент, начиная с адреса 0 (поэтому для EXE не надо писать "org 100h") -- это будет cs.

EXE можно делать в любой модели. COM только в tiny (вы знаете почему).

xmaister в сообщении #736248 писал(а):
При модели памяти tiny и линковки .COM сначала загружается PSP, потом код, а потом данные.

Да.

xmaister в сообщении #736248 писал(а):
Модель памяти small и линковка .COM

Низя.

xmaister в сообщении #736248 писал(а):
Если линковать .EXE объектник в котором указана модель памяти small и явно не загнать
Код:
mov ax, @data
mov ds,ax

то в ds будет находится непонятно что.

Верно в том смысле, что там будет не сегмент данных, который вам нужен. Но и не мусор: там будет сегмент, в котором записан PSP.

 Профиль  
                  
 
 Re: Hello world
Сообщение14.06.2013, 17:29 
Заслуженный участник
Аватара пользователя


03/08/11
1613
Новосибирск
lena7 в сообщении #736262 писал(а):
xmaister в сообщении #736248 писал(а):
Модель памяти small и линковка .COM

Низя.

Я имел ввиду, что написать .model small а потом линковать в .COM никто не запрещает. Как я понял с Ваших слов линкер склеит DGROUP и _TEXT описанных в объектнике и не станет делать поправку на загрузку PSP.
lena7 в сообщении #736262 писал(а):
Верно в том смысле, что там будет не сегмент данных, который вам нужен. Но и не мусор: там будет сегмент, в котором записан PSP.

Я когда смотрел дебуггер, адрес в ds до и после
Код:
mov ax,@data
mov ds,ax
отличается, соотвественно смещение msg до и после
Код:
mov ax,@data
mov ds,ax
0108 и 0008 соответсвенно. Я думал что обратится к элементу сегмента можно только задав адрес сегмента и смещение конкретного байта и только так. А тут получается можно двумя способоми обратится к строке msg: Если не инициализировать сегмент данных то ds:0108, а если инициализировать, то ds:0008. :facepalm: Я думал что сегменты изолированы друг от друга и сегмент ничего не знает про другие сегменты...

 Профиль  
                  
 
 Re: Hello world
Сообщение14.06.2013, 20:11 
Заслуженный участник


29/04/12
268
xmaister в сообщении #736648 писал(а):
Я думал что сегменты изолированы друг от друга и сегмент ничего не знает про другие сегменты...

Сегменты могут перекрываться.

 Профиль  
                  
 
 Re: Hello world
Сообщение15.06.2013, 01:00 
Заслуженный участник


09/09/10
3729
xmaister в сообщении #736648 писал(а):
Я думал что обратится к элементу сегмента можно только задав адрес сегмента и смещение конкретного байта и только так.

Разумеется. Вот только 8086 имеет 20-битную шину адреса, а оперирует 16-битными значениями. Откуда еще 4 бита берутся? Ответ: в сегментном регистре лежит адрес начала сегмента, сдвинутый на 4 бита вправо. И когда вы адресуете память, указывая сегментный регистр и смещение, физический адрес вычисляется следующим образом: значение сегментного регистра сдвигается на 4 разряда влево и к нему прибавляется смещение.

Поэтому сегмент 0008 лежит, начиная со 128-го байта. И

MOV DX, 0000
MOV AX, 0008
MOV DS, AX
MOV AL, [DX]

загрузит в AL байт по адресу 128, а код

MOV DX, 0080
MOV AX, 0000
MOV DS, AX
MOV AL, [DX]

загрузит в AL байт по адресу... тоже 128!

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 49 ]  На страницу Пред.  1, 2, 3, 4  След.

Модераторы: maxal, Toucan, PAV, Karan, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group