149ea694a792f3ad2caaf77077a0df58 Спорящая с богом
Пришла оценка за гос по ассемблеру: 97. Похоже, что сам экзамен я написала на 100, потому как маген ("защитная" оценка по итогам семестра и внутренним экзаменам) у меня был 94.
Именно в виде кода - нет, ей описание необходимых прерываний. Хочешь?
А вообще открою маленький секрет: пишешь прогу на Си, а потом построчно заменяешь инструкции на ассемблерные. Очень хороший способ не запутаться в структуре программы.
Да со структурой-то всё понятно, я себе схемы начертил. На си эту прогу написать - раз плюнуть. А тут нужно всё самому, ручками =) Проблема именно в чтении =) У меня какие-то странные выкрутасы с маркером чтения происходят, например, если его поставить на пятый байт от начала, будет выдавать всякий мусор, которого в файле вообще нет, а если поставить на шестой - всё работает, но не так как надо =)
А не пробовал установить указатель на начало файла и читать побайтово? И вообще, покажи листинг. Может, там у тебя какая ошибка...
Посмотри здесь второй исходник - может оказаться что-то полезное...
Ну так я и читаю побайтово. Иду с начала файла побайтово, если встретится символ 13 (0DH, переход), то выходит из цикла. У меня сейчас кода на этой машине нет, но нечто выходит вроде..
Цикл с чтением (работает нормально)
MOV DX,20
SUB DX,CX ;Это чтобы найти количество пройденных символов
Затем маркер ставлю на начало и считываю это количество байт в переменную. Перехожу к следующему.. =)
У нас просто такая система, проходим сейчас ОС и ассемблер. В плане занятий - написание 4 программ. Первую "выпендриться" я сделал достаточно зверскую, ввернул туда прилично логики, условных и безусловных переходов, ввод текста, вывод на экран и т.д. =) А в итоге препод дал мне задание сделать самообучающуюся программу для ответа на вопросы. То есть, ей задают вопрос, она ищет его в файле с данными и выдает на него ответ. Если там нет - просит пользователя ввести ответ и вместе их туда записывает. Вот эту дозапись блок я написал, а чтение - ну что-то не выходит. Ты бы как реализовала хранение данных? Мне на ум ничего кроме построчного хранения ничего не приходит. Там просто парные строки - первая вопрос, вторая ответ, третья вопрос и т.д. =)
Поглядел я ссылку - конечно, интересно, но там почти всё про и под Windows, а книги даже скачать нельзя =(
У тебя строки ограничены по длине? Тогда в чём проблема сразу при побайтовом чтении заполнить место под строчку? Иначе получается, что ты делаешь двойную работу.
Теоретически, они ограничены 20ю символами, но могут быть и меньше.
Главное, что не больше. Считывай побайтово в массив. Если у тебя строки неодинакового размера - это будет быстрее, чем поиск конца строки и блоковое чтение. Так что и проблему решишь, и время сэкономишь.
А ты считывай не 20 штук, а проверяя каждый символ на предмет конца строки. Если нет - запиши в массив и сдвинь указатель, если да - переходи к обработке строки, через простейшие арифметические операции с указателем можно узнать её длину. Просто используй не LOOP, а условные джампы.
Я не знаю, как делать массивы и про арифметические операции не очень понимаю. Как можно из адреса и смещения узнать её длину?
В Ассемблере ты хоть всем дата-сегментом можешь пользоваться как массивом. Например, сделай так:
tmp_str db 20 dup (0)
Т.е. зарезервировать 20 байт памяти, первому из которых соответствует смещение tmp_str, и заполнить нулями.
Арифметические операции тоже очень просты. Предположим, что ты прочитал строку в tmp_str побайтово, пользуясь регистром di в качестве пойнтера.
mov ax,di
sub ax,offset tmp_str
dec ax ;после окончания записи указатель обычно указывает на ячейку (байт, слово) после последнего записаного
Впрочем, можно делать ещё проще: используй индексную адресацию. Т.е. что-то типа tmp_str[di], где di содержит смещение внутри массива.
Нет, всё равно не очень представляю. Допустим, создал на 20 байт памяти, заполнил нулями - это и будет массив? По байтам? Если да, то как обращаться к конкретной ячейке? Извини обилие глупых вопросов, просто после шарпа меня немного угнетает невозможность всё решать проверенными способами =)
Вот, узнать хотел, а нельзя побайтово считывать сразу в строку? То есть, считали байт - записали его в строку в память, проверили - если это 13ый, то скипануть следующий (10ый) и читать в память заново? А то считывание два раза - это как-то неоптимально, мне кажется.
А можно как-то не очень хитро узнать длину файла? Если её знать, то можно ведь создать буффер вроде buffer db ? и туда записать весь считанный файл, он не должен быть большим.
Обращаться к ячейке памяти в массиве можно так:
tmp_str[5] или tmp_str+5 - выражения абсолютно одинаковые с точки зрения ассемблера, обращение идёт к шестому байту tmp_str, точнее, шестому после метки (ассемблер не следит за границами массивов).
В адресации можно использовать константные числа и регистры BX, SI, DI, но регистры SI и DI в одном адресе использовать нельзя.
Короче, кусок кода будет примерно такой:
(файл должен быть уже открыт, идентификатор файла - переменная file_id, массив для чтения - tmp_str)
mov di,0
l1:
mov ah,3Fh
mov bx,file_id
mov cx,1
mov dx, offset tmp_str[di]
int 21h
inc di
;обработай байт
;выясни надо ли читать следующий
je l1
А вот как узнавать размер файла я пока что не нашла;о(
Ты мне невероятно помогла =) Спасибо огромное =)
Завсегда пожалуйста;о)
Честно, я безумно обожаю шарп, но в ассемблере есть своя прелесть. Это почти дао - думать на языке понятном процессору;о)
Кстати, согласен =) У нас хотя и не программистская кафедра, но базисные знания о системах нам дают. Позволяет краем примазаться к программистам =) Приятно видеть, что в группе несколько человек заинтересовались шарпом и читают книги по нему "для себя". Ассемблер пока не столь популярен =) Нет, дао не подходит - дао не познаваемо =)
А ты попробуй мыслить на ассемблере. Поймёшь, что это тоже непознаваемо;о)
MOV DX,@message
INT 21
message db 'Ну почему же сразу непознаваемо? =)$'
В яблочко!;о)
Слушай, вот вопрос по тому куску кода, который ты привела. Там после проверки идёт условный джамп на новый такт цикла, но ведь вроде бы JE срабатывает именно когда сравнение удачное, когда в флаг кладётся именно нолик? Может, там JNE? У меня просто сейчас некуда заглянуть проверить =)
Search Proc
;--------------Маркер в файле на начало------------------------
MOV AH,42H ; Функция для указания маркера в файле
MOV BX, 5 ; Указание дескриптора (для файла - 5)
MOV AL,0 ; 00 - Счёт ведётся относительно конца файла
MOV CX,0 ; Смещение
MOV DX,0
INT 21H
;-------------Чтение из файла побайтово-------------------------
MOV SI,0
l1:
MOV AH,3FH
MOV BX,5
MOV CX,1
MOV DX,offset readbuf[SI]
INT 21H
INC SI
CMP readbuf[SI],0DH
JNE l1
MOV AH, 40H
MOV BX,1
MOV CX,SI
MOV DX,offset readbuf
INT 21H
Ты путаешь... инструкция CMP эквивалентна инструкции SUB с той лишь разницей, что результат нигде не сохраняется. Если результат вычитани равен нулю (операнды равны) - зажигается ZeroFlag, т.е. становится единицей. А JE это тоже самое что и JZ - прыгнуть ксли флаг нуля горит. Кстати, рекомендую иметь под рукой таблицу какие инструкции на какие флаги влияют - совсем необязательно специально проводить сравнение, может, после последнего арифметического действия флаг сам выставляется как надо.
Я проверил, если ставить JE, то он на первом же символе уходит из цикла. Если JNE, то доходит именно до переноса. What's up? =)
а как ты сравниваешь?
Чуть выше я выложил этот кусок кода, ты, наверное, не заметила =)
Ой, я идиотка! Конечно же JNE! Проверка четырёхканальных Е1-мультплексоров не способствует мышлению на ассемблере;о)
Да ладно, мне бы твои способности в программировании =) А у тебя нет мыслей, почему тот код вверху не работает? Вроде бы логически всё безупречно. Но это мне так кажется =)