Сборка x8086 получает символы до 'z' или 'Z' и печатает маленькие символы, большие символы, числа - PullRequest
0 голосов
/ 28 декабря 2018

У меня есть вопросы:

  1. Программа для получения ввода от пользователя до ввода 'z' или 'Z', программа проверит символы и напечатает (новая строка) маленькийchars
    (новая строка) большие символы
    (новая строка) числа
    [без 'z' или 'Z']
    не могут использовать переменные.
    только стек.
    пример: input: ASdf154sdgdf123vcvbz Маленькие символы: dfsdgdfvcvb Большие символы: AS Числа: 154123

  2. Программа с размером строки Определите N, программа примет ввод от пользователя и примет только цифры из вводаи поместите их в строку с размером N, размер ввода равен N. и напечатайте сообщение со строкой (должно содержать только цифры из ввода) и количество чисел.
    пример (размер строки 10)
    input: 1adr1t23g7
    строка: 11237
    распечатка:
    Строка чисел: 11237 и числа Толата: 5

Застрял с вопросом 1, не понимаю предмет ине могу продолжить на вопрос 2. спасибо всем, кто может мне помочь

Это код вопроса 1:

STA SEGMENT STACK
    DB 100H DUP (0)
STA ENDS
CODE SEGMENT
    ASSUME CS:CODE,SS:STA
MAIN:
    MOV BP, SP
    MOV BX, BP
    SUB BP, 2
    MOV CX, 0
INPUT:
    MOV AH, 01H
    INT 21H
    INC CX
    CMP AL, 'z'
    JE TOPRINT
    CMP AL, 'Z'
    JE TOPRINT
    MOV AH, 0
    PUSH AX
    MOV AX, 0
    JNE INPUT
    MOV DI, CX
TOPRINT:
    POP DX
    CMP DX, 'a'
    JL NEXT
    CMP DX, 'z'
    JG NEXT
    MOV AH, 02H
    INT 21H
    CMP DX, 'A'
    JL NEXT
    CMP DX, 'Z'
    JG NEXT
    MOV AH, 02H
    INT 21H
    CMP DX, '0'
    JL NEXT
    CMP DX, '9'
    JG NEXT
    MOV AH, 02H
    INT 21H
NEXT:
    SUB BP, 2
    DEC CX
    CMP CX, 0
    JMP TOPRINT
    MOV AX, 4C00H
    INT 21H
CODE ENDS
    END MAIN

1 Ответ

0 голосов
/ 28 декабря 2018

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

не понимает предмет

кажется точным.Но затем вы просите людей написать короткую главу книги в простой ответ SO ... хм, обычно я не люблю этого делать, потому что полная книга - это полная книга, а в коротком ответе нужно будет опустить некоторые детали, но давайтепопробуйте, если что-то вырубленное может удержаться как ответ:

Память стека в реальном режиме 16b является обычной компьютерной памятью, но пара регистров ss:sp указывает на "вершину стека", и есть несколько неявных инструкцийиспользуя эти два регистра для доступа к памяти, например, pop dx «читает значение слова по адресу памяти ss:sp в регистр dx, затем добавляет 2 к sp (чтобы оно указывало на следующее слово в памяти)» (словов смысле «16 бит информации», а не «текстовое» слово).

Обратите внимание на описания инструкций push / pop (см. руководство по эксплуатации, официальные документы от Intel или, например, основы *)1017 *), push вычитает из sp, т. Е. Стек «увеличивается» от старших адресов памяти к низким адресам памяти, а когда вы pop,sp возвращается к старшим адресам памяти.«Вершина стека» - это последний вставленный в него элемент, который находится по текущему адресу ss:sp.Предыдущий элемент, помещенный в стек, находится в ss:sp+2 (в режиме 16b) и т. Д., Поэтому, если вы хотите использовать bp для адресации, и вы копируете значение sp в bp после последнего pushсохраняя элементы в стеке, ваши элементы доступны с помощью адресации [bp+0], [bp+2], [bp+4], ... (примечание: bp по умолчанию ассоциируется с сегментом ss, поэтому mov ax,[bp] неявно mov ax,ss:[bp] (загружает значение из сегмента стека),в то время как mov ax,[bx] по умолчанию неявно mov ax,ds:[bx] (загружается из сегмента данных) .. если вы не указали явное переопределение сегмента в исходном коде).

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

В своем коде в emu8086 вы резервируете область памяти для стека, определяя сегмент стека в начале вашего кода, резервируя256 байтов (128 слов), что является минимальным стеком для такой задачи, требующей большого количества стеков, поскольку ваш код будет потреблять стек со скоростью «одно слово на один входной символ», вы можете ввести не более 128 символов ... это может показаться разумнымДо тех пор, пока вы не узнаете, что фактический пользовательский стек используется также прерываниями DOS, что имеет два основных последствия:

  • некоторые из этих 128 слов используются прерываниями (не уверен, сколько, скажем, 30 слов), и если вы введете 100 символов, прерывания будут уже ниже вашей зарезервированной памяти, начиная перезаписывать части памяти, которые вы не зарезервировали для нее (проблема «переполнения стека»)
  • память ниже current ss:sp периодически перезаписывается обработчиками прерываний DOS

Ваша задача звучит так, как будто вы можете:

  • читать ввод пользователя в цикле до z/ Z вводится, помещая каждый элемент в стек (и считая = у вас теперь есть что-то подобное, как только вы установите pop только правильное количество раз), или указатель конца напустой стек)
  • просмотреть все введенные значения и вывести только маленькие символы
  • вывести новую строку
  • просмотреть все введенные значения и вывести только заглавные буквы
  • output newline
  • пройти через все введенные значения и вывести только цифры
  • output newline
  • exit

Теперь у вас может возникнуть желание сделать pop в самом первом «просмотре всех введенных значений», но это означает, что вы бы переместили ss:sp вверх к исходному «пустому стеку» ... и если бы вызатем вычтите 2 * предметов из sp, вы можете подумать, что теперь вы можете pop снова использовать те же символы из памяти, изменяя модификацией sp.Но если какое-то прерывание все же произошло, исходные символы ниже ss:sp в этот момент уничтожаются, поэтому НЕ pop для первых двух циклов.

используйте скорее bp для доступа к данным, то есть mov bp,sp перед каждым выходным циклом, а затем зацикливание элементов, много раз делая mov dl,[bp] add bp,2, но оставляя ss:sp неизменным (и где-то хранится количество копий элементов, так что вы получите его для второго и третьего цикла ..)или скопируйте "empty" sp где-нибудь, например, mov di,sp в начале, чтобы сделать cmp bp,di для проверки выходных циклов, если вы прочитали все элементы.

Если вы в сборке еще меньшепредмет программирования, и вы чувствуете себя потерянным из-за большей части моего текста, сначала прочитайте какую-нибудь книгу или учебное пособие ... основы из регистров / памяти / и т. д. часто можно выбрать из этого резюме http://www.cs.virginia.edu/~evans/cs216/guides/x86.html, которое предназначено для 32-битного режима, ноЯ не знаю о таком коротком введении для 16b (я думаю, что ваши лекторы дали вам некоторые рекомендации, что изучать), или используйте google ... имейте в виду, что режим 16b более сложный и сложный, чем режим 32b, bпотому что вам также нужно узнать о сегментах памяти, и адресация памяти более ограничена (mov al,[cx] не существует в режиме 16b, в то время как mov al,[ecx] допустимо в режиме 32b).

Если у вас есть проблемытолько с какой-то определенной частью, спросите в комментариях.

Затем взгляните в своем коде, научитесь использовать отладчик (это абсолютно необходимо, использование веб-стека overoverflow, поскольку сервис отладки менее эффективен и рассматривается многими (включая меня)как грубое и плохое поведение ... если вы можете показать, что вы отладили код, и вы можете хорошо описать удивительное поведение (что происходит и чего вы хотели / ожидаете вместо этого), будет гораздо больше людей, желающих написать вамответьте, почему это происходит и где ваш мыслительный процесс неправильный), и попробуйте использовать приведенную выше информацию, чтобы переписать ее.

...