Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Asm: Общие вопросы > Помогите с линковкой


Автор: Гость_Andrey 4.6.2004, 18:39
Помогите кто может.
Скачал и установил MASM 6.13. Вроде бы все круто, написал мин. приложение, откомпилировал:
ml.exe /c /coff first.asm
Пытаюсь линковать:
link.exe firs.obj /subsystem:windows
а он говорит что неизвестный параметр /subsystem

Автор: Гость_Andrey 4.6.2004, 18:55
Это не оригинальный линковщик. (Не тот который ставился с MASM), а скаченый с какогото сайта. Оригинальный линковщик вообще ничего не выдает и ничего не делает.
Можно написать для него любую строку, любую абракадабру, а он проглотит и даже ничегоне напишет.

Автор: Chingachguk 5.6.2004, 10:17
Батник:

[code]
@echo off

if exist %1.obj del %1.obj
if exist %1.exe del %1.exe

\masm32\bin\ml /c /coff %1.asm
if errorlevel 1 goto errasm

if not exist rsrc.obj goto nores

\masm32\bin\Link /SUBSYSTEM:WINDOWS %1.obj rsrc.obj
if errorlevel 1 goto errlink

dir %1.*
goto TheEnd

:nores
\masm32\bin\Link /SUBSYSTEM:WINDOWS %1.obj
if errorlevel 1 goto errlink
dir %1.*
goto TheEnd

:errlink
echo _
echo Link error
goto TheEnd

:errasm
echo _
echo Assembly Error
goto TheEnd

:TheEnd

pause
[quote]

Автор: Гость_Andrey 6.6.2004, 15:46
Thaks.
Правда приведенный батник не понадобился.
Я просто скачал и установил дополнение MASM - 2005 по ссылке http://www.wasm.ru/tools/7/BIN.2005.zip.

По мимо всякой прочей лабуды там оказался ликовщик, который не ругается на параметр /SUBSYSTEM:WINDOWS.
smile.gif

Еще один вопрос возник:
Сегментные регистры FS,GS и т.д. можно ли использовать как временные переменные (под Windows). Или лучше этого не делать. Другое применение в небольших программах для них придумать сложно.

Автор: Chingachguk 6.6.2004, 16:35
Цитата
Сегментные регистры FS,GS и т.д. можно ли использовать как временные переменные (под Windows). Или лучше этого не делать. Другое применение в небольших программах для них придумать сложно.


Что значит - делать или не делать ? Что делать ? Вообще-то они предназначены для хранения сегментов (селекторов). Однако win32-приложения не используют оперирование сегментами (архитектура такая) - не то, что в DOS. Если, к примеру, в дос было понятие 64-килобайтного сегмента и программа получала при запросе памяти ее адрес в виде комбинации сегмент:смещение, то в win при аналогичном запросе она получает лишь 32-х битный offset. Это не означает, что ОСЬ отдает все адресное пр-во во владение программам в виде большого массива: контроль ведется на уровне страниц.

Однако при попытке программировать системные вещи уже начинаешь использовать селектора. Например, такая вещь, как SEH - обработчик исключений для user-кода. Например, при таком обрамлении на Дельфи:

try

...

exception:

...

finally:

Компиллятор воткнет в прологе установку собственного обработчика ошибок, и в finally восстановит прежний обработчик. Все структуры для установки SEH лежат в FS:[0...], те селектор этот используется. Или при вызове GetTickCount система (я про win98) вытащит инкрементальный счетчик из ~ GS:[0]. SEH часто используют защиты уровня приложения для самораспаковки, что немного затрудняет их анализ ;)

Даже при программировании драйверов нечасто используешь манипуляции с селекторами. Однако иногда их свойства могут быть полезны...


Автор: Гость_Andrey 8.6.2004, 09:48
Ну драйвера я пока не программирую. Пока я занимаюсь более приземленными вещами.
А имел ввиду я следующее. Например, в нектором месте программы мне нужно сохранить некторый регистр, что бы потом его использовать. Конечно я могу сделать
push xx
......
pop xx

Все отлично. Но - этот участок кода находиться в очень большом цикле, да еще в двойном (цикл вложенный в цикл). Так как с регистрами работа происходит гораздо быстрее, то нельзя ли мне не в стек запихивать свою переменную, а, например, в fs?
Я конечно понимаю, что даже если я этого добьюсь, то наврядли замечу существенного ускорения, но все же хочется усовершенствовать по максимому.

Я пробовал, вроде работает. Правда не всегда. sad.gif
Возможно это из-за того, что не разрешается различные страницы использовать. Может он воспринимает это как селектор страницы и получается исключение по доступу к неправильному участку памяти (ну в смысле не к своему). В общем не знаю, поэтому и решил спросить, может что скажете по этому поводу.

Автор: _Chingachguk_ 8.6.2004, 10:18
Цитата
Может он воспринимает это как селектор страницы и получается исключение по доступу к неправильному участку памяти


Совершенно верно ! Немного не так, другое исключение - но в целом верно, в сегментный регистр нельзя писать произвольные числа. Это можно проверить циклическим присвоением.

Насчет быстродействия. Это не лучший способ по многим причинам. Хотя бы по тем, что при команде

mov eax,ebx ; Сохранить ebx в eax

процессор НЕ выполняет проверок на корректность значения,
а вот при команде:

mov fs,ax

очевидно, выполняет проверки на корректность селектора, и очень вероятно, тратит больше времени. Точнее - см. таблицу времени выполнения команд.

К тому же в 32-х битном коде многие значения не помещаются в 16-ть бит селектора. Команды же со стеком сейчас, на современных процессорах, работают очень быстро (1-2 такта). Гораздо больший вклад в быстодействие вносит конвеер - спариваемость команд. Кратко принцип такой: если вторая из двух команд требует результата выполнения первой, то процессор не может выполнить эти команды параллельно и быстродействие снижается. Например, P3 800 может работать на некоторых алгоритмах НЕ МЕДЛЕННЕЕ P4 1600 !

Пример неспаренных команд:

mov eax,[ebx] ; use eax
mov ecx,[ebx+eax] ; use eax - AGI !

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


Автор: Гость_Andrey 30.6.2004, 18:08
Возникли еще глупые вопросы (куда же без них smile.gif)
1. Можно ли с помощью LOCAL делать локальные массивы (в стеке в смысле). Если да, то каким образом. Сколько не пробовал, ничего не получается.
2. Каким образом можно сделать динамический массив. Т. е. вопрос в том, как работать с динамической памятью (массивы не в стеке, а именно в динамической памяти). Просто появилась задача - есть набор строк, а их число до момента выполнения программы неизвестно. Причем работать с этими строками будут разные функции на протяжении работы всей программы. Так что стек для хранения здесь как то не подходит.

Автор: oleg1973 1.7.2004, 09:16
Цитата
1. Можно ли с помощью LOCAL делать локальные массивы (в стеке в смысле). Если да, то каким образом. Сколько не пробовал, ничего не получается.


proc SomeShit
enter
тут код и все такое
return

вот и будет массив в стеке для некой процедуры Someshit
Цитата
Каким образом можно сделать динамический массив

выделив заранее бОльший кусок памяти чем может понадобится

p.s.
я вот только господа асемблершики не пойму почему так все любят пихать данные в стек? (имеются ввиду массивы всякие) этоже не совсем удобно.
поясню свою точку зрения
1) если массив с известным размером, можно просто сделать алокейш памяти ,на esi к примеру поинтер и работай себе спокойно
2) если массив с неизвестным размером (нууу очень редко бывает при програмировании на асме), поступаем аналогично выделив кусок памяти и меняя его размер по необходимости

преимушества на мой взгляд очевидны
если в системе ну нету больше памяти то она и не выделится и прога ваша спокойно завершится, а вот размер стека и размер ваших данный система контролировать не может, так что можно получить и переполнение

Автор: Guest 3.7.2004, 11:39
Thank you!!!
Я так и сделал. Выделил нужный кусок памяти и все стало нормально.
А со стеком (массивы в стеке хранить), это действительно не очень хорошо. Просто это очень легко и удобно (уменьшил esp и все в порядке).
Для небольших массивов (имя с клавы спросить, или еще чего), очень удобно.

Автор: oleg1973 3.7.2004, 12:28
ну дык для мелких массивов делай секцию неинициализированных данных
она место в фале не занимает, а ОС при загрузке сама выделит память для массива, таким образом избежиш гемороя с GlobalAlloc и прочим

Автор: MORRA 2.11.2004, 05:51
О хранении промежуточных данных в сегментых регистрах:

Теоретически можно, но на практике лучше воспользоваться стеком или переменными в памяти, например, так:

main:

;если изначально переменная размером с байт в регистре AL

mov var, al

...

mov al, var

end main
var db 0

и зачем, спрашивается, изобретать велосипед?


А все дело в том, что сегментные регистры имеют так называемую теневую часть размером с двойное слово, которая, фактически, недоступна, но представляет собой некоторое подобие дескриптора сегмента, а их этого следует, что любое значение в сегментном регистре просто так "не сходит с рук" :)

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)