Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

RusFAQ.ru: программирование на языке Assembler


Информационный Канал Subscribe.Ru

RusFAQ.ru: программирование на языке Assembler

Выпуск № 326
от 24.07.2002, 20:50

Администратор:
Имя: Калашников О.А.
URL: Информационный ресурс
ICQ: 68951340
Россия, Москва
О рассылке:
Задано вопросов: 817
Отправлено ответов: 2333
Активность: 285.5 %
[Задать вопрос >>][Регистрация эксперта >>]
[Поиск в базе]


 Список экспертов, ответы которых опубликованы в данном выпуске

Pablo
Статус: Доверительный
Общий рейтинг: 114.54
[Подробней >>]
ASMодей
Статус: Доверительный
Общий рейтинг: 127.69
[Подробней >>]
Топор
Статус: Профессиональный
Общий рейтинг: 118.65
URL: Хорошая Русская Металлическая команда
Телефон: (8462)500298
[Подробней >>]
 
Portnov
Статус: Опытный
Общий рейтинг: 121.78
[Подробней >>]
masquer
Статус: Профессиональный
Общий рейтинг: 160.71
[Подробней >>]
Ayl
Статус: Профессиональный
Общий рейтинг: 125.56
[Подробней >>]
 
UFO
Статус: Опытный
Общий рейтинг: 112
[Подробней >>]
Александр
Статус: Профессиональный
Общий рейтинг: 117.34
[Подробней >>]
Артём Шегеда
Статус: Профессиональный
Общий рейтинг: 121.29
URL: Пристанище неодинокого программиста
[Подробней >>]
 
Kalashnikoff
Статус: Профессиональный
Общий рейтинг: 101.7
URL: Информационный ресурс
[Подробней >>]
Spike
Статус: Доверительный
Общий рейтинг: 115
[Подробней >>]
Sinner
Статус: Начальный
Общий рейтинг: 112.06
[Подробней >>]
 
vitya
Статус: Профессиональный
Общий рейтинг: 114.79
[Подробней >>]


 Краткий перечень вопросов

Вопрос № 782. Здравствуйте, уважаемые Эксперты! Очень прошу не гоните в шею сразу. Я пишу свой загрузчик (DOS, пок... (ответов: 4)
Вопрос № 783. Вот тут читаю Юрова, ну так скажу вродеу по Асму все понятно, язык клевый базару нет (кул, супер, аа... (ответов: 2)
Вопрос № 784. Здравствуйте, господа эксперты. Никто не подскажет, где можно скачать DriverStudio 2.6. Только, pls,... (ответов: 1)
Вопрос № 785. Здравствуйте, уважаемые Эксперты! (Это дополнение к вопросу 782) Гнать то меня в шею может и не стои... (ответов: 5)
Вопрос № 786. Здравствуйте ув. эксперты! В ассемблере я ещё чайник. Помогите понять эту программу(см. ниже) Всем ... (ответов: 7)
Вопрос № 787. Доброе время суток, уважаемые эксперты! Написал я тут программку на Delphi, в которой использ... (ответов: 7)

Вопросов: 6, ответов: 26


 Вопрос № 782

Здравствуйте, уважаемые Эксперты!
Очень прошу не гоните в шею сразу.
Я пишу свой загрузчик (DOS, пока тестирую на 3.5 дискете, в идеале надобно для HDD). И пока не напишу его – не успокоюсь. Это дело я затеял в первую очередь в образовательных целях, а во вторую – есть 4-ка с авардовским биосом, в котором не предусмотрен пароль на загрузку. Так вот, надобно исправить.
По ходу дела возникли вопросы:
Первый вопрос немного запутанный.
1. Что мне делать с org 100h? Прога то, из бут сектора грузится в 0000h:7c00h и нету никакого 100h.
2. Объясните насчет org 100h. (Тоесть как это влияет на offset <переменная>?)
3. Вообще можно ли использовать что-либо (и как) кроме org 100h, например org 7c00h. А то у меня Тлинк ругнулся: “Fatal: Cannot generate COM file : invalid initial entry point address”
4. Я замыслил прогу немного большего размера чем 512 байт. Где мне разместить оставшуюся часть?. И как ее коректно загрузить, чтобы она потом выполнилась?
5. Надобно сохранить старый загрузчик, чтобы и его загрузить и передать ему управление.
Где его сохранить? Тоесть, как определить что сектор пуст и как потом пометить его, чтобы туда больше никто не писал?
Вобщем, в этих вопросах я полный ламер. Надеюсь вылечите.
Приветствуется любая инфа.
ЗЫ Если Эксперты очень помогут с инфой, обещаю полностью обсосаную прогу выложыть на рассмотрение общественности.

Заранее благодарю!


Приложение:


Вопрос отправлен: 20.07.2002, 00:02
Отправитель: Бадян (sba@litech.net)

[Следующий вопрос >>] [Список вопросов]

Отвечает Pablo

Здравствуйте, Бадян!]
Если ты не используешь абсолютные переходы, то org 100h никак не повлияет на код, но обычное ассемблер и не использует таких переходов, а только относительные, на счет команды call для 16-ти бит я не помню, для 32-бит она тоже имеет формат относительного вызова. Также при написании страрайся обойтись без аболютных смещений, если тебе надо проводить чтение из памяти используй, адрес смещения твоего кода от 0, который ты можешь вычислить один раз в начале работы твоей программы, а потом с его помощью работать с и с абсолютными переходами и с чтением из памяти и записью в память. Это по поводу 1 и 2 го пунктов.
По 3-му пункту, org 7c00h не нужен, делай org 100h, а адреса контролируй как написано выше.
По 4 и 5-му пунктам, если ты пишешь загрузчик для партишена то сразу за самим партишеном есть место обычно равное количеству секторов на поверхности(head) минус 1. там и можешь попробовать разместить загрузчик и старый и расширение твоего, если ты используешь boot-sector загрузчие, то нада тебе либо делать размер ФАТа больше чем нуджен и в зарезервированном пространстве размещать загрузчик, либо, АФАЙК как делают другие, в обычном специальном файле размещать оставшуюся часть загрузчика и старый загрузчик!
Я помню у меня тоже была идея загрузчик сделать, но я остановился на дизасемблировании, а также не мог понять какая память занята до того как загрузчик будет загружен БИОСом!

Ответ отправлен: 20.07.2002, 23:13
Отправитель: Pablo


Отвечает ASMодей

Добрый день, Бадян!
У меня была такая же ситуация, поэтому с этой проблемой
я знаком достаточно хорошо, так что отвечаю по порядку:
1. Проще всего написать EXE-шник, поставив ORG 7C00h и
потом вырезать 512 байт любым HEX-редактором.
2. ORG 100h означает, что все содержимое сегмента будет
"сдвинуто" на 256 байт, поэтому вместо offset <...>
получишь 100h+offset <...>.
Это вызовет очень веселый эффект: при тестировании
программа работает, а на месте - нет.
Выход - смотри пункт 1.
3. При компилировании COM-программы ничего кроме ORG 100h
использовать нельзя.
4 и 5. У Floppy и у HDD есть неиспользуемое пространство
в виде нескольких секторов между первым сектором диска
и началом следующей стороны дорожки (по крайней мере
так было во времена DOS). Вот там то и можно разместить
остаток программы и старый загрузчик.
А защитить сектор от записи, к сожалению, никоим
образом невозможно.
Всего хорошего!


Ответ отправлен: 21.07.2002, 20:33
Отправитель: ASMодей


Отвечает Топор

Добрый день, Бадян!
ORG - директива увеличения программного счёичика на столько-то байт. Практически это означает, что при трансляции проги эффективные адреса команд и данных начнутся не с CS:0000h, а спустя столько байт, сколько укажешь. В COM-файлах org 100h делается для того, чтобы оставить место в 256 байт для префикса сегмента программы (PSP), в котором лежит, например, командная строка, ну и ещё кое-какая полезная инфа. Для EXE такое смещение делается для сегмента данных автоматически. Если оно не нужно, то, по моим наблюдениям, можно безболезненно сделать org 0, по крайней мере для EXE, для комов тлинкер действительно может ругаться (а может и нет).


Ответ отправлен: 21.07.2002, 10:18
Отправитель: Топор


Отвечает Portnov

Доброе время суток, Бадян!
Тута Dron пытался свою ось писать, можете сходить на asmdev.narod.ru, там подписаться на его рассылку и скачать архив. Рассылка, правда, чего-то заглохла, но проект вроде бы развивается на http://sourceforge.net/projects/dronix.
1),2).org 100h-директива ассемблеру, указывающая, что ко всем смещениям надо прибавлять 100h.
3) COM-формат не поддерживает другие точки входа. Я бы посоветовал взять Nasm, он позволяет делать вообще все что угодно, поддерживает все существующие инструкции (а то сами знаете, tasm/masm ругаются на вещи вида jmp ffff:fffe, хотя такие инструкции есть), и к тому же имеет сверхмощный макроязык.
4),5)-см. упомянутую рассылку Dron'а, он там много чего интересного про операционки рассказывает.
С уважением, Portnov.

Ответ отправлен: 22.07.2002, 12:24
Отправитель: Portnov


 Вопрос № 783

Вот тут читаю Юрова, ну так скажу вродеу по Асму все понятно, язык клевый базару нет (кул, супер, аааааааааа)!
Ну вообщем так я люблю Асм!
Ну а Вопрос такой, что такое конвеер (так непонятно описано), и почему там все кодируется, ну всмысле переставляется код?
Асм зе Бест!


Приложение:


Вопрос отправлен: 20.07.2002, 00:35
Отправитель: cono (cono@torba.com)

[Следующий вопрос >>] [Список вопросов]

Отвечает masquer

Доброе время суток, cono!
Конвейер - это небольшой участок памяти внутри процессора (кеш L1), куда попадают команды после prefetch выборки, процессор команды для выполнения берет именно оттуда, так как L1 быстрее обычной памяти в десятки раз.
Все это, конечно, упрощенно.

Ответ отправлен: 20.07.2002, 08:58
Отправитель: masquer


Отвечает Ayl

Добрый день, cono!
Конвейер - это быстрая кеш-память процессора. При выполнении программы осуществляется т.н. предвыборка команд из памяти. Процессору же на выполнение команды поступают из конвейера.
Использование конвейера позволяет увеличить скорость выполнения программы в несколько раз за счет уменьшения простаивания процессора для ожидания обращений к памяти (выборка осуществляется параллельно с выполнением команд).
Сброс конвейера осуществляется при выполнении команд перехода любого типа.
Как показала практика, на современных процах уже не проходит трюк с изменением кода следующей команды для изменения логики выполнения программы - умный проц отслеживает это изменение и сбрасывает конвейер. В старых моделях (до 386 точно) этого не происходило.
Программно конвейер недоступен.

Ответ отправлен: 22.07.2002, 13:16
Отправитель: Ayl


 Вопрос № 784

Здравствуйте, господа эксперты.
Никто не подскажет, где можно скачать DriverStudio 2.6. Только, pls, рабочий URL.
Заранее спасибо



Вопрос отправлен: 20.07.2002, 10:08
Отправитель: Gibbel (Gibbel@mail.ru)

[Следующий вопрос >>] [Список вопросов]

Отвечает UFO

Здравствуйте, Gibbel!
fosi.da.ru

Ответ отправлен: 20.07.2002, 14:15
Отправитель: UFO


 Вопрос № 785

Здравствуйте, уважаемые Эксперты!
(Это дополнение к вопросу 782)
Гнать то меня в шею может и не стоит, а вот в TECH Help послать надобно. Почти все о чем спрашивал там и нешел. Дык, появились новые вопросы:
Зачем 2 экземпляра FAT?
А что если... один стереть к ч.м. (тоесть забить своей инфой)?
Теперь что у на есть?
А есть вот что:
0 Boot сектор
1 - 9 1-я копия FAT
10 - 18 2-я копия FAT
19 - 32 Корневой каталог
Насколько это можно порезать без особого вреда?
Как порезать я уже, вроде как, разобрался (wResSects, bFatCnt, wFatSects, lHidSects).
Но все же вопрос: Могу ли я безболезненно крутить этими параметрами?
На чистой дискете, вроде как можно. А как быть если надо не попортить инфу на диске?
Как не старался, но в следующих (после 32-го) секторах ничего спрятать не смог. Видно плохо старался. Или это, в принципе, не возможно?
ЗЫ Конечно прошли времена ДОС, но покопаться в таких вещах всетаки интересно. Не поймите меня привратно, у меня просто щас такое настроение. Мне неделю назад сделали операцию, так что прийдется все оставшееся лето сидеть дома. Благо, хоть за компом сидеть мона.
ЗЗЫ Посмотрите, плиз, приложение.
С уважением, Бадян!


Приложение:


Вопрос отправлен: 20.07.2002, 13:37
Отправитель: Бадян (sba@litech.net)

[Следующий вопрос >>] [Список вопросов]

Отвечает Pablo

Доброе время суток, Бадян!
Нее, не нада 2-й ФАТ забивать своей инфой, лучше зарезервируй место в конце ФАТа! То есть сделай его побольше при форматировании!))))А лучше грузи из файла свою оставшуюся часть!


Ответ отправлен: 20.07.2002, 23:14
Отправитель: Pablo


Отвечает Александр

Приветствую Вас, Бадян!
Ну можно элементарно порезать bFatCnt и размер корневой директории. А всё остальное лучше не трогать. А вторая копия фат используется для восстановления первой, если чего не так. При этом scandisk кажется этим не занимается, в отличие от NDD.


Ответ отправлен: 22.07.2002, 07:15
Отправитель: Александр


Отвечает ASMодей

Доброе время суток, Бадян!
Я тут в предыдущем ответе допустил ошибку: пункты 4 и 5
применимы только для жесткого диска, а у Floppy никакого
свободного пространства нет.
А теперь собственно ответ.
Второй экземпляр FAT используется только если в первом
экземпляре возникла ошибка. В этом случае второй экземпляр
копируется на место первого и дальше работает только
первая FAT.
После 32-го сектора без всяких промежутков начинается
область данных, так что спрятать здесь что-либо вряд ли
удастся. Однако можно спрятать что-нибудь в саму область
данных. Для этого достаточно пометить нужные кластеры в
FAT (в обоих экземплярах) как поврежденные или
зарезервированные, и после этого их можно будет свободно
использовать (естественно только до первого
форматирования).


Ответ отправлен: 22.07.2002, 11:22
Отправитель: ASMодей


Отвечает Portnov

Доброе время суток, Бадян!
Про две копии FAT - все просто, одна запасная. Насколько я знаю, загрузчик Win/DOS проверяет наличие и корректность каждого экземпляра. Есди корректен только один, он копируется на место второго.
С уважением, Portnov.

Ответ отправлен: 22.07.2002, 12:27
Отправитель: Portnov


Отвечает Артём Шегеда

Приветствую Вас, Бадян!
На своём диске ты можешь иметь 1, 2, 3, ... копий FAT. Но так, чтобы указать 2 копии, а вместо второй записать свою инфу - ничего не выйдет.
Хочешь оставить свою инфу - используй параметр wResSects (TechHelp - Boot Sector Layout). Или делай, как сказал ASMодей


Ответ отправлен: 22.07.2002, 12:29
Отправитель: Артём Шегеда


 Вопрос № 786

Здравствуйте ув. эксперты!
В ассемблере я ещё чайник. Помогите понять эту программу(см. ниже)
Всем спасибо!
PS
Если можете объясните по подробнее и попроще.

CSEG segment
assume cs:CSEG, ds:CSEG, es:CSEG, ss:CSEG
org 100h
Start:
jmp Init
Int_21h_proc proc
pushf ;???
cmp ah,9
je Ok_09
popf
jmp dword ptr cs:[Int_21h_vect] ;??????? что такое vect
Ok_09:
push ds ;?
push dx ;?
push cs ;?
pop ds ;?
mov dx,offset My_string
pushf :;?
call dword ptr cs:[Int_21h_vect] ;???????
pop dx
pop ds
popf
iret ;?
Int_21h_vect dd ;???????? что такое ddd
My_string db 'Моя строка!$'
int_21h_proc endp
Init:
mov ah,35h
mov al,21h
int 21h
mov word ptr Int_21h_vect,bx ;?????????????????
mov word ptr Int_21h_vect+2,es ;????????????????
mov ax,2521h ;что это
mov dx,offset Int_21h_proc ;?????
int 21h
mov dx,offset Init ;???
int 27h
CSEG ends
end Start



Вопрос отправлен: 20.07.2002, 14:36
Отправитель: R@ptor (Spinosaur@narod.ru)

[Следующий вопрос >>] [Список вопросов]

Отвечает masquer

Здравствуйте, R@ptor!
CSEG segment
assume cs:CSEG, ds:CSEG, es:CSEG, ss:CSEG
org 100h
Start:
jmp Init
Int_21h_proc proc
pushf ; сохраняем флаги
cmp ah,9
je Ok_09
popf ; восстановим флаги и перейдем на оригинальный вектор
jmp dword ptr cs:[Int_21h_vect] ; вектор - адрес прерывания
Ok_09:
push ds ; перехват функции печати строки
push dx ; с передачей параметров оригинальному
push cs ; вектору
pop ds
mov dx,offset My_string
pushf :; сохраняем флаги
call dword ptr cs:[Int_21h_vect] ; вызов оригинального выктора
pop dx
pop ds
popf
iret ; возврат из прерывания
Int_21h_vect dd ; dd - define double - двойное слово - хранилище для оригинального адреса вектора
My_string db 'Моя строка!$'
int_21h_proc endp
Init:
mov ah,35h
mov al,21h
int 21h ; получим адрес оригинального 21-го прерывания
mov word ptr Int_21h_vect,bx ;и сохраним его bx=al*4
mov word ptr Int_21h_vect+2,es ;es=al*4+2
mov ax,2521h ;устанавливаем для 21-го прерывания
mov dx,offset Int_21h_proc ;новый обработчик Int_21h_proc
int 21h
mov dx,offset Init ; процедура Int_21h_proc остается
int 27h ; резидентной в памяти
CSEG ends
end Start

Ответ отправлен: 20.07.2002, 18:02
Отправитель: masquer


Отвечает Kalashnikoff

Приветствую Вас, R@ptor!
Похоже, эта программа взята из моей книги. Найдите соответствующую главу и прочтите описание. Должно быть все понятно.
Если будут какие-то конкретные вопросы по отдельно взятым операторам - пишите.

Ответ отправлен: 20.07.2002, 19:17
Отправитель: Kalashnikoff


Отвечает Spike

Приветствую Вас, R@ptor!
CSEG segment
assume cs:CSEG, ds:CSEG, es:CSEG, ss:CSEG
org 100h
Start:
jmp Init
Int_21h_proc proc
pushf ;Сохраняет в стеке все флаги (CF, ZF, ...)
cmp ah,9
je Ok_09
popf
jmp dword ptr cs:[Int_21h_vect] ;Int_21h_vect - Вектор на предыдущий обработчик (см. ниже), обычный переход в старый обработчик
Ok_09:
push ds ;Следующие две команды сохраняют используемые регистры,
push dx ; чтобы не нарушить работу прерванной программы
push cs ;Сохранить регистр CS, в нем находится сегментный адрес нашего обработчика
pop ds ;Записать его в DS, эти две команды делают обычную пересылку CS --> DS, т.к. для этого нет прямой команды, это нужно для того, чтобы настроить сегмент данных на наш обработчик
mov dx,offset My_string
pushf : ;Сохраняет в стеке все флаги (CF, ZF, ...), только двоеточие здесь не надо !
call dword ptr cs:[Int_21h_vect] ;Вызов старого обработчика, т.к. состояние стека при вызове прерывания FLAGS, CS, IP, то эти две команды эмулируют это состояние для правильной работы предыдущего обработчика
pop dx
pop ds
popf
iret ;Выход из обработчика прерывания, помимо восстановления адреса возврата, восстанавливает из стека все флаги
Int_21h_vect dd ;Здесь сохраняется адрес предыдущего обработчика, DD - это двойное слово (4 байта), только здесь ошибка, нужно Int_21h_vect dd (?)
My_string db 'Моя строка!$'
int_21h_proc endp
Init:
mov ah,35h
mov al,21h
int 21h
mov word ptr Int_21h_vect,bx ;Т.к. Int_21h_vect указан как двойное слово, то компилятор выдал бы ошибку, а word ptr принудительно изменяет размер операнда (в данном случае на word (dw - слово)) и сохраняет там регистр BX
mov word ptr Int_21h_vect+2,es ;См. описание предыдущей команды, но сохраняет регистр CS со смещением +2, т.к. это сегментный адрес предыдущего обработчика
mov ax,2521h ;25h - команда DOS - получить вектор прерывания, а 21h - это как раз и есть номер прерывания, вектор которого и надо получить, это можно было сделать AH, 25h; AL, 21h; но так компактней
mov dx,offset Int_21h_proc ;OFFSET указывает записать в DX адрес! процедуры Int_21h_proc, в данном случае это наш обрабочик
int 21h
mov dx,offset Init ;В DX адрес! процедуры Init (в данном случае означает конец нашего обработчика прерывания)
int ! 27h ;Не знаю зачем тут !, но он точно не нужен, эта команда завершает работу, оставив в памяти резидентную программу, конец которой указан в DX (см. предыдущую команду)
CSEG ends
end Start


Ответ отправлен: 21.07.2002, 10:53
Отправитель: Spike


Отвечает Pablo

Доброе время суток, R@ptor!
ну это обычный хандлер перехваченного прерывания с номером 21h. Перехватываемая функция 9h. В начале идет проверка на эту функцияю если она то, переход на обработку внутри этой процеддуры, а если нет то дальный прыжок на страый обработчик, адрес которого хранится по адресу Int_21_vect.
В теле анутренней обработки также вызвается старый обработичик но с таким условием чтобы усправление вернулось в этуже функцию. Поэтому там и поставлены pushf и call [Int_21_vect]. В начале этого обработчика ds и dx сохраняется чтобы затем использовать его в нужных целях! Ну я так понимаю что это вывод одной и тойже строки, в переопределенном векторе. И в конце обработчика в ds:dx помещается именно эта строка.
Ну а ниже приведелна программа, которая и переопределяет вектор.


Ответ отправлен: 21.07.2002, 17:01
Отправитель: Pablo


Отвечает Александр

Здравствуйте, R@ptor!
Такие листинги лучше в приложение загоняй. Все комментарии в приложении. А для того, чтобы не задавать таких вопросов неплохо бы сначала книжек почитать. Зубков С.В. "Ассемблер - Язык неограниченных возможностей" или П.И. Рудаков, К.Г. Финогенов "Язык ассемблера: уроки программирования".


Приложение:

Ответ отправлен: 22.07.2002, 07:15
Отправитель: Александр


Отвечает Sinner

Добрый день, R@ptor!
CSEG segment
assume cs:CSEG, ds:CSEG, es:CSEG, ss:CSEG
org 100h
Start:
jmp Init
Int_21h_proc proc
pushf ; сохранение регистра флагов в стек
cmp ah,9
je Ok_09
popf
jmp dword ptr cs:[Int_21h_vect] ; переход на адрес стандартной процедуры обработки 21h
Ok_09:
push ds ; сохранение регистра ds в стек
push dx ; сохранение регистра dx в стек
push cs ; сохранение регистра cs в стек
pop ds ; восстановление регистра ds из стека
mov dx,offset My_string
pushf :;?
call dword ptr cs:[Int_21h_vect] ;вызов стандартной процедуры обработки 21h
pop dx
pop ds
popf
iret ; выход из обработчика прерываний
Int_21h_vect dd ; dd - define double - двойное слово - четыре байта
My_string db 'Моя строка!$'
int_21h_proc endp
Init:
mov ah,35h
mov al,21h
int 21h
mov word ptr Int_21h_vect,bx ; смещение стандартной процедуры обработки прерывания 21h
mov word ptr Int_21h_vect+2,es ; сегмент стандартной процедуры обработки прерывания 21h
mov ax,2521h ;что это
mov dx,offset Int_21h_proc ; установка адреса своей процедуры для обработки прерывания 21h (ds:dx)
int 21h
mov dx,offset Init ; размер оставляемой части памяти для TSR (в котором находится твой обработчик прерывания)
int 27h ; Terminate and Stay Resident
CSEG ends
end Start


Ответ отправлен: 22.07.2002, 09:17
Отправитель: Sinner


Отвечает ASMодей

Здравствуйте, R@ptor!
Обясняю попроще: эта программа подменяет собой обработчик
прерывания INT 21h и при каждом вызове функции вывода
строки символов на экран (09h) выводит на экран свою
строку, то есть ведет себя как типичная
программа-вредитель.
Подробнее о ее структуре можно узнать из литературы по
ассемблеру вообще и по созданию резидентных программ в
частности.


Ответ отправлен: 22.07.2002, 11:23
Отправитель: ASMодей


 Вопрос № 787

Доброе время суток, уважаемые эксперты!
Написал я тут программку на Delphi, в которой используется массив
типа int64.
Возникла необходимость часть кода для ускорения перевести на ASM.
Первый вопрос состоит в том, можно ли в ассемблерной вставке
использовать переменные типа int64 и если нет, то какой вы
предлагаете выход?
Второй вопрос. Нужно для массива типа int64 Mas[0..63]
сделать следующую вещь:
Mas[0]=1 shl 1;
Mas[0]=1 shl 2;
...
Mas[63]=1 shl 63;
Проблема состоит в том, что в shl в качестве параметра используются
только младшие 5 бит (Operand=Operand and 31).
Каким же образом мне получить сдвиг на больше, чем 32 бита?
Буду благодарен за любой совет.
С уважением, Serg.



Вопрос отправлен: 20.07.2002, 18:32
Отправитель: serg

[Следующий вопрос >>] [Список вопросов]

Отвечает masquer

Приветствую Вас, serg!
Если использовать MMX, то можно, иначе пару регистров использовать, например eax, edx.
Я вообще не понял, что ты хочешь сделать, на каком-то одном языке напиши, что есть, и что должно получиться.
У shl синтаксис несколько иной "shl eax, 3" - например так, сдвигает eax на 3 бита влево.

Ответ отправлен: 20.07.2002, 19:15
Отправитель: masquer


Отвечает Pablo

Добрый день, serg!
Насколько я помню из ассемблера то shl eax, 31 == shl eax, 63, то есть старшая часть при сдвиге сбрасывается.
Ну а в такой ситуацие как у тебя тебе надо как то записывать в массив не пару edx:eax, а eax:edx, где edx = 0, а eax получается вследствие вычисления shl eax, n.
Ведь в формате __int64 обычно используется пара edx:eaxб впрочем иногда и другие регистры тоже используются. Точнее эта пара edx:eax используется при возвращении числа __int64 из какой либо функции.
Но как это на паскале сделать не знаю, если там есть вставки ассемблерные, то можешь сделать так: объявить инициализирующую функцию, например MasInit, которая будет возвращать пару edx:eax. А в этой функции ты будешь возвращать для значений n < 32 edx:eax, а для значений n > 31 eax:edx, значения которых описаны выше.


Ответ отправлен: 21.07.2002, 17:01
Отправитель: Pablo


Отвечает Александр

Добрый день, serg!
Я так понимаю, что тебе надо установить по одному биту в каждом элементе массива. Можно конечно пользоваться и арифметическим сдвигом. Только для больших данных это будет shld. Её формат shld rm16/32, r16/32, imm/cl.
Осуществляет сдвиг двойного слова, задаваемого первыми двумя операндами. Но величина сдвига всё равно не должна превышать 31. Поэтому тебя спасёт команда bts, устанавливающая в 1 значение нужного тебе бита:
bts r/m, r/m
Первый операнд либо регистр, либо указатель на строку бит. Собственно то, что надо изменить. А второй операнд, либо непосредственное байтовое значение, либо регистр любой имеющейся разрядности. Указывает на номер изменяемого бита. Кроме прочего она устанавливает флаг CF в зависимости от значения указанного бита.


Ответ отправлен: 22.07.2002, 07:15
Отправитель: Александр


Отвечает vitya

Здравствуйте, serg!
ну с первыми 31 элементом проблем нету. А дальше поступаешь так, сначала все в цикле сдвигаешь на 31 разряд влево, а потом в цикле от 1 то 31 по нарастающей сдвигаешь остальные элементы массива.

Ответ отправлен: 22.07.2002, 09:07
Отправитель: vitya


Отвечает ASMодей

Приветствую Вас, serg!
Насчет первого вопроса сказать ничего не могу, так как
с Delphi не дружу, а по второму вопросу отвечу.
Если величина сдвига определяется еще на этапе компиляции
программы, то можно использовать следующий макрос:
SSHL macro HiReg,LoReg,count
if count gt 31
shld HiReg,LoReg,31
shl LoReg,31
shld HiReg,LoReg,count-31
shl LoReg,count-31
else
shld HiReg,LoReg,count
shl LoReg,count
endif
endm
Если же смещение определяется только во время исполнения
программы, то нужно использовать такой макрос:
DSHL macro HiReg,LoReg,count
LOCAL l1
mov cl,count
cmp cl,31
jbe l1
shld HiReg,LoReg,31
shl LoReg,31
sub cl,31
l1: shld HiReg,LoReg,cl
shl LoReg,cl
endm
Использовать их очень просто, например:
SSHL eax,ecx,25
или
DSHL edx,ebx,48
(здесь в регистрах EAX, EDX находится старшая часть
операнда, а в регистрах ECX,EBX - младшая).


Ответ отправлен: 22.07.2002, 11:24
Отправитель: ASMодей


Отвечает Артём Шегеда

Здравствуйте, serg!
Я, конечно, мог бы написать правильный код - вот только зачем писать то, что уже неаписано и работает? Знаешь асм - поймёшь то, что находится в этих файлах (благо, Delphi идёт с исходниками библиотек):
"C:/Program Files/Borland/Delphi5/Source/Rtl/Sys/_ll.asm"
"C:/Program Files/Borland/Delphi5/Source/Rtl/Sys/readint64.asm"


Ответ отправлен: 22.07.2002, 12:12
Отправитель: Артём Шегеда


Отвечает Portnov

Доброе время суток, serg!
1) Естественно, да. Int64 - это квадрослово. Напр.,
chislo dq 123456789ABCDEF0h
Другой вопрос, что производить действия с такими числами посложнее. Напр., сложение:
mov eax,chislo1_low
mov edx,chislo1_hi; edx:eax=chislo1
mov ebx,chislo2_low
mov ecx,chislo2_hi; ecx:ebx=chislo2
add eax,ebx
adc edx,ecx; edx:eax=chislo1+chislo2,
если только я нигде не напутал. Но не короче точно.
2) Очень просто! Делать два сдвига! Только вот делать сдвиг квадрослова - довольно занятная задачка. Нет, это вполне можно, но... Раз уж вы хотите сдвигать единицу, то проще будет посчитать все результаты сдвигов и их загружать.
С уважением, Portnov.

Ответ отправлен: 22.07.2002, 12:28
Отправитель: Portnov



Форма отправки вопроса

Внимание!
Форма может работать некорректно в почтовых программах "Microsoft Outlook" и "Microsoft Outlook Express". В программе The Bat! подобные формы не работают вообще!
После нажатия на кнопку "Отправить", будет открыто второе окно. Заметьте, что в некоторых браузерах могут стоять запреты на открытие других окон, а также "чрезмерное" кэширование данных, при этом факт отправки Вашего вопроса стоит под сомнением.
Мы рекомендуем открывать рассылку в программе Internet Explorer 5.0+ или отправлять вопросы с сайта по адресу: http://rusfaq.ru/cgi-bin/Message.cgi.

© 2002 Команда RusFAQ.ru.

 Персональные данные

Ваше имя:

Ваш e-mail:

Опубликовать мой e-mail в рассылке


 Вопрос и дополнение

Ваш вопрос:


Приложение (если необходимо):


Получить ответов:


 Выбор рассылки

Программисту
Assembler (44)
C / C++ (33)
Perl (10)
Delphi (18)
Pascal (31)
Basic / VBA (11)
Java / JavaScript (10)
PHP (8)
MySQL / MSSQL (11)
Пользователю
Windows 95/98/Me (44)
Windows NT/2000/XP (34)
"Железо" (36)
Поиск информации (18)
Администратору
Windows NT/2000/XP (17)
Linux / Unix (16)
Юристу
Гражданское право (7)
Семейное право (3)
Трудовое право (7)
КоАП (2)

Отправить вопрос всем экспертам выбранной рассылки.




be number one Яндекс цитирования

© 2002 Россия, Москва. Авторское право: RusFAQ.ru


http://subscribe.ru/
E-mail: ask@subscribe.ru
Отписаться
Убрать рекламу

В избранное