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

Ассемблер? Это просто! Учимся программировать


РАССЫЛКИ ПОРТАЛА RUSFAQ.RU

/ КОМПЬЮТЕРЫ И ПО / Языки программирования / Assembler (Ассемблер)

Выпуск № 572
от 14.10.2006, 01:05

Администратор:Калашников О.А.
В рассылке:Подписчиков: 354, Экспертов: 35
В номере:Вопросов: 6, Ответов: 16


Вопрос № 58103: Вопрос такой. Немного хочу доработать программку из книги. Работа с файлами, там файл октрывается, происходит чтение в памяти, затем закрывается. Мне вот захотелось еще и вывести то что он записал в память. Но столкнулся с проблемой $. Так как эт...
Вопрос № 58118: Здравствуйте ! Как можно избежать такой ошибки: relative jump out of range ?...
Вопрос № 58119: Здравствуйте ! Не подскажете, почему не удается упакопать exe-проги, написанные на асме программой aspack ?...
Вопрос № 58122: mov dx,offset message1 mov ah,9 int 21h ; вывести приглашение ко вводу message1 mov dx,offset buffer mov ah,0Ah int 21h ; считать строку символов в буфер mov dx,offset crlf mov ah,9 int 21h ; перевод строки ...
Вопрос № 58190: Здравствуйте ! Допустим у меня есть две строки. Как скопировать строку kkk в конец строки eee ?...
Вопрос № 58191: Здравствуйте ! Кто-нибудь, откройте мне военную тайну: что такое КУЧА ?...

Вопрос № 58.103
Вопрос такой.
Немного хочу доработать программку из книги. Работа с файлами, там файл октрывается, происходит чтение в памяти, затем закрывается. Мне вот захотелось еще и вывести то что он записал в память. Но столкнулся с проблемой $. Так как этого знака нет прерывания dos вместе с тем, что было в файле выводит мусор. Вывод я делал так:
mov dx, offset buffer ; в buffer находится то что считали из файла
mov ah,9
int 21h
Я захотел добавить знак '$' в конец текста.
mov di,3
mov es, offset buffer
mov es:[di], '$'
А затем вывести buffer, как выше показывал. В итоге все равно мусор.
И еще родился второстепенный, но более важный для меня вопрос, как узнать сколько байт было считано из файла в память.
Полный листинг в приложении.

Приложение:

Отправлен: 08.10.2006, 10:05
Вопрос задал: Torsten (статус: 1-ый класс)
Всего ответов: 2
Мини-форум вопроса >>> (сообщений: 3)

Отвечает: Олег Владимирович
Здравствуйте, Torsten!

Результат функции 3F - не только заполнение буфера, но и выдача в AX количества прочитанных байт. Кстати, если AX=0, то достигнут конец файла.
Тепеь о более важном: зачем mov es,dx ? На какой сегмент вы хотите установить ES? Сегмент, номер которого совпадает со смещением DX, совсем не там, где вы ожидали (абсолютный адрес его в 16 раз больше)
Предлагается сразу после вызова прерывания INT 21h, считывающего данные в буфер, делать: MOV BX,AX; MOV DI,OFFSET Buffer; MOV byte ptr [BX+DI],'$'
Кстати, а где ваш буфер? buffer - это константа, численно равная 34 - коду '$'. Память для неё не выделяется, а везде, где вы пишете buffer, компилятор подставляет 34. Её надо определять не директивой EQU, а DB. И почему нет проверки JC после считывания?

Удачи!
---------
Факультет ПМ-ПУ - лучший в СПбГУ!
Ответ отправил: Олег Владимирович (статус: 4-ый класс)
Ответ отправлен: 08.10.2006, 10:30
Оценка за ответ: 5
Комментарий оценки:
Спасибо, во всем разобрался. Ну или так скажем почти во всем, по крайне мере задачу вывода я решил с помощью вашего ответа.
В мини-форуме сейчас напишу ответы на ваши вопросы в ответе :) каламбур :)

Отвечает: ENS
Здравствуйте, Torsten!
Для начала отвечу на второй вопрос. Количество байт записанное в память из файла Вы указали сами в CX функции 3Fh. А на счет вывода без мусора.
Мы знаем сколько занимает текст в памяти(т.к.Вы сами указывали сколько байт считать из файла), Увеличиваем это число на 1 и пишем бакс.
;0fde8h-количество байт.
mov di,0Fde9h;то есть на 1 увеличили
mov al,'$'
add di,byte ptr buffer
stosb; заносим бакс в es:[di] т.е после текста из файла.
Все это дело надо вставить после считывания из файла ,а то что Вы написали убрать.
Надеюсь я Вам помог.

Приложение:

---------
Если нет выхода ищу вход.

Ответ отправил: ENS (статус: 6-ой класс)
Ответ отправлен: 08.10.2006, 19:41
Оценка за ответ: 4
Комментарий оценки:
Начнем с того, что компилятор MASM 6.11 ругается на строчку:
add di,byte ptr buffer
Invalid instruction operands
Думаю вы просто забыли offset добавить
add di, offset byte ptr buffer
Способ интересный, но какой-то не очевидный. Было бы очень интересно узнать, что работает быстрее такая вставка бакса, или та которую я хотел с самого начала, и которую описал Олег Владимирович.

И самое главное, утверждение о том, что я прочил 0fde8h (65000) байт не верно. Я хотел прочитать 65000 байт, но в файле их может быть меньше или больше. Прерывание возвращает количество реально считанных байт в регист ax.
Вот за эту ошибку ставлю "4", а не "5".


Вопрос № 58.118
Здравствуйте ! Как можно избежать такой ошибки: relative jump out of range ?
Отправлен: 08.10.2006, 12:40
Вопрос задал: Whiteman (статус: Посетитель)
Всего ответов: 3
Мини-форум вопроса >>> (сообщений: 1)

Отвечает: Евгений Иванов
Здравствуйте, Whiteman!

В TASM используй директивы:
SMART
VERSION T510

и два и более прохода - ключ /m9

удачи!
---------
Что имеем - не храним, потерявши - плачем
Ответ отправил: Евгений Иванов (статус: Профессор)
Россия, Нижний Новгород
Тел.: +78313145721
Организация: M2Media.ru
Адрес: Нижний Новгород, ул.Малая Ямская, 66
WWW: Eugene Ivanov
ICQ: 214889076
----
Ответ отправлен: 08.10.2006, 12:56

Отвечает: Олег Владимирович
Здравствуйте, Whiteman!

Можно ошибочный jump (обычно условный, для JMP труднее добиться такой ошибки под DOS) , допустим JC @label, заменить на:
JNC @temp1
JMP @label
temp1:

Удачи!
---------
Факультет ПМ-ПУ - лучший в СПбГУ!
Ответ отправил: Олег Владимирович (статус: 4-ый класс)
Ответ отправлен: 08.10.2006, 16:25

Отвечает: Вiктор
Здравствуйте, Whiteman!
полностью согласен с мнением Олега Владимировича, могу только добавить что ошибка условного прыжка (JC, JNE, JZ, JO и т.п.) возникает когда вы хотите прыгнуть более чем на 127 байт назад или более чем на 128 бит вперёд. Это потому что смещение в комаднах условного прыжка (для 0х86) задаётся одним байтом со знаком. А для инструкции JMP (безусловный прыжок) смещение задаётся 2-мя байтами, поэтому он способен покрыть намного большее количество байт кода. Как переделать условные прыжки чтобы преодолеть 128-байтовое ограничение, вам уже рассказал Олег Владимирович. Это вариант если надо прыгать более чем на 128 байт, но ещё вариант - переписать код так, чтобы тот кусок кода, через который вам надо перепрыгнуть, занимал меньше 128 (127 для прыжка по меньшим адресам) байт.
Р.S. Вроде бы могут возникнуть ошибки при безусловном прыжке через сегменты, но я сейчас не могу вспомнить подходят ли они под этот тип ошибки и не могу вспомнить примеры.
---------
можно ли считать баги двигателем прогресса, если учесть, что они заставляют улучшать программы?
Ответ отправил: Вiктор (статус: 6-ой класс)
Ответ отправлен: 08.10.2006, 23:45


Вопрос № 58.119
Здравствуйте ! Не подскажете, почему не удается упакопать exe-проги, написанные на асме программой aspack ?
Отправлен: 08.10.2006, 12:41
Вопрос задал: Whiteman (статус: Посетитель)
Всего ответов: 1
Мини-форум вопроса >>> (сообщений: 0)

Отвечает: Brutaller
Здравствуйте, Whiteman!
Если имеются ввиду проги под Win32, то UPX и ASpack отказываются их паковать по причине и так их малого размера. Некоторые упаковщики вообще например из проги размером в 2кб могут сделать 3кб и более.
Для прог написанных на асме рационально использовать такие упаковщики как например FSG 2.0 или MEW, т.к. размер кода их распаковщика исчисляется в десятках байт! Если верить автору FSG, то код распаковщика всего 158 байт.
FSG можно взять здесь http://www.xtreeme.prv.pl/
MEW на http://northfox.uw.hu/
Ответ отправил: Brutaller (статус: 3-ий класс)
Ответ отправлен: 08.10.2006, 14:08


Вопрос № 58.122
mov dx,offset message1
mov ah,9
int 21h ; вывести приглашение ко вводу message1
mov dx,offset buffer
mov ah,0Ah
int 21h ; считать строку символов в буфер
mov dx,offset crlf
mov ah,9
int 21h ; перевод строки

messagel db "Десятичное число: $"
err_msg db "Ошибка ввода"
crlf db 0Dh,0Ah,'$'
buffer db 6 ; максимальный размер буфера ввода
blength db ? ; размер буфера после считывания
bcontents: ; содержимое буфера располагается за
; концом СОМ-файла
end start
Здравствуйте! После ввода символов и считывания их, в blength окзывается количество введенных символов, каким образом это происходит?
Отправлен: 08.10.2006, 13:39
Вопрос задал: Xabar (статус: Посетитель)
Всего ответов: 3
Мини-форум вопроса >>> (сообщений: 0)

Отвечает: Евгений Иванов
Здравствуйте, Xabar!

Десятая функция ДОС записывает их в это место.

Всего хорошего!
---------
Что имеем - не храним, потерявши - плачем
Ответ отправил: Евгений Иванов (статус: Профессор)
Россия, Нижний Новгород
Тел.: +78313145721
Организация: M2Media.ru
Адрес: Нижний Новгород, ул.Малая Ямская, 66
WWW: Eugene Ivanov
ICQ: 214889076
----
Ответ отправлен: 08.10.2006, 13:43

Отвечает: ENS
Здравствуйте, Xabar!
Так и должно быть.Функция 0Ah возвращает количество введенных символов во второй байт буфера, т.е blength. После объявления buffer db 6 надо зарезервировать место так
db 6 dup(?)

---------
Если нет выхода ищу вход.
Ответ отправил: ENS (статус: 6-ой класс)
Ответ отправлен: 08.10.2006, 19:42

Отвечает: Вiктор
Здравствуйте, Xabar!
согласен с мнениями уже ответивших экспертов, эта функция считает количество введённых символов и говорит его вам, чтобы вы знали какой длины эта строка.
---------
можно ли считать баги двигателем прогресса, если учесть, что они заставляют улучшать программы?
Ответ отправил: Вiктор (статус: 6-ой класс)
Ответ отправлен: 09.10.2006, 00:01


Вопрос № 58.190
Здравствуйте ! Допустим у меня есть две строки. Как скопировать строку kkk в конец строки eee ?

Приложение:

Отправлен: 09.10.2006, 00:40
Вопрос задал: Whiteman (статус: Посетитель)
Всего ответов: 3
Мини-форум вопроса >>> (сообщений: 1)

Отвечает: ADSota
Здравствуйте, Whiteman!

Так как вы написали в приложении - ккк и так стоит в конце еее... Тут ничего даже менять не надо. Копируется просто - в DS:SI ставится адрес строки ккк, в es:di - адрес конца строки eee, в cx - количество символов для копирования и выполняется строчное копирование: "rep movsb":

mov di,eee + 5
mov si,kkk
mov cx,4
rep movsb
---------
Открыть глаза навстречу солнцу
Ответ отправил: ADSota (статус: Специалист)
Ответ отправлен: 09.10.2006, 08:53
Оценка за ответ: 5

Отвечает: Pinkbyte
Здравствуйте, Whiteman!

Вам необходимо выделить буфер после строки eee, иначе вы можете затереть другие переменные.

buffer db 3 dup (0)

и потом уже копировать...
---------
Нейтральность - высшее достижение сознания
Ответ отправил: Pinkbyte (статус: 1-ый класс)
Ответ отправлен: 10.10.2006, 18:29

Отвечает: ENS
Здравствуйте, Whiteman!
При копировании cтрочки kkk в eee. Строка kkk может затереть байты после eee(т.е.kkk а kkk может еще понадобиться)
Надо зарезервировать место после eee (в нашем случае 4 байта) db 4 dup(0).А далее использовать инструкции для работы со строками MOVSB.
MOV CX,04h; количество байт в kkk
MOV DI,eee+5; сдвинули указатель что бы не затереть eee
MOV SI,kkk; адрес kkk
rep stosb; исполнить CX раз перемещение

---------
Если нет выхода ищу вход.
Ответ отправил: ENS (статус: 6-ой класс)
Ответ отправлен: 10.10.2006, 19:58


Вопрос № 58.191
Здравствуйте ! Кто-нибудь, откройте мне военную тайну: что такое КУЧА ?
Отправлен: 09.10.2006, 00:43
Вопрос задал: Whiteman (статус: Посетитель)
Всего ответов: 4
Мини-форум вопроса >>> (сообщений: 0)

Отвечает: ADSota
Здравствуйте, Whiteman!

"КУЧА" - это область памяти для временных переменных (если правильно перевел название). Используется, когда по тем или иным причинам не удается использовать стек.
---------
Открыть глаза навстречу солнцу
Ответ отправил: ADSota (статус: Специалист)
Ответ отправлен: 09.10.2006, 08:47

Отвечает: n0name
Здравствуйте, Whiteman!
Куча - это область памяти небольших размеров, до мегабайта, более не эффективно.
Процесс может иметь несколько куч. В каждой можно выделить память. Если нужно большие объемы памяти, то VirtualAlloc.
Создать Кучу - HeapCreate, удалить - HeapDestroy, выделить память в куче HeapAlloc, освободить HeapFree.
Ответ отправил: n0name (статус: 6-ой класс)
Ответ отправлен: 09.10.2006, 14:23

Отвечает: Луковкин Николай Иванович
Здравствуйте, Whiteman!
Постараюсь объяснить своими словами - что такое КУЧА:
Во время выполнения программы у каждого программного потока имеется стек, в котором хранятся локальные переменные. Для глобальных переменных (и переменных, слишком больших для размещения в стеке) программе требуется другая область памяти, доступная для записи. Объем необходимой памяти может быть неизвестен на стадии компиляции, поэтому такие СЕГМЕНТЫ часто выделяются на стадии выполнения специальной системной функцией. Все СЕГМЕНТЫ с поддержкой записи обозначаются термином - КУЧА.
P.S. Для хакера термин - переполнение КУЧИ, как для нас с Вами бутерброд с черной икрой!
---------
Главным критерием эффективности того или иного пути может служить лишь то, достиг или нет крекер конечного результата!!!
Ответ отправил: Луковкин Николай Иванович (статус: 2-ой класс)
Ответ отправлен: 09.10.2006, 22:06

Отвечает: ENS
Здравствуйте, Whiteman!
Куча - это облать памяти, причем небольшая, изпользуемая для хранения временных переменных, но не стек.

---------
Если нет выхода ищу вход.
Ответ отправил: ENS (статус: 6-ой класс)
Ответ отправлен: 10.10.2006, 19:58


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

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

* Код программы, выдержки из закона и т.п. дополнение к вопросу.
Эта информация будет отображена в аналогичном окне как есть.

Обратите внимание!
Вопрос будет отправлен всем экспертам данной рассылки!

Для того, чтобы отправить вопрос выбранным экспертам этой рассылки или
экспертам другой рассылки портала RusFAQ.ru, зайдите непосредственно на RusFAQ.ru.


Форма НЕ работает в почтовых программах The BAT! и MS Outlook (кроме версии 2003+)!
Чтобы отправить вопрос, откройте это письмо в браузере или зайдите на сайт RusFAQ.ru.


© 2001-2006, Портал RusFAQ.ru, Россия, Москва.
Идея, дизайн, программирование: Калашников О.А.
Email: adm@rusfaq.ru, Тел.: +7 (926) 535-23-31
Авторские права | Реклама на портале
Версия системы: 4.37 от 04.10.2006
Яндекс Rambler's Top100

В избранное