Ru-Board.club
← Вернуться в раздел «Прикладное программирование»

» Assembler

Автор: ForposT_ForeveR
Дата сообщения: 28.05.2012 19:42
Да, через ком строку. Всё верно.


Цитата:
это не проблема

Для меня это огромнейшая проблема, на которую никто не может дать ответ. Ни преподаватели, ни коллеги-программисты.
Если же у Вас есть такая возможность - моей благодарности не было бы границ, а радости - уж и словами не передать. Свяжитесь, пожалуйста, со мной, если Вас не затруднит.
Автор: Yvaliko
Дата сообщения: 28.05.2012 21:21

Цитата:
а ещё уже написанный конвертер, который сам всё переведет в асм.

Дизассемблер называется
Опиши конкретнее чем тебе помочь.
Автор: MERCURY127
Дата сообщения: 28.05.2012 21:45
ForposT_ForeveR, ну приблизительно так:
на стороне си# создаем файл - полный ассемблерный сырец, в который напрямую пишем все операции и данные, чтоб не мучиться с парсингом комстроки. Вызываем шелл два раза: 1 - ассемблер, 2 - сам полученный ехе. Проблему получаем, когда ехе должен вернуть результат - записать его прямо в память родителя не получится из-за защиты. Выход - записать данные в файл? И потом прочитать из родителя? Больше идей нету
Автор: cp58
Дата сообщения: 28.05.2012 22:25
ForposT_ForeveR
Решений множество.

Есть вариант "ленивый". Выражения достаточно похожи на delphi-синтаксис, что может позволить использовать delphi компилятор, а соответственно сгенерировать asm код(впрочем, я не уверен, позволяет ли это сделать, например, компилятор borland).

Также можно преобразовать код в C-подобный и тогда точно выйдет получить ассемблерный код, используя, например, gcc или vc от microsoft.

Посложнее сделать парсер на C++, с использованием boost::spirit, портировать api к нему.

Ну и самый трудозатратный. Практически компилятор. Написать лексический анализатор, выделить токены, затем парсер, который преобразует токены в древовидную структуру, потом генерировать код, на основе дерева.

Как со вторым и третьим вариантом, в конечном итоге придется генерировать ассемблерный код, под заданную архитектуру(x86 я так понимаю) и синтаксис(intel наверно) и лучше использовать какие-либо наработки из области open-source.
Автор: Yvaliko
Дата сообщения: 28.05.2012 22:28
Так он вроде не говорил, что результат нужно возвращать в родитель. Просто сгенерировать, откомпилить и запустить.
Автор: ForposT_ForeveR
Дата сообщения: 28.05.2012 23:40

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

Да, именно такая задача состоит изначально.
Однако, таблица лексем, древо вывода тоже сделал. А вот как генерировать код на асме не знаю. Поэтому и спрашиваю у Вас.
Остаётся задача сгенерировать асмовский файл, далее я уже разберусь что с ним сделать.
Помогите, пожалуйста, написать генератор асма для решения поставленной задачи.
Автор: Yvaliko
Дата сообщения: 28.05.2012 23:53
ForposT_ForeveR
В общем, я так понимю тебе нужно набросать набор макросов на все случаи жизни.
Давай опрелелимся с несколькими вещами.
С какими числами работаем? Со знаком/без знака? От 0 до...? Целые/дробные? Вообще есть ли ограничения?
Какие выражения необходимо решать? В твоем примере вижу лишь сложение, вычитание, деление, умножение. Это все? Никаких корней и синусов?
1 файл для решения одного выажения? Или надо чтоб один файл решал несколько выражений и выдавал несколько ответов?
Автор: cp58
Дата сообщения: 29.05.2012 00:04
ForposT_ForeveR
Без оптимизации это не так сложно.

Если будут использоваться числа с плавающей запятой, то можно использовать сразу мат. сопроцессор и объявлять переменные соответствующе. Пройтись по дереву, выделить переменные, которые будут использоваться, объявить в начале файла(для masm/fasm/tasm это db,dw,dd для gas - .byte, .word, .int).
Затем подгружать переменные в регистры и производить мат. операции, потом сохранять(mov eax, [some_variable] mov ebx, [some_variable2] add eax, ebx mov [some_variable3], eax для intel синтаксиса).
С оптимизациями дольше, заменять операции чтения из памяти, контролировать свободные регистры и т.д.
Автор: ForposT_ForeveR
Дата сообщения: 29.05.2012 01:09

Цитата:
нужно набросать набор макросов на все случаи жизни.

Именно!


Цитата:
С какими числами работаем? Со знаком/без знака? От 0 до...? Целые/дробные? Вообще есть ли ограничения?

Дробные и со знаками. Ограничений нет.

Цитата:
Какие выражения необходимо решать? В твоем примере вижу лишь сложение, вычитание, деление, умножение. Это все? Никаких корней и синусов?


Только умножение, деление, сложение, вычитание.

Цитата:
1 файл для решения одного выажения? Или надо чтоб один файл решал несколько выражений и выдавал несколько ответов?

Нет, 1 строка - 1 выражение.
Причем последующие строки могут связаны с предыдущими выражениями.
И самое главное, значение каждого выражения надо выводить на экран, также с новой строки.

Автор: akaGM
Дата сообщения: 29.05.2012 01:13
ForposT_ForeveR
так кинул бы просто для примера входный файл, а то уже целую страницу у тебя выпытывают его формат...
Автор: ForposT_ForeveR
Дата сообщения: 29.05.2012 10:14

Цитата:
Необходимо на ассемблере решать арифметические выражения вида:
А := K + 4 * (10-8) / 8
P := A + 8

A,K,P - это переменные, которые мы получаем из файла
4,8,10,8 - числа
+-*/ - арифметические знаки
() скобки

Читай выше
Автор: akaGM
Дата сообщения: 29.05.2012 11:18
ForposT_ForeveR
если это мне, то это всё описалово, кот. не заменит реального файла данных, как любой обучающий текст сопровождается иллюстрациями...
при чём тут, например, паскалевское присваивание? или это псевдокод?
у тебя уже есть готовый и надёжный парсер, кот. хотя бы вложенные скобки отрабатывает?

т.е., в конце-концов всё это будет выглядеть так, да?

Код:
printf(".model small\n");
printf(".code\n");
printf(".start:\n");
printf(" mov ax, 10\n");
printf(" add ax, 8\n");

printf(" ; ещё и вывод здесь генерить?\n");

printf(" add ax, 4c00h\n");
printf(" int 21h\n");
printf("end start\n");
Автор: ForposT_ForeveR
Дата сообщения: 29.05.2012 12:46
akaGM
Да, парсер написать не проблема.
Софтина разобьёт всё на элементарные операции, потом для каждой операции будет вызываться соответствующая функция и генерировать асмовский код.


Цитата:
если это мне, то это всё описалово, кот. не заменит реального файла данных, как любой обучающий текст сопровождается иллюстрациями...

Понимаю, но тестовых данных нет. Самому надо придумывать.


Цитата:
при чём тут, например, паскалевское присваивание? или это псевдокод?

А что насчет знака присваивания - так это по ТЗ именно такой он и будет. Почему он схож с паскалевским знает только преподаватель.


Цитата:
душевный онанизм...

Правильный синоним тяжелых будней учебного процесса.
Автор: Yvaliko
Дата сообщения: 30.05.2012 14:01
ForposT_ForeveR
Ну что я могу сказать. Все не так плохо как могло бы быть
Т.к. числа будут всякие, то можно сразу все делать через сопроцессор. А можно не делать
Итак, что нам нужно:
Счиать из файла все выражения
Составить последовательность их решения. Ведь некоторые выраджения используют переменные которые вычисляются в другом выражении. Значит надо первым выполнить то выражение, все переменные которого уже известны.
Составить список всех переменных. Сформировать из них сегмент данных нашего исходника.
Тут еще можно подумать над типом данных. Думаю достаточно будет двойного слова для не дробных. Пусть все они будут целые со знаком, для всех будем использовать операции над числами со знаком, это немного уменьшит число макросов. Для дробных можно взять 10 байт, стандартный размер регистра сопроцессора. Неизвестные переменные заполнить нулями.
Формируем алгоритм решения первого выражения.
Для удобства написания макросов лучше соблюсти правило. Первое число всегда загружаем в eax, а второе в ebx. После присвоения значений регистрам идет вычисление значения и запись результата в переменную (если результат это значение новой переменной).
По окончании вычисления одного выражения вставляем макрос вывода на экран и выводим результат.
Потом формируем алгоритв расчета второго выражения и так далее.

Как то так я это вижу.
Если я все вижу правильно, то можно начать пилить макросы.
Автор: blaro
Дата сообщения: 13.06.2012 14:05
День добрый всем. Я написал прогу которая принимает от юзера данные с клавиатуры и вносит их в массив который определен внутри стека.
Далее прога.
[more=code]
.MODEL SMALL
.STACK 64
.DATA
msg db 20,20 dup (?)
.CODE
print proc
push bp
mov bp,sp
add bp,2
push dx
mov dx,[bp+2]
mov ah,1
int 21h
pop dx
pop bp
ret 2
endp

getstring proc
push bp
mov bp,sp
add bp,2
sub sp,100
push di
push cx
xor cx,cx
mov di,sp
ent: mov ah,1
int 21h
cmp al,0dh
je prnt
mov ss:[di],al
inc di
inc cx
jmp ent
prnt: inc di
mov ss:[di],byte ptr "$"
mov di,sp
xor dx,dx
nt: mov dl,ss:[di]
push dx
call print
inc di
loop nt
pop cx
pop di
pop bp
ret
endp
start:
mov ax ,@data
mov ds, ax
call getstring
mov ax,4c00h
int 21h
end start
[/more]
У меня такой вопрос, как взять этот "массив" и переслать его второй функции для печати?
Автор: MERCURY127
Дата сообщения: 13.06.2012 14:10
blaro, просто вызови ее - массив останется на стеке, только указатель стека сместиться вниз.
Автор: akaGM
Дата сообщения: 13.06.2012 14:32
blaro
а зачем так? ну и заносил бы его в msg...
Автор: blaro
Дата сообщения: 13.06.2012 14:43
akaGM

Цитата:
а зачем так? ну и заносил бы его в msg...

если бы все было так просто, я бы даже не задавал бы вопрос. а msg там определен я даже не помню зачем.
Автор: akaGM
Дата сообщения: 13.06.2012 14:49
blaro
ну так и надо стремиться к простоте...
тем более, если ты -- автор программы ;)
Автор: blaro
Дата сообщения: 13.06.2012 14:57
akaGM

Цитата:
ну так и надо стремиться к простоте...
тем более, если ты -- автор программы

автор то я, но получил задание от препода. если бы не препод, сделал бы самую простую прогу
Автор: akaGM
Дата сообщения: 13.06.2012 15:07
blaro
ну так и как выглядит задание в оригинале?
наверное, у вас там готовят инквизиторов? :)

обычно "хранить данные п/п на стеке", это хранить в динамической памяти, что по простому реализуется через
push bp
mov bp, sp
sub sp, 100

хотя возможны варианты...
Автор: Abs62
Дата сообщения: 13.06.2012 16:52
blaro

Цитата:
push bp
mov bp,sp
add bp,2

Это зачем? И где восстановление sp?
Если в фунции требуется доступ к параметрам вызова или стековым переменным, делается так:

Код: push bp
mov bp, sp
sub sp, xxxx
...
mov sp,bp
pop bp
Автор: akaGM
Дата сообщения: 13.06.2012 17:26

Цитата:
Если в фунции требуется доступ к параметрам вызова или стековым переменным, делается так:

после
push bp
mov bp, sp
sub sp, xxxx

уточнение:

к параметрам вызова
mov ax, [bp+4]

к стековым _локальным_ переменным
mov bx, [bp-4]



Цитата:
Статические/Автоматические/Динамические переменные

и это уточнение принимается...
Автор: Abs62
Дата сообщения: 13.06.2012 17:54
akaGM

Цитата:
уточнение:

к параметрам вызова
mov ax, [bp+4]

Уточнение:
По адресу [bp] лежит старое значение bp (2 байта), по адресу [bp+2] - адрес возврата из функции, 2 или 4 байта в зависимости от типа вызова. Поэтому параметры начинаются с [bp+4] для функций типа near и с [bp+6] для far.

Цитата:
к стековым _локальным_ переменным
mov bx, [bp-4]

А это уже зависит от того, какие там переменные.
Автор: akaGM
Дата сообщения: 13.06.2012 18:26
Abs62
да, если речь идёт о 16-битном приложении...
и тогда уж
mov ax, ss:[bp+4]
потому что лично я не знаю относительно чего, кроме тасма/масма, адресуют bp другие ассемблеры...
передачу параметров через регистры или очистку стека в зависимости от соглашения о вызовах обсуждать будем? :)
Автор: bomzzz
Дата сообщения: 13.06.2012 23:49

Цитата:
чего, кроме тасма/масма, адресуют bp другие ассемблеры...

bp для локальных переменных используется вроде
Автор: cp58
Дата сообщения: 14.06.2012 00:01
bomzzz

Цитата:
bp для локальных переменных используется вроде

bp(ebp) это регистр, используемый для стековых фреймов.
Автор: bomzzz
Дата сообщения: 14.06.2012 00:11



Цитата:
Регистр ЕВР содержит адрес, начиная с которого в стек вносится или забирается информация (или "глубина" стека). Параметры функций имеют положительный сдвиг относительно ЕВР, локальные переменные - отрицательный сдвиг, а полный адрес этого участка памяти будет SS:EBP.
Автор: Abs62
Дата сообщения: 14.06.2012 00:13
akaGM

Цитата:
потому что лично я не знаю относительно чего, кроме тасма/масма, адресуют bp другие ассемблеры...

Ассемблеры тут не при чём, это определяется архитектурой процессора.

Цитата:
The uses of general-purpose registers as base or index components are restricted in the following manner:
• The ESP register cannot be used as an index register.
• When the ESP or EBP register is used as the base, the SS segment is the default segment. In all other cases, the DS segment is the default segment.
Intel® 64 and IA-32 Architectures Developer's Manual: Vol. 1
Автор: akaGM
Дата сообщения: 14.06.2012 00:48
ну теперь знаю...

вообще bp = Base Pointer

а на самом деле в локале в bp можно заносить/хранить что угодно, что неднократно делается ассемблерщиками при "нехватке регистров"...

Страницы: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384

Предыдущая тема: .NET GUI компоненты


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.