#parsing #assembly #x86
#синтаксический анализ #сборка #x86
Вопрос:
Я работаю над программой, которая должна считывать входные данные из файла, содержащего инструкции по сборке, а затем выводить, содержит ли каждая строка метку, код операции, oper1, oper2 или комментарий. Вот что у меня есть до сих пор:
.model small
.8086
.data
line db 'LABEL=','$'
opcode db 'OPCODE=','$'
oper1 db 'OPER1=','$'
oper2 db 'OPER2=','$'
com db 'COMMENT=',13,10,13,10,'$'
filemsg db '... end of file',13,10,1Ah,'$'
.code
start:
mov ax,@data
mov ds,ax
progloop:
mov ah,8
int 21h
cmp al,1Ah
je eof
mov dl,al
mov ah,2
int 21h
cmp dl,3Ah ; this is where I would check for a colon. incomplete for now
cmp dl,0Ah
je eol
jmp progloop
eol:
mov dx,offset line
mov ah,9
int 21h
mov dx,offset opcode
mov ah,9
int 21h
mov dx,offset oper1
mov ah,9
int 21h
mov dx,offset oper2
mov ah,9
int 21h
mov dx,offset com
mov ah,9
int 21h
jmp progloop
eof:
mov dx,offset filemsg
mov ah,9
int 21h
exit: mov ax,4c00h
int 21h
end start
Программа в основном должна выводиться следующим образом:
Addval: add [salary],1000 ; this line has all five operands
LABEL=Y OPCODE=Y OPER1=Y OPER2=Y COMMENT=Y
testit: ; a label and a comment
LABEL=Y OPCODE=N OPER1=N OPER2=N COMMENT=Y
Я не уверен, как правильно это сделать. Должен ли я создать linemsg
и отслеживать LABEL=, OPCODE= и т. Д.? Как я должен отслеживать флаги Y / N?
Ответ №1:
Самым простым, но не идеальным, было бы что-то вроде этого…
Сначала определите, есть ли комментарий к строке, а затем удалите его оттуда (либо физически, либо сократите эффективную длину строки до позиции первой точки с запятой).
Затем посмотрите, есть ли двоеточие в том, что осталось. Если есть, слева от него находится имя метки. Вы можете удалить его (или, опять же, просто пропустить мимо него, делая вид, что строка начинается после двоеточия).
Если что-то еще осталось, первым элементом является код операции. Если после этого что-то есть, это операнды (один или несколько, разделенные запятыми).
Это не идеальное решение, поскольку в различных ассемблерах x86 поддерживается ряд более сложных конструкций, например, если указан сегмент, будет двоеточие, которое не имеет ничего общего с метками:
mov al, byte ptr es:[bx]
В приведенном выше mov al, byte ptr es
нет метки.
Или у вас может быть объявлен массив, как показано ниже. Имя массива не является кодом операции, это фактически метка, но после нее нет двоеточия:
MyArray db 1,2,3,4,5 ; array of 5 bytes
И вы также можете столкнуться с пунктуаторами внутри символьных и строковых литералов, которые не разделяют строку на метки, операнды и комментарии:
MyString db ':,a;'
Здесь MyString db '
это не метка только потому, что после нее стоит двоеточие. a
не является операндом только потому, что перед ним стоит запятая. И, наконец, ;'
это не комментарий только потому, что там есть точка с запятой.
Для полной поддержки всех этих возможностей вам потребуется реализовать более сложное решение, вероятно, с использованием конечного автомата синтаксического анализа.
Комментарии:
1. Я должен не согласиться с этим ответом — по крайней мере, с первой частью. Я почти уверен, что весь смысл упражнения заключается в разработке токенизатора; распознавание ключевых слов, литералов и переменных; и, наконец, сборка кода в байт-код. Написание кода, предназначенного для определенного файла или даже определенного языка, сводит на нет цель обучения. Существует процесс написания системного программного обеспечения, и этот процесс определен по определенной причине.
2. @Sparafusile: пожалуйста, обратите внимание, что это инструкции x86 с 3 операндами (например, SHLD и SHRD), поэтому в этом отношении данная задача ограничена не только конкретным языком, но и его подмножеством. Нам ничего не сказали о намерениях, ожиданиях, токенизаторах общего назначения, фактической сборке исходного кода, и мы не в состоянии судить о SO, как обучение выполняется где-то еще, и пытаться его изменить. Я думаю, что для этого есть более подходящие способы и места. Кроме того, это задание; ожидания и процессы, существующие в отрасли, здесь не применяются в полном объеме.