Kanał - ATNEL tech-forum
Wszystkie działy
Najnowsze wątki



Teraz jest 28 mar 2024, o 15:22


Strefa czasowa: UTC + 1





Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 5 ] 
Autor Wiadomość
PostNapisane: 15 kwi 2018, o 18:54 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 26 maja 2017
Posty: 143
Pomógł: 0

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Zastanawia mnie po zdefiniowaniu tablicy gdzie jest przetrzymywany ten adres zawarty w nazwie tab ?
Bo przecież nazwa zawiera adres ,na który patrzy wskaźnik do elementu uint8_t tak to odebrałem po przeczytaniu rozdziału o Wskaźnikach.

Asembler odpowiedziałby na moje pytania ale nie znam go i bardzo ciężko mi analizować plik .lss może ktoś pomoże, i opisze co i gdzie się dzieje z tą tablicą w asemblerze ;) ?

Przepraszam jeśli kogoś rażę moimi pytaniami w szczególności Mirka, Mirku poproszę o książkę "Asembler dla Początkujących" Mirosław Kardaś ;) , będzie mi łatwiej ;) .

Pozdrawiam Procek87



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 15 kwi 2018, o 19:09 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27212
Lokalizacja: Szczecin
Pomógł: 1041

mnie nie razisz dokąd nie piszesz na forum, że napisałem w książce coś - czego nigdy nie napisałem.

procek87 napisał(a):
Zastanawia mnie po zdefiniowaniu tablicy gdzie jest przetrzymywany ten adres zawarty w nazwie tab ?


Nigdzie nie jest przetrzymywany - ty wciąż po prostu nie możesz zrozumieć tego, że kompilator musi taką tablicę gdzieś umieścić w pamięci, pod jakimś adresem. A skoro tak - to dlatego wszędzie w całym kodzie gdy ktoś posłuży się nazwą to kompilator wie do jakiego adresu się odwołać.

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 15 kwi 2018, o 19:43 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 26 maja 2017
Posty: 143
Pomógł: 0

mirekk36 napisał(a):

procek87 napisał(a):
Zastanawia mnie po zdefiniowaniu tablicy gdzie jest przetrzymywany ten adres zawarty w nazwie tab ?


Nigdzie nie jest przetrzymywany - ty wciąż po prostu nie możesz zrozumieć tego, że kompilator musi taką tablicę gdzieś umieścić w pamięci, pod jakimś adresem. A skoro tak - to dlatego wszędzie w całym kodzie gdy ktoś posłuży się nazwą to kompilator wie do jakiego adresu się odwołać.


tab[]={1,2,4,8,16,32,64,128}

Mirku rozumiem to że tablica dokładnie tych kilka komórek uint8_t , które są ułożone jedna po drugiej, i jest na nich etykieta tab[] i to jest tablica w uproszczeniu .

Nie rozumiem jednego jeśli nazwa Tab bez nawiasów okrągłych oznacza adres do elementu pierwszego tablicy to skoro tak to ten adres musi być gdzieś przetrzymywany w dwóch komórkach pamięci , dlatego że nazwa tablicy jest wskaźnikiem do miejsca pamięci o adresie , zawierającym elementy -1,-2 itd . bajtowe.

Cytuj:
mnie nie razisz dokąd nie piszesz na forum, że napisałem w książce coś - czego nigdy nie napisałem.


Dyskutujemy dzięki temu się uczymy , dyskusje są budujące , i zmuszają do zastanawiania się. ;)



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 15 kwi 2018, o 20:01 
Offline
Użytkownik

Dołączył(a): 07 cze 2016
Posty: 563
Pomógł: 143

procek87 napisał(a):
Zastanawia mnie po zdefiniowaniu tablicy gdzie jest przetrzymywany ten adres zawarty w nazwie tab ?
Bo przecież nazwa zawiera adres ,na który patrzy wskaźnik do elementu uint8_t tak to odebrałem po przeczytaniu rozdziału o Wskaźnikach.

Asembler odpowiedziałby na moje pytania ale nie znam go i bardzo ciężko mi analizować plik .lss może ktoś pomoże, i opisze co i gdzie się dzieje z tą tablicą w asemblerze ;) ?

Nie zrozum mnie źle. To nie jest jakaś złośliwość czy brak chęci pomocy. Ja już raz odpowiedziałem na Twoje pytanie dość szczegółowo w innym wątku, tylko aby zrozumieć, trzeba już mieć jakąś wiedzę np. dotyczącą budowy i zasady działania mikrokontrolera, jego listy rozkazów, assemblera itp.
Ty tej wiedzy jeszcze nie masz, dlatego nie zrozumiałeś, więc zadajesz następne pytania. Odpowiedź na te pytania zapewne zrodzi następne pytania itd. W ten sposób można napisać na forum całą książkę, a forum do tego nie służy.

Ale OK, spróbuję jeszcze raz (ostatnie podejście), oczywiście w dużym uproszczeniu i postaram się jak najprzystępniej dla początkującego. Opis dotyczy zmiennych globalnych i nie uwzględnia procesu inicjowania wartości zmiennych wartościami podanymi przez programistę, aby nie zaciemniać sprawy ;) Zmienne lokalne są alokowane na stosie, a to już zupełnie inna historia.
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

Kiedy kompilator C napotka taką definicję tablicy myśli sobie tak:

Programista chce mieć do dyspozycji zmienną zmienna_a typu uint16_t. Trzeba zarezerwować odpowiednią ilość bajtów pamięci RAM w pierwszej dostępnej lokalizacji. Aktualnie pierwszym dostępnym adresem jest 0. Zmienna jest 16-bitowa, więc zajmie 2 bajty.

Kompilator na podstawie tej definicji robi więc co następuje:
  • zapisuje sobie w swojej pamięci podręcznej symbol zmienna_a,
  • przypisuje symbolowi adres w pamięci RAM równy początkowi pamięci RAM, np. dla Atmega8 jest to adres 0x0060,
  • przypisuje do symbolu rozmiar, który w tym przypadku wynosi 2 bajty,
  • zapamiętuje też inne rzeczy, które w tej chwili nie są dla nas bardzo istotne.

Na podstawie następnej definicji robi tak:
  • zapisuje sobie w swojej pamięci podręcznej symbol tab,
  • przypisuje symbolowi adres w pamięci RAM, który jest sumą adresu poprzedniego symbolu i przypisanego mu rozmiaru, czyli (0x0060+0x02)=0x0062,
  • przypisuje do symbolu rozmiar, który w tym przypadku wynosi (8 elementów) * (1 bajt) = 8 bajtów.

Na podstawie następnej definicji robi tak:
  • zapisuje sobie w swojej pamięci podręcznej symbol zmienna_b,
  • przypisuje symbolowi adres w pamięci RAM, który jest sumą adresu poprzedniego symbolu i przypisanego mu rozmiaru, czyli (0x0062+0x08)=0x006A,
  • przypisuje do symbolu rozmiar, który w tym przypadku wynosi 1 bajt.

Na podstawie następnej definicji robi tak:
  • zapisuje sobie w swojej pamięci podręcznej symbol wsk,
  • przypisuje symbolowi adres w pamięci RAM, który jest sumą adresu poprzedniego symbolu i przypisanego mu rozmiaru, czyli (0x006A+0x01)=0x006B,
  • przypisuje do symbolu rozmiar, który w tym przypadku wynosi 2 bajty.

Należy pamiętać o tym, że kompilator do tej pory jeszcze nigdzie żadnego adresu nie umieścił w kodzie, po prostu te adresy sobie pamięta.

Jeśli teraz napotka w kodzie np. taką linijkę:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

to może wygenerować taki przykładowy kod (sposobów jest oczywiście więcej, więc nigdy nie wiadomo, który sposób kompilator wybierze jako najbardziej optymalny w danym momencie):
Składnia: [ Pobierz ] [ Ukryj ]
język asm
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Jeśli później napotka w kodzie np. taką linijkę:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

to może wygenerować taki przykładowy kod:
Składnia: [ Pobierz ] [ Ukryj ]
język asm
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Wywołanie funkcji, której argumentem jest wskaźnik do tablicy:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
będzie wyglądało mniej więcej tak:
Składnia: [ Pobierz ] [ Ukryj ]
język asm
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Jak widać kompilator w momencie napotkania definicji zmiennej (jakiejkolwiek, nie tylko tablicy) nie musi od razu nigdzie zapisywać wartości przydzielonego jej adresu w pamięci RAM. On ten adres po prostu zapamiętuje w swojej pamięci podręcznej na czas kompilacji i wstawia jego wartość do odpowiednich poleceń assemblera jako ich argumenty dopiero w momencie, gdy w kodzie jest odwołanie do danego symbolu.

Oczywiście w rzeczywistości sprawa jest nieco bardziej skomplikowana, ale po szczegóły zapraszam już do wspomnianej wcześniej w innym wątku literatury.

Jeżeli nadal nie zrozumiałeś, to ja się już niestety poddaję. Ponieważ interesują Cię takie szczegóły powinieneś jednak duuużo poczytać o budowie i zasadzie działanie mikrokontrolera, o kodzie maszynowym i instrukcjach ASM, a także o zasadzie działania kompilatora, a wtedy na pewno wszystko się wyjaśni.

Pozdrawiam
Andrzej



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 16 kwi 2018, o 17:42 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 26 maja 2017
Posty: 143
Pomógł: 0

Dziękuje andrews za szczegółowe wyjaśnienie bardzo cenny kawał wiedzy bardzo cennej dla początkującego jak narazie czytam książkę BB i nie zbaczam z kursu choć czasem właśnie dobrze coś dokładniej przeanalizować .



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
Wyświetl posty nie starsze niż:  Sortuj wg  
Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 5 ] 

Strefa czasowa: UTC + 1


Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zidentyfikowanych użytkowników i 0 gości


Nie możesz rozpoczynać nowych wątków
Nie możesz odpowiadać w wątkach
Nie możesz edytować swoich postów
Nie możesz usuwać swoich postów
Nie możesz dodawać załączników

Szukaj:
Skocz do:  
Sitemap
Technologię dostarcza phpBB® Forum Software © phpBB Group phpBB3.PL
phpBB SEO