реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> поясните принцип действия, матчасть :)
Kail
сообщение Feb 3 2007, 21:18
Сообщение #1


Участник
*

Группа: Свой
Сообщений: 60
Регистрация: 3-08-06
Пользователь №: 19 285



Изучая доку на RealView ASM V. 3.0, решил углубить свои знания в асме и пописать на нем. И как обычно стали вылезать впросы, которые не приходят в голову, когда пишешь на С и все опции проекта, почти без изменений из Keil'a.
Вот код:
Код
    
    AREA Strcopy, CODE, READONLY
            ENTRY
start
            ldr        r1, =srcstr    ; Pointer o first string
            ldr        r0, =dststr    ; Pointer to second string
            ldr        r3, =45        ; load 45
            ldr        r4, =0x40000004; load addres of RAM
            str     r3, [r4]    ; store 45 in RAM
            bl         strcopy        ; Call subroutie to do copy
stop
            b        stop        ;    make loop
strcopy
            ldrb    r2, [r1], #1; load byte and update address
            strb    r2, [r0], #1; Store byte and update address
            cmp        r2, #0        ; check for zero terminator
            bne        strcopy        ; keep going if not
            mov        pc, lr        ; return

            AREA Strings, DATA, READWRITE
srcstr        DCB "First string - source",0
dststr        DCB "Seconf string - destination",0
            END


Вот листинг линкера
Код
  
    Strcopy                                  0x00000000   Section       56  source1.o(Strcopy)
    source1.s                                0x00000000   Number         0  source1.o ABSOLUTE
    Strings                                  0x40000000   Section       50  source1.o(Strings)
    srcstr                                   0x40000000   Data          22  source1.o(Strings)
    dststr                                   0x40000016   Data          28  source1.o(Strings)
................................................................................
.........................................
    Total RO  Size (Code + RO Data)                   56 (   0.05kB)
    Total RW  Size (RW Data + ZI Data)                52 (   0.05kB)
    Total ROM Size (Code + RO Data + RW Data)        108 (   0.11kB)


Вот вопрос: в процессе отадки в симуляторе кейла, гляжу на адреса ОЗУ, т.е. 0x40000000. А там ничего нету. И кстати часть кода, которая должна копировать строку не работает. Точнее срабатывает один раз, находит нуль и все! Специально написал ряд инструкций, чтобы записать число 45 в ОЗУ. Все работает, в окне просмотра памяти вижу записанное мной число! Как я понимаю Total ROM Size (Code + RO Data + RW Data) - размер образа программы, который будет размещен во флэш. А Total RO Size - та область памяти, которую непосредственно будет считывать процессор и последовательно выполнять комманды (не учитывая прыжков и проч.). Но вот никак не могу понять как Total RW Size перебертся из Total ROM Size в ОЗУ, где ей и место. И почему вобще код копировани строки не работает???

Не хватает мне знания курса "Архиктура ЭВМ", который читают на специальностях, связанных с программированием. Всегда осовные вопросы возникают на грани взаимодействия памяти и процессора. Почему alligment, почему разные инструкции могут работать только с разными данными и проч. Приходится информацию доставать по крупицам, причем под x86. А потом додудывать под arm.
Go to the top of the page
 
+Quote Post
sonycman
сообщение Feb 4 2007, 01:19
Сообщение #2


Любитель
*****

Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695



Это весь ваш код?
Стандартного Startup.s нет?

Библиотечная __main вызывается?
Go to the top of the page
 
+Quote Post
sergeeff
сообщение Feb 4 2007, 12:29
Сообщение #3


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



А в твоей системе реально существует RAM по адресу 0x40000000?
Go to the top of the page
 
+Quote Post
Kail
сообщение Feb 4 2007, 15:55
Сообщение #4


Участник
*

Группа: Свой
Сообщений: 60
Регистрация: 3-08-06
Пользователь №: 19 285



А кто по вашему выполняет стартовый код? Тот же процессор, и в функцию main входить вполне не обязательно. может я вообще харкорный прогер и пишу все на чистом асме. Код этот почти целиком из мануала на armar. Код линкуется под LPC2106, озу по адресу 0x40000000. И есть кусок кода, который я специально втсавил сам, чтобы проверить работу с памятью. Число 45 записывается по адресу 0x40000004. После выполнения этого участка, вижу в памяти записанное число. Причем, если адрес в сырце ввести другой, например 0x300000000, Симулятор вполне обоснованно ругается на ошибкудоступа памяти, ибо ОЗУ там нету.
Такое у меня ощющение, что код представленный в мануале, просто не рабочий. Ведь DCD только лишь резервирует место в ОЗУ, но ничего туда не записывает. Необходимо еще вставить код, который перепишет из ROM строки в RAM, а потом уже запускать копирование строк. Вообще-то стыд и позор для arm писать мануалы с неработающим кодом, может я все-таки не прав и чего-то недопонмаю?
Go to the top of the page
 
+Quote Post
Petka
сообщение Feb 5 2007, 11:36
Сообщение #5


Профессионал
*****

Группа: Свой
Сообщений: 1 453
Регистрация: 23-08-05
Пользователь №: 7 886



Цитата(Kail @ Feb 4 2007, 15:55) *
Такое у меня ощющение, что код представленный в мануале, просто не рабочий. Ведь DCD только лишь резервирует место в ОЗУ, но ничего туда не записывает. Необходимо еще вставить код, который перепишет из ROM строки в RAM, а потом уже запускать копирование строк. Вообще-то стыд и позор для arm писать мануалы с неработающим кодом, может я все-таки не прав и чего-то недопонмаю?

для компилятора СИ есть несколько сегментов памяти. один из них должен быть обнулён перед запуском основной программы, другой должен быть заполнен уже заранее заданным содержимым (скопирован из ПЗУ в ОЗУ). Вот как раз эти инициализирующие действия и выполняет sturtup. Поэтому DCD как раз инициализирует ячейку, только в ПЗУ, которую потом надо будет скопировать ОЗУ.
Go to the top of the page
 
+Quote Post
Kail
сообщение Feb 5 2007, 14:06
Сообщение #6


Участник
*

Группа: Свой
Сообщений: 60
Регистрация: 3-08-06
Пользователь №: 19 285



Цитата(Petka @ Feb 5 2007, 11:36) *
для компилятора СИ есть несколько сегментов памяти. один из них должен быть обнулён перед запуском основной программы, другой должен быть заполнен уже заранее заданным содержимым (скопирован из ПЗУ в ОЗУ). Вот как раз эти инициализирующие действия и выполняет sturtup. Поэтому DCD как раз инициализирует ячейку, только в ПЗУ, которую потом надо будет скопировать ОЗУ.


Но я ведь не использую компилятор СИ. Все на ассемблере написано. А вообще, я разобрался, спасибо.
Asm - рулит полюбас!
Go to the top of the page
 
+Quote Post
d__
сообщение Feb 5 2007, 14:28
Сообщение #7


Частый гость
**

Группа: Свой
Сообщений: 197
Регистрация: 26-08-04
Пользователь №: 548



Стоило ли так расстраиваться. В программе не хватило 15 строчек, сличайте, сличайте...
Я программировал на ассемблере 8080 и пдп11 -- это песня! Когда пришлось перейти на ассемблер 8086, дого плевался и матюкался на него, думая что ничего горше него в своей карьере не придется использовать. Однако я ошибался -- есть еще более стукнутые по голове ассемблеры, это ассемблер АРМ Лтд...
AREA Strcopy, CODE, READONLY
ENTRY
export start
import |Load$$ER_RW$$Base|
import |Image$$ER_RW$$Base|
import |Image$$ER_RW$$Length|

start
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
ldr r0,=|Load$$ER_RW$$Base|
ldr r1,=|Image$$ER_RW$$Base|
ldr r2,=|Image$$ER_RW$$Length|
ldr SP,=stacktop
initloop
ldrb r3,[r0],#1
strb r3,[r1],#1
subs r2,#1
bne initloop
;################################################################
ldr r1, =srcstr ; Pointer o first string
ldr r0, =dststr ; Pointer to second string
ldr r3, =45 ; load 45
ldr r4, =0x40000004; load addres of RAM
str r3, [r4] ; store 45 in RAM
bl strcopy ; Call subroutie to do copy
stop
b stop ; make loop
strcopy
ldrb r2, [r1], #1; load byte and update address
strb r2, [r0], #1; Store byte and update address
cmp r2, #0 ; check for zero terminator
bne strcopy ; keep going if not
mov pc, lr ; return

AREA Strings, DATA, READWRITE
srcstr DCB "First string - source",0
dststr DCB "Seconf string - destination",0
AREA Stack,DATA,NOINIT,ALIGN=4
SPACE 32*4
stacktop
END
--------------------------------------------------------------------------
командная строчка линкера:
*.o --ro-base 0x00000000 --entry 0x00000000 --rw-base 0x40000000 --strict
--first start --map --xref --callgraph --symbols
--info sizes --info totals --info unused --info veneers
--list ".\strcpy.map"
-o "strcpy.axf"
Go to the top of the page
 
+Quote Post
Kail
сообщение Feb 5 2007, 16:33
Сообщение #8


Участник
*

Группа: Свой
Сообщений: 60
Регистрация: 3-08-06
Пользователь №: 19 285



Цитата(d__ @ Feb 5 2007, 14:28) *
export start
import |Load$$ER_RW$$Base|
import |Image$$ER_RW$$Base|
import |Image$$ER_RW$$Length|


Откуда Load$$ER_RW$$Base и проч. берутся. Глобальная метка линкера? Тогда помимо этого кода еще
скрипт для линкера нужен как бы...

Цитата(d__ @ Feb 5 2007, 14:28) *
ldr r0,=|Load$$ER_RW$$Base|
ldr r1,=|Image$$ER_RW$$Base|
ldr r2,=|Image$$ER_RW$$Length|
ldr SP,=stacktop
initloop
ldrb r3,[r0],#1
strb r3,[r1],#1
subs r2,#1
bne initloop

Как я понимаю это и есть копирование данных из ROM в RAM.
Цитата(d__ @ Feb 5 2007, 14:28) *
AREA Stack,DATA,NOINIT,ALIGN=4
SPACE 32*4
stacktop

Зачем стек? Он ведь не используется?


А вод еще задачка для самых сообразительных:
Глазеем на стартовый код под гнутый ассемблер:

/* copy .data section (Copy from ROM to RAM) */
ldr R1, =_etext
ldr R2, =_data
ldr R3, =_edata
1: cmp R2, R3
ldrlo R0, [R1], #4
strlo R0, [R2], #4
blo 1b

/* Clear .bss section (Zero init) */
mov R0, #0
ldr R1, =_bss_start
ldr R2, =_bss_end
2: cmp R1, R2
strlo R0, [R1], #4
blo 2b

Все чики-пики. Нативно понятно.
Теперь берм листиннг стартового кода под RealView (см. вложение). Где аналог?????? Где там хоть что-то похожее на копирование данных из RAM в ROM???? Я уже весь монитор взглядом испепелил, так и не понял. Нда буду продолжать шуршать мануалами, может что-то прояснится... Хотя подсказка мне бы очень помогла.
P. S. Недавно как раз читал про ПДП-11. Сурьезный агрегат. Хардкор.
P. S. S. Непонятно как тут делать вложения. В общем сознательная часть листинга стартового кода для Realview:
; Enter User Mode and set its Stack Pointer
MSR CPSR_c, #Mode_USR
MOV SP, R0
SUB SL, SP, #USR_Stack_Size


; Enter the C code

IMPORT __main
LDR R0, =__main
BX R0


; User Initial Stack & Heap
AREA |.text|, CODE, READONLY

IMPORT __use_two_region_memory
EXPORT __user_initial_stackheap
__user_initial_stackheap

LDR R0, = Heap_Mem
LDR R1, =(Stack_Mem + USR_Stack_Size)
LDR R2, = (Heap_Mem + Heap_Size)
LDR R3, = Stack_Mem
BX LR

Хде???? Хде оно, копроварие кода?

Сообщение отредактировал Kail - Feb 5 2007, 16:39
Go to the top of the page
 
+Quote Post
d__
сообщение Feb 5 2007, 16:46
Сообщение #9


Частый гость
**

Группа: Свой
Сообщений: 197
Регистрация: 26-08-04
Пользователь №: 548



Возьми доку на линкер и запусти поиск по тексту с параметрои одной из этих меток, например Load$$ER_RW$$Base, там все написано... Инициализация так называемого RTL у ИАРА и РВ спрятана в либах и относится к исполняемой системе языка Ц. Если ты пишешь прогу на чистом ассемблере инициализацию ртл должен делать ручками или выдернуть соотв субрутины из либы, но там очень много лишнего. И по моему есть сурцы этих субр, только не помню где...

Зачем стек? Он ведь не используется?

Это так наз "правила хорошого тона " при программировании на ассемблере. Правильно, у тебя используется только один уровень вложения подпрограмм, но если не дай Бог уровень вложения больше одного, тебя постигнет краш. Поэтому, это та сама соломка подстеленная на случай падения...
Go to the top of the page
 
+Quote Post
ek74
сообщение Feb 5 2007, 18:06
Сообщение #10


Частый гость
**

Группа: Свой
Сообщений: 81
Регистрация: 4-08-05
Из: г. Саратов
Пользователь №: 7 351



Цитата(Kail @ Feb 5 2007, 16:33) *
; Enter the C code

IMPORT __main
LDR R0, =__main
BX R0
Хде???? Хде оно, копроварие кода?

У Realview __main не тоже самое, что int main(void). Вот выдержка из "RealView Compilation Tools Version 3.0 for μVision Compiler and Libraries Guide":
Код
The entry point of a program is at __main in the C library where library code does the following:
1. Copies nonroot (RO and RW) execution regions from their load addresses to their execution addresses. Also, if any data sections are compressed, they are decompressed from the load address to the execution address. See RealView Compilation Tools v3.0 Linker and Utilities Guide for more details.
2. Zeroes ZI regions.
3. Branches to __rt_entry.

и далее
Код
The library function __rt_entry() runs the program as follows:
1. Calls __rt_stackheap_init() to set up the stack and heap.
2. Calls __rt_lib_init() to initialize referenced library functions, initialize the locale and, if necessary, set up argc and argv for main(). For C++, calls the constructors for any top-level objects by way of __cpp_initialize__aeabi_. See C++ initialization, construction, and destruction
on page 5-32 for more details.
3. Calls main(), the user-level root of the application. From main(), your program might call, among other things, library functions. See Library functions called from main() on page 5-35 for more information.
4. Calls exit() with the value returned by main().

Т.е. мы имеем последовательность вызовов startup -> __main -> __rt_entry -> main, по ходу которой и происходит инициализация кучи, стека, библиотек и областей памяти.
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th July 2025 - 07:39
Рейтинг@Mail.ru


Страница сгенерированна за 0.0146 секунд с 7
ELECTRONIX ©2004-2016