Модуль commands asm


Как написать модуль для ассемблера

24.05.2015, 15:07

Написать программу на языке ассемблера
Написать программу на языке ассемблера, использующую функции стандартного ввода-вывода, выполняющую.

Написать уравнение на языке ассемблера
Написать уравнение z=48/(x/y)+12*(x-y) на языке ассемблера. И если не сложно прокомментировать его.

Написать программу на языке ассемблера
1. Написать программу на языке ассемблера, в которой: – объявить массив типа BYTE на 256 элементов.

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

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

24.05.2015, 15:17 2

Компилируешь его
tasm /l s.asm
Получается объектный файл s.obj

Пишешь головную программу g.asm

Компилируешь ее
tasm /l g.asm
Получается объектный файл g.obj

А теперь компонуешь их вместе :
tlink /t g.obj s.obj
И вуаля — получается исполняемый файл g.com

24.05.2015, 16:56 [ТС] 3

Похоже выводит содержимое стека, но не то, что мне нужно. (нужно вывести строку а)
Как правильно передавать параметры?

Добавлено через 11 минут
Подправил.
m2.asm basic

24.05.2015, 17:16 4

Решение

Если ты компонуешь EXE-программу, то в головной программе
org 100h
уже не нужно.
Стек побольше ! Настоящая MS-DOS жадно жрет стек.
s segment stack ‘stack’
db 200h dup (?)
s ends

А вот модуль с подпрограммой написан вообще с ошибками. Правильно будет так :

Потому-что после mov bp,sp
[bp] у тебя указывает на сохраненное значение bp в стеке
2[bp] на адрес возврата из подпрограммы
4[bp] на тот параметр для подпрограммы, что ты положил в стек
ret 2 в конце подпрограммы, выходя из нее, также выкинет параметр со стека.

Добавлено через 8 минут
В итоге у тебя реализовались соглашения по вызовам подпрограмм языка Паскаль (в Паскале параметры подпрограммы выкидывает со стека вызываемая подпрограмма, а в Си вызывающая программа).

ARM Обзор системы команд

Список системы команд

Общий формат команд

Формат системы команд в режиме ARM приведен ниже.

Рис. 10. Формат построения системы команд в режиме ARM


Примечание: некоторые коды команд не определены, но в то же время их выполнение не вызывает исключения «неизвестная команда» (Undefined instruction exception), кроме команды умножения с установленным в «1» битом 6. Эти команды не должны применяться, хотя, некоторые из них могут быть реализованы в новых версиях ядра ARM.

Справочник по командной строке ассемблера ARM ARM Assembler Command-Line Reference

В этой статье рассматривается командной строки в ассемблер ARM Microsoft armasm, компиляция ARMv7 Thumb языка ассемблера в реализации Майкрософт распространенных объектов формата файла (COFF). This article provides command-line information about the Microsoft ARM assembler, armasm, which compiles ARMv7 Thumb assembly language into the Microsoft implementation of the Common Object File Format (COFF). Компоновщик может привязывать COFF кода с кодом объекта, созданного в ассемблер ARM или компилятор C, вместе с библиотеки объектов, созданных библиотекаря. The linker can link COFF code with object code that is produced by the ARM assembler or by the C compiler, together with object libraries that are created by the librarian.

Синтаксис Syntax

armasm [параметры] sourcefile objectfile armasm [*параметры *] -o objectfile sourcefile armasm [options] sourcefile objectfile armasm [options] -o objectfile sourcefile

Параметры Parameters

options options
Состоят из нуля или более составляющих: A combination of zero or more of the following:

-errors filename -errors filename
Перенаправления ошибки и предупреждения для filename. Redirect error and warning messages to filename.

-i dir[; dir] -i dir[;dir]
Добавление указанных директорий в включаемый путь поиска. Add the specified directories to the include search path.

-predefine directive директива -predefine directive
Укажите директиву SETA, SETL или SETS, чтобы заранее определить символ. Specify a SETA, SETL, or SETS directive to predefine a symbol.
Пример: armasm.exe-заранее определить source.asm «COUNT SETA 150» Example: armasm.exe -predefine «COUNT SETA 150» source.asm
Дополнительные сведения см. в разделе armasm компилятора ARM справочное руководство по. For more information, see the ARM Compiler armasm Reference Guide.

-nowarn -nowarn
Отключение всех предупреждающих сообщений. Disable all warning messages.

— ignore warning -ignore warning
Отключение указанного предупреждения. Disable the specified warning. Возможные значения см. в разделе о предупреждениях. For possible values, see the section about warnings.

-help -help
Печать сообщения Справка по командной строке. Print the command-line help message.

-machine машины -machine machine
Укажите тип компьютера для установки в заголовке PE. Specify the machine type to set in the PE header. Возможные значения для машины являются: Possible values for machine are:
ARM— задает тип компьютера для IMAGE_FILE_MACHINE_ARMNT. ARM—Sets the machine type to IMAGE_FILE_MACHINE_ARMNT. Это значение по умолчанию. This is the default.
БЕГУНОК— задает тип компьютера для IMAGE_FILE_MACHINE_THUMB. THUMB—Sets the machine type to IMAGE_FILE_MACHINE_THUMB.

-oldit -oldit
Создать стиль ARMv7 блоки ИТ. Generate ARMv7-style IT blocks. По умолчанию, совместимые с ARMv8 создаются блоки ИТ. By default, ARMv8-compatible IT blocks are generated.

— via filename -via filename
Чтение дополнительных аргументов командной строки из filename. Read additional command-line arguments from filename.

-16 -16
Соберите источника как 16-разрядные инструкции бегунка. Assemble source as 16-bit Thumb instructions. Это значение по умолчанию. This is the default.

-32 -32
Соберите источника как 32-разрядные инструкции ARM. Assemble source as 32-bit ARM instructions.

-g -g
Создает отладочную информацию. Generate debugging information.

-errorReport: параметры -errorReport: option
Укажите, как сведения о внутренних ассемблер, ошибки передаются в корпорацию Майкрософт. Specify how internal assembler errors are reported to Microsoft. Возможные значения для параметр являются: Possible values for option are:
Нет— не отправлять отчеты. none—Do not send reports.
строки— запрашивать пользователя для немедленной отправки отчетов. prompt—Prompt the user to send reports immediately.
очередь— запрашивать пользователя на отправку отчетов при следующем входе администратора. queue—Prompt the user to send reports at the next admin logon. Это значение по умолчанию. This is the default.
Отправить— отправлять отчеты автоматически. send—Send reports automatically.

SourceFile sourcefile
Имя исходного файла. The name of the source file.

objectfile objectfile
Имя файла объекта (на выходе). The name of the object (output) file.

Примечания Remarks

Следующий пример демонстрирует способы использования armasm в типичном сценарии. The following example demonstrates how to use armasm in a typical scenario. Во-первых используйте armasm построение файла источника (.asm) языка ассемблера в файл объектов (OBJ). First, use armasm to build an assembly language source (.asm) file to an object (.obj) file. Затем используйте компилятор командной строки C CL для компиляции файла исходного (.c) и также указать параметр компоновщика, чтобы связать объектный файл ARM. Then, use the CL command-line C compiler to compile a source (.c) file, and also specify the linker option to link the ARM object file.

Модуль commands asm


LDR R0, [PC, #0x088] ;загружает в регистр R0 содержимое ячейки памяти по адресу (PC+0x088)

LDR R1, [R0, #0] ;загружает в регистр R1 содержимое ячейки памяти по адресу R0

STR R1, [R0, #0] ;сохраняет регистр R1 по адресу в R0

LDR pc, =label ;загружает в PC адрес метки кода label

ldr r2,=(BG2_ENABLE|MODE_3) ;загрузить в r2 результат от логической операции OR двух констант

label:
LDR PC, [PC, #-&F20] ;загружает в PC содержимое ячейки по адресу PC-0x00000F20 (обычно используется как вход в прерывание)

DCD Label001 ;Define Constant Data, определяет в памяти константу Label001

SUB lr, lr, #4 ;вычесть 4 из LR и результат поместить в LR

STMFD sp!, ;сначала сделать декремент SP на 4, потом сохранить регистр LR (он указан в списке ) по адресу в SP, измененный адрес сохранить в SP

Илон Маск рекомендует:  Что такое код mcrypt_get_key_size

MRS lr, SPSR ;записать в LR значение регистра SPSR

STMFD sp!, ;сохранить в стеке R0 и LR. По окончанию операции SP уменьшится на 8, в памяти будет сначала лежать R0, а потом LR

LDR lr, =AT91C_BASE_AIC ;записать в LR константу 0xFFFFF000 (AT91C_BASE_AIC)

LDR r0, [r14, #AIC_IVR] ;записать в R0 содержимое ячейки памяти по адресу R14+256, т. к. #AIC_IVR==256

STR lr, [r14, #AIC_IVR] ;записать значение LR по адресу R14+256, т. к. #AIC_IVR==256

MSR CPSR_c, #ARM_MODE_SVC ;.

STMFD sp!, ;сохранить в стеке R1, R2, R3, R12, LR. Содержимое стека при этом уменьшится на 5*4 = 20

LDMIA sp!, ;вернуть из стека содержимое регистров. Содержимое стека при этом увеличится на 5*4 = 20

LDMIA sp!, ^ ;вернуть из стека содержимое PC. ^ означает установить S и вернуть пользовательский банк.

b label1 ;перейти (branch) по метке label1

CMP r0, r4 ; сравнить регистры r0 и r4 (устанавливаются соответствующие флаги в регистре CPSR)

BEQ label34 ; переход по метке label34, если r0 == r4

ldr r2,[r1]+4! ; Загрузить в регистр r2 содержимое того, на что указывает r1, а затем, после того как всё сделано, добавить 4 к r1.

ldr r2,[r1+4]! ; сначала добавить к r1 число 4, а потом загрузить в r2 содержимое ячейки по адресу r1

str r2,[r0]+4! ; сохранить содержимое r2 по адресу в r0, а потом к r0 добавить 4

В ассемблерном модуле вызываемая процедура должна быть дополнительно объявлена при помощи директивы PUBLIC

Взаимодействие ассемблерных модулей с модулями, написанными на языках высокого уровня


Выполнить трансляцию модуля modul2.asm и получить объектный модуль modul2.obj;

Выполнить трансляцию модуля modul1.asm и получить объектный модуль modul1.obj;

Пример использования директив extrn и public на схеме связи двух модулей Модуль1.asm и Модуль2.asm.

; ——Объявляем процедуру My_proc_1 видимой извне ———

Extrn my_proc_1 ; объявляем процедуру my_proc_1 внешней

call my_proc_1 ; вызов my_proc_1 из модуля 1

Если необходимо собрать два ассемблерных модуля, например modul1.asm и modul2.asm в один исполняемый модуль, необходимо:

6) cкомпановать программу утилитой TLINK командной строкой вида:

tlink /v modul1.obj+ modul2.obj

В итоге будет создан исполняемый модуль modul1.obj и можно будет исследовать данный модуль в отладчике, но при этом в турбо дебагере можно будет увидеть только текст программы modul1. Для того, чтобы войти в вызываемую процедуру, необходимо нажимать клавишу F7. Обработка этой команды приведёт к открытию второго окна, в котором будет выведен текст вызванной процедуры.

Рассмотрим простой модуль на языке ассемблера, содержащий процедуру, копирующую одну строку в другую. Подсоединяем этот модуль к программам, написанным на языке Си и Паскаль, с использованием трех трансляторов: Borland C++, Visual C++, Delphi.

Borland C++ 5.0

1) В С++ функции, вызываемые из ассемблерного модуля объявляются при помощи модификаторов extern «С» и stdcall.

2) Если модуль на языке ассемблера транслируется с помощью транслятора TASM, проблемы с подчеркиванием не возникает.

3) Тип вызова stdcall предполагает, что стек освобождается в вызываемой процедуре.

Пример использования процедуры из внешнего модуля. Используется транслятор BORLAND C++ 5.0.

// файл copyc.cpp#include #include extern «C» _stdcall COPYSTR(char *, char *);vo ,(char *)COPYSTR(s1, s2)); ExitProcess(0);> ; файл copy.asm.386P; эта процедура будет вызываться из внешнего модуляPUBLIC COPYSTR.MODEL FLAT, stdcall_TEXT SEGMENT DWORD PUBLIC USE32 ‘CODE’; процедура копирования одной строки в другую; строка, куда копировать [EBP+08Н]; строка, что копировать [EBP+0CН]; не учитывает длину строки, куда производится копированиеCOPYSTR PROC PUSH EBP MOV EBP,ESP MOV ESI,DWORD PTR [EBP+0CH] MOV EDI,DWORD PTR [EBP+08H]L1: MOV AL,BYTE PTR [ESI] MOV BYTE PTR [EDI],AL CMP AL,0 JE L2 INC ESI INC EDI JMP L1L2: MOV EAX,DWORD PTR [EBP+08H] POP EBP RET 8COPYSTR ENDP_TEXT ENDSEND

Не нашли то, что искали? Воспользуйтесь поиском:

Лучшие изречения: Для студента самое главное не сдать экзамен, а вовремя вспомнить про него. 10039 — | 7504 — или читать все.

188.64.174.135 © studopedia.ru Не является автором материалов, которые размещены. Но предоставляет возможность бесплатного использования. Есть нарушение авторского права? Напишите нам | Обратная связь.

Отключите adBlock!
и обновите страницу (F5)

очень нужно

Assembler:Commands:IMUL

command imul destination, source1, source2

Performs a signed multiplication of two or three operands. This instruction has three forms, depending on the number of operands.

One-operand This form is identical to that used by the MUL instruction, just signed. Here, the source operand (in a general-purpose register or memory location) is multiplied by the value in the accumulator register and the upper product is stored in the data register and lower product is stored in the accumulator register. The CF and OF flags are set when significant bits are carried into the upper half of the result and cleared when the result fits exactly in the lower half of the result. Two-operand With this form the destination operand (the first operand) is multiplied by the source operand (second operand). The destination operand is a general purpose register and the source operand is an immediate value, a general-purpose register, or a memory location. The product is then stored in the destination operand location. The CF and OF flags are set when the result must be truncated to fit in the destination operand size and cleared when the result fits exactly in the destination operand size. The SF, ZF, AF, and PF flags are undefined. Three-operand This form requires a destination operand (the first operand) and two source operands (the second and the third operands). Here, the first source operand (which can be a general-purpose register or a memory location) is multiplied by the second source operand (an immediate value). The product is then stored in the destination operand (a general-purpose register). The CF and OF flags are set when the result must be truncated to fit in the destination operand size and cleared when the result fits exactly in the destination operand size. The SF, ZF, AF, and PF flags are undefined.


Performs a signed multiplication of two operands. This instruction has three forms, depending on the number of operands.

One-operand form. This form is identical to that used by the MUL instruction. Here, the source operand (in a general-purpose register or memory location) is multiplied by the value in the AL, AX, or EAX register (depending on the operand size) and the product is stored in the AX, (E)DX:(E)AX.

Two-operand form. With this form the destination operand (the first operand) is multiplied by the source operand (second operand). The destination operand is a general purpose register and the source operand is an immediate value, a general-purpose register, or a memory location. The product is then stored in the destination operand location.

Three-operand form. This form requires a destination operand (the first operand) and two source operands (the second and the third operands). Here, the first source operand (which can be a general-purpose register or a memory location) is multiplied by the second source operand (an immediate value). The product is then stored in the destination operand (a general-purpose register).

When an immediate value is used as an operand, it is sign-extended to the length of the destination operand format.

The CF and OF flags are set when significant bit (including the sign bit) are carried into the upper half of the result. The CF and OF flags are cleared when the result (including the sign bit) fits exactly in the lower half of the result.

The three forms of the IMUL instruction are similar in that the length of the product is calculated to twice the length of the operands. With the one-operand form, the product is stored exactly in the destination. With the two- and three- operand forms, however, the result is truncated to the length of the destination before it is stored in the destination register. Because of this truncation, the CF or OF flag should be tested to ensure that no significant bits are lost.

The two- and three-operand forms may also be used with unsigned operands because the lower half of the product is the same regardless if the operands are signed or unsigned. The CF and OF flags, however, cannot be used to determine if the upper half of the result is non-zero.

Илон Маск рекомендует:  Работа с аппаратурой под windows (com порт)

ASM в STM32. Начало

Настоящим джедаям посвящается

О IDE

Попробовав Keil, уже не могу работать на чем-нибудь другом под арм. Мощный макро-язык, крутой отладчик. Поэтому далее все касательно Keil’а. Вот только мой любимый F100C4 отладчик не знает, да и с другими(например, F103) C4 не все в порядке. Может в свежих версиях уже поправили? Так что отладка на F103C8. Благо, разницы почти нет.

О сегментах

Для удобства и чтобы избежать некоторых проблем (например, с выравниванием) желательно делить программу минимум на следующие сегменты:
AREA RESET, DATA, READONLY — стартовый сегмент (стартап)
AREA |.text|, CODE, READONLY — программный сегмент
AREA |.text|,DATA,READONLY — сегмент данных (flash)
AREA |header data|,DATA,READWRITE — сегмент данных (ram)

О стартапе

Это банальная таблица векторов прерываний. Она несколько больше, чем у 8ми-битников. Располагается вначале программного флеша, т.е. с адреса 0x8000 0000. Порядок векторов расписан в Reference manual для конкретного семейства (100, 101, 102, 103 и т.д.) и подсемейства (connectivity line, XL-density и т.д.). Вот, для примера, таблица под STM32F100C4:
Настоящий вектор Reset_Handler, естественно, первый, а остальные — заглушки. Если понадобится какое-то прерывание — мы заменим его заглушку на необходимую нам метку.

О стеке

Для стека удобно сразу выделить область в раме:
О константах

Наиболее употребляемые константы — 0 и 1 удобно держать подготовленными в каких-нибудь регистрах (например, 0 в R10 а 1 в R11). Это ускоряет написание программы и сокращает ее размеры. Поэтому, сразу после метки сброса пишем:
Главное потом об этом не забывать. Можно переименовать для удобства сами регистры, например:
А затем их проинициализировать:
Критерии выбора регистров под константы просты: во-первых, лучше не трогать регистры, которые автоматически сохраняются при прерывании, т.е. r0, r1, r2, r3, r12; во-вторых, название регистра должно намекать на его содержимое. Поэтому альтернатив r10, r11 я не вижу.

О макросах

Макросы позволяют писать программы быстро и читабельно. Важно чтобы они были простыми для запоминания. Поскольку в нашем риск-процессоре частые операции чтение-модификация-запись, необходимо упростить рутину их написания с помощью макросов.
Удобнее писать loadb var(переменная), чем
mov32 r0,#var(переменная)
ldrb r1,[r0]
Главное запомнить используемые в макросе регистры, специализировать их и не менять специализацию в однотипных макросах. Для примера, группа макросов работы с байтовой переменной:
Также можно поступить и с переменными размером в полуслово и слово (loadh, loadw например). Макросы — очень мощный инструмент для ассемблерщика и пренебрегать им не стоит. Удобные макросы приближают скорость разработки ассемблерной программы к скорости написания в ЯВУ(+ улучшается читаемость программы). Для примера, настройка портов может выглядеть так:
если прописать соответствующие макросы (и константы):
Или вывод на 20×4 LCD может быть такой:
если макрос:
Естественно, голову макрос не заменит :)

О константах периферии

STM32 богат на всякие вкусности, что поначалу даже пугает. Поэтому поступаем как обычно — делим большое на куски. Если используем какой-то периферийный блок (например, порты), расписываем его регистры (и константы для них) например так:
Варианты могут быть и другие (например, определение сразу абсолютного адреса регистра, а не как выше — относительно блока). Главный критерий — удобство применения этих констант в ваших макросах. Блоки макросов лучше собирать в отдельный файл и подключать к программе командой GET имя_equ.asm.

О псевдооператорах

Важно знать какой код получаем от псевдооператоров (ldr, mov32 и др.) и их особенности. Об этом хорошо рассказывает кейл (достаточно посмотреть код в отладчике и почитать ейный хелп). Эти знания реально экономят время и нервы (особенно если программа больше 4kB).

О суффиксах

Применение суффиксов условного исполнения команд значительно облегчает написание кода, но не увлекайтесь. Есть соблазн написать всю обработку части условия условными командами и выйти из подпрограммы. Однако это не только замедляет подпрограмму, но и при изменении условия заставляет переделывать весь «условный» код.


О подпрограммах

Следите за LR. (особенно если много макросов).

О глюках и ошибках

Какой бы мистической ни казалась реакция программы, всегда есть рациональное объяснение. Проверьте: тип переменной; куда возвращаемся из подпрограммы (прерывания); нет ли ошибки в макросе; сбросили ли флаг прерывания; изменяет ли команда те флаги, которые мы потом проверяем; в той ли очередности вернули из стека и т.д. и т.п.

О процессоре

На мой взгляд, идеальный процессор для асма и радиолюбителя это STM32F100C4. Он забит периферией больше чем его собратья из серий «покруче», частоты в 24Мгц достаточно для большинства радиолюбительских устройств, 16kB flash + 4kB ram тоже, 48 ног и ЦЕНА! конечно. Реальная замена соответствующих восьмибитников.

О программаторе

Пока пользуюсь STM32L-Discovery (u-link забросил — не удобно).

Итого

Процесс разработки устройства на асме STM32 ничем не отличается от того же на avr или stm8. Время вхождения, конечно, больше, т.к. необходимо осваивать немного более сложную периферию. Зато писать на асме STM32 и быстрее и удобнее чем, например, под avr (ИМХО).

И напоследок, заготовка под асм-проект для STM32F100C4.

Микроконтроллеры

Меню навигации

Пользовательские ссылки

Информация о пользователе

Вы здесь » Микроконтроллеры » Популярное » Программирование STM32 на ассемблере

Программирование STM32 на ассемблере

Сообщений 1 страница 9 из 9

Поделиться12020-02-18 22:48:06

Disclaimer )
Я не агитирую программировать STM32 на ассемблере и даже, наоборот, не советую.
IMHO, ассемблер интересен в трёх случаях:
1) Невозможно сделать на си
2) Разобраться как оно устроено
3) Just for fun
Поскольку первый случай сложный, а третий — тяжёлый, то дальше я излагаю, ориентируясь на второй )
Да, и речь только о Cortex-M<0,3,4>, т.е. о STM32

Основной мануал по ассемблеру для STM32 — st-шный Programming manual.
Он написан более понятным языком, чем st-шные RM, потому что является по сути пересказом армового Generic User Guide с учётом особенностей STM32.
Вот ссылки на тот и другой, например, для STM32F1
http://www.st.com/content/ccc/resource/ … 228163.pdf
http://infocenter.arm.com/help/topic/co … 3_dgug.pdf
Для других серий STM32 и ядер Cortex есть такие же свои.

Из софта требуются только два файла — две программы: as и objcopy, которые можно взять из любого дистрибутва gcc-arm-none-eabi, например, этого — https://developer.arm.com/open-source/g … /downloads
Ещё нужен какой-то дебаггер, например, Segger Ozone

Первая, самая минимальная программа (для любой серии STM32)

.syntax unified — директива выбора варианта синтаксиса ассемблера (подробнее — https://sourceware.org/binutils/docs/as … 2dSet.html)

.word 0x20001000 — в самое первое слово программы, по нулевому адресу, помещается значение указателя стека (SP), которое будет устанавливаться при ресете (стек растёт в сторону уменьшения адресов, RAM начинается с 0x20000000).


.word Reset+1 — во второе слово программы (по адресу 4) помещается значение счётчика команд (PC), которое будет устанавливаться при ресете.
Младший бит не используется для адресации (реальный счётчик команд всегда чётный), а имеет специальное назначение.
В докортексовых армах использовались два пересекающихся набора инструкций — 32-битный (arm) и 16-битный (thumb), а младший бит значения PC использовался для переключения между ними.
Хотя в кортексах только один набор инструкций — thumb2 (thumb с дополнительными 32-битными инструкциями), а переключение бессмысленно и запрещено, тем не менее в младшем бите остался тот же переключатель и он должен всегда устанавливаться в единицу.

.word NMI+1, HardFault+1 — с третьего слова (с адреса 8) начинается область векторов прерываний (в кортексах вектор прерывания == адрес обработчика).
Минимально необходимы первые два: NMI — немаскируемое и HardFault — фатальный сбой.

Дальше всё просто
.=0x200 — указание ассемблеру размещать остальную программу с адреса 0x200, пропустив область векторов прерываний (просто для приличия, хотя это и не обязательно).
Reset: — сама «программа».
NMI: HardFault: — заглушка для прерываний.

Ассемблирование в объектный файл

Получение бинарника из объектного файла

Результат в Ozone

Поделиться22020-02-18 23:52:00

Я так понимаю, что этап линковки пропущен т.к. программа элементарная. в обычной жизни без линковщика ведь не обойтись ?

Поделиться32020-02-19 00:19:03

vt340
Добавь ещё реверсинг к стимула изучить АСМ.

Поделиться42020-02-19 09:12:50

Я так понимаю, что этап линковки пропущен т.к. программа элементарная. в обычной жизни без линковщика ведь не обойтись ?

Да почему, можно и обойтись, если хочется )
Если не делать раздельной трансляции файлов, а объединять на уровне текста

Поделиться52020-02-19 09:18:55

vt340
Добавь ещё реверсинг к стимула изучить АСМ.

Имеешь в виду «анализ исключительно в исследовательских целях»? )
Попадает под случай «Разобраться как оно устроено»

Илон Маск рекомендует:  Что такое код itoa

Поделиться62020-02-22 10:11:52

По закону жанра дальше должна быть мигалка )

Поскольку потребуется обращаться к регистрам периферии, и не по числовым же адресам к ним обращаться, то вот файлы определений символических имён регистров периферии (в архиве 43 файла, сгенерированные из всех 43-х SVD-файлов CMSIS)
https://yadi.sk/d/naqKh4e03EDEJU/STM32/sfr.zip

Пример мигалки для STM32F10x

Начало такое же как в прошлой программе, плюс вектор системного таймера SysTick.
SysTick дальше будет настроен на период 1 мс.

Обработчик прерывания SysTick.

R8 — счётчик, инкрементируется каждую миллисекунду.
R9 — адрес GPIO BSRR.
R10, R11 — значения GPIO BSRR для вкл. и выкл. светодиода.

Что здесь есть интересного? Во-первых выход из прерывания (bx lr).
Внешне выход из прерывания не отличается от выхода из подпрограммы — тот же безусловный преход по адресу из регистра LR.
Однако, если при вызовах подпрограмм стек не трогается (адрес возврата просто сохраняется в LR), то при прерываниях в стек автоматически загружаются восемь слов (R0-R3, R12, адрес возврата, PSR, LR).
Соответственно, при возврате они должны выгружаться обратно, но где спец команда для этого?
Фокус в том, что при прерываниях в LR заносится не адрес возврата, как при вызове подпрограмм, а спец код, который процессор распознаёт при загрузке в счётчик команд и делает выгрузку восьми слов из стека вместо этого.

Ещё из интересного — условный блок (ite eq и две следующие команды).
Внутри условного блока каждая команда либо выполняется, либо пропускается в зависимости от условия, что позволяет обходиться без ветвлений и меток.
Кол-во команд в условном блоке задаётся в ассемблере кол-вом букв «t» (then) и «e» (else) в заголовке блока.

Лирическое отступление )
Cortex — RISC процессор, операции с памятью — только загрузка-сохранение в регистр, составных команд нет, данные могут быть только в слове команды, а места там мало.
Поэтому оптимальный стиль — работа с массивами, структурами, таблицами, когда длинный базовый адрес загружается в регистр один раз, и дальше уже всё идёт косвенной адресацией с короткими смещениями.
В таком стиле компилирует си, под такой стиль заточены сишные headers периферии, так что мигалка тоже будет стильной )

Таблицы данных для мигалки.


Директива .align — выравнивание по границе 32-битных слов (подробнее — https://sourceware.org/binutils/docs/as/Align.html).
В первой строке начальные значения для R8-R11 для SysTick.
Дальше идёт таблица инициализации периферии — в каждой строке по три слова: адрес, маска и значение.

Команды ldm — загрузка серии слов из памяти сразу в несколько регистров, в R0 — адрес, «!» ещё и дополнительно инкрементирует R0 на 4*<кол-во регистров>, так что в следующий раз будет загрузка следующей серии слов.
Сначала из первой строки таблицы загружаются начальные значения R8-R11.
Затем для каждой следующей строки в R1-R3 загружаются адрес, маска и значение, проделывается чтение по адресу (ldr), «и» по дополнению к маске (bics), «или» по значению (orrs) и запись по адресу (str) — в общем всё так же как и на си, всё как обычно.

Директива .include с файлом определений периферии в самом конце программы — ассемблеру всё равно, он многопроходный, а для листинга удобнее когда 100500 строк определений в конце, после кода (опция для генерации листинга: -ahls=<имя>.lst)

В ассемблерном модуле вызываемая процедура должна быть дополнительно объявлена при помощи директивы PUBLIC

Взаимодействие ассемблерных модулей с модулями, написанными на языках высокого уровня

Выполнить трансляцию модуля modul2.asm и получить объектный модуль modul2.obj;

Выполнить трансляцию модуля modul1.asm и получить объектный модуль modul1.obj;

Пример использования директив extrn и public на схеме связи двух модулей Модуль1.asm и Модуль2.asm.

; ——Объявляем процедуру My_proc_1 видимой извне ———

Extrn my_proc_1 ; объявляем процедуру my_proc_1 внешней

call my_proc_1 ; вызов my_proc_1 из модуля 1

Если необходимо собрать два ассемблерных модуля, например modul1.asm и modul2.asm в один исполняемый модуль, необходимо:

6) cкомпановать программу утилитой TLINK командной строкой вида:

tlink /v modul1.obj+ modul2.obj

В итоге будет создан исполняемый модуль modul1.obj и можно будет исследовать данный модуль в отладчике, но при этом в турбо дебагере можно будет увидеть только текст программы modul1. Для того, чтобы войти в вызываемую процедуру, необходимо нажимать клавишу F7. Обработка этой команды приведёт к открытию второго окна, в котором будет выведен текст вызванной процедуры.

Рассмотрим простой модуль на языке ассемблера, содержащий процедуру, копирующую одну строку в другую. Подсоединяем этот модуль к программам, написанным на языке Си и Паскаль, с использованием трех трансляторов: Borland C++, Visual C++, Delphi.

Borland C++ 5.0

1) В С++ функции, вызываемые из ассемблерного модуля объявляются при помощи модификаторов extern «С» и stdcall.

2) Если модуль на языке ассемблера транслируется с помощью транслятора TASM, проблемы с подчеркиванием не возникает.

3) Тип вызова stdcall предполагает, что стек освобождается в вызываемой процедуре.

Пример использования процедуры из внешнего модуля. Используется транслятор BORLAND C++ 5.0.

// файл copyc.cpp#include #include extern «C» _stdcall COPYSTR(char *, char *);vo ,(char *)COPYSTR(s1, s2)); ExitProcess(0);> ; файл copy.asm.386P; эта процедура будет вызываться из внешнего модуляPUBLIC COPYSTR.MODEL FLAT, stdcall_TEXT SEGMENT DWORD PUBLIC USE32 ‘CODE’; процедура копирования одной строки в другую; строка, куда копировать [EBP+08Н]; строка, что копировать [EBP+0CН]; не учитывает длину строки, куда производится копированиеCOPYSTR PROC PUSH EBP MOV EBP,ESP MOV ESI,DWORD PTR [EBP+0CH] MOV EDI,DWORD PTR [EBP+08H]L1: MOV AL,BYTE PTR [ESI] MOV BYTE PTR [EDI],AL CMP AL,0 JE L2 INC ESI INC EDI JMP L1L2: MOV EAX,DWORD PTR [EBP+08H] POP EBP RET 8COPYSTR ENDP_TEXT ENDSEND

Не нашли то, что искали? Воспользуйтесь поиском:

Лучшие изречения: При сдаче лабораторной работы, студент делает вид, что все знает; преподаватель делает вид, что верит ему. 9339 — | 7293 — или читать все.

188.64.174.135 © studopedia.ru Не является автором материалов, которые размещены. Но предоставляет возможность бесплатного использования. Есть нарушение авторского права? Напишите нам | Обратная связь.


Отключите adBlock!
и обновите страницу (F5)

очень нужно

Модуль commands asm

LDR R0, [PC, #0x088] ;загружает в регистр R0 содержимое ячейки памяти по адресу (PC+0x088)

LDR R1, [R0, #0] ;загружает в регистр R1 содержимое ячейки памяти по адресу R0

STR R1, [R0, #0] ;сохраняет регистр R1 по адресу в R0

LDR pc, =label ;загружает в PC адрес метки кода label

ldr r2,=(BG2_ENABLE|MODE_3) ;загрузить в r2 результат от логической операции OR двух констант

label:
LDR PC, [PC, #-&F20] ;загружает в PC содержимое ячейки по адресу PC-0x00000F20 (обычно используется как вход в прерывание)

DCD Label001 ;Define Constant Data, определяет в памяти константу Label001

SUB lr, lr, #4 ;вычесть 4 из LR и результат поместить в LR

STMFD sp!, ;сначала сделать декремент SP на 4, потом сохранить регистр LR (он указан в списке ) по адресу в SP, измененный адрес сохранить в SP

MRS lr, SPSR ;записать в LR значение регистра SPSR

STMFD sp!, ;сохранить в стеке R0 и LR. По окончанию операции SP уменьшится на 8, в памяти будет сначала лежать R0, а потом LR

LDR lr, =AT91C_BASE_AIC ;записать в LR константу 0xFFFFF000 (AT91C_BASE_AIC)

LDR r0, [r14, #AIC_IVR] ;записать в R0 содержимое ячейки памяти по адресу R14+256, т. к. #AIC_IVR==256

STR lr, [r14, #AIC_IVR] ;записать значение LR по адресу R14+256, т. к. #AIC_IVR==256

MSR CPSR_c, #ARM_MODE_SVC ;.

STMFD sp!, ;сохранить в стеке R1, R2, R3, R12, LR. Содержимое стека при этом уменьшится на 5*4 = 20

LDMIA sp!, ;вернуть из стека содержимое регистров. Содержимое стека при этом увеличится на 5*4 = 20

LDMIA sp!, ^ ;вернуть из стека содержимое PC. ^ означает установить S и вернуть пользовательский банк.

b label1 ;перейти (branch) по метке label1

CMP r0, r4 ; сравнить регистры r0 и r4 (устанавливаются соответствующие флаги в регистре CPSR)

BEQ label34 ; переход по метке label34, если r0 == r4

ldr r2,[r1]+4! ; Загрузить в регистр r2 содержимое того, на что указывает r1, а затем, после того как всё сделано, добавить 4 к r1.

ldr r2,[r1+4]! ; сначала добавить к r1 число 4, а потом загрузить в r2 содержимое ячейки по адресу r1

str r2,[r0]+4! ; сохранить содержимое r2 по адресу в r0, а потом к r0 добавить 4

Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL