Informacje o kodzie zawartym w plikach Intel Hex...

To forum jest dla wszystkich pasjonatów wiecznie młodych mikrokontrolerów '51. Wymiana doświadczeń i pomoc dla początkujących w pisaniu programów zarówno w C, Asemblerze jak i BASCOM. Zapraszam znawców tematu, aby pomogli wszystkim początkującym!
ODPOWIEDZ
Awatar użytkownika
Sagittarius
Użytkownik
Posty: 130
Rejestracja: 29 maja 2007, 9:29
Lokalizacja: Kujawsko-pomorskie
Kontakt:

Informacje o kodzie zawartym w plikach Intel Hex...

Post autor: Sagittarius » 19 lut 2008, 8:16

Z pewnością każdemu piszącemu program na mikrokontroler z ograniczoną pamięcią (np 89C2051) zdarzyło się, że ostateczny kod okazał się odrobinę za duży do posiadanej pamięci. Napisałem program, który pozwoli na wyświetlenie informacji zarówno o adresach, pod jakie załadowany jest program, o ilości bajtów, jak i rozmiarze kodu. Mi już kilka razy ten program pomógł. Jest to wersja testowa i ma pewne ograniczenia. Programik jest zarówno w wersji dla systemów Linux, jak i dla konsoli Windows. Aktualna wersja powstała w C.

Opis oraz program dostępny jest na:

1) Wersja polska: http://maciej.sochaczewski.w.interia.pl/hexinfo.htm

2) Wersja angielska: http://maciej.sochaczewski.w.interia.pl/e_hexinfo.htm
Ostatnio zmieniony 28 lut 2008, 7:45 przez Sagittarius, łącznie zmieniany 1 raz.

tasza
Użytkownik
Posty: 1389
Rejestracja: 21 lut 2005, 15:02

Post autor: tasza » 19 lut 2008, 12:49

Fajne.
Nie prosiłeś wprawdzie o komentarze, ale pozwoliłam sobie na mały test i poniżej
z niego wnioski....może skorzystasz.

Wyobraźmy sobie taki "kawałek programu" ( składania SB-Assembler, http://www.sbprojects.com/sbasm/sbasm.htm )

Kod: Zaznacz cały

	.cr	8085            
	.tf maciek.hex,int
	.li on,mon,con
	.lf maciek.lst , 60	
	;
	.or $0100
	;
	.db $00,$11,$22,$33,$44,$55
	;
	.or $0200
	;
	.db "abcdefgh"
	;			
Widać, że bloki stałych są ulokowane w dwóch miejscach - od adresu 100h i 200h
Listing:

Kod: Zaznacz cały

0000-                 5         ;
0100-                 6         .or $0100
0100-                 7         ;
0100-00 11 22 33 
0104-44 55            8         .db $00,$11,$22,$33,$44,$55
0106-                 9         ;
0200-                10         .or $0200
0200-                11         ;
0200-61 62 63 64 
0204-65 66 67 68     12         .db "abcdefgh"
0208-                13         ;                       
0208-                14                         
Symbol table
0 Errors in assembly
Symbol table size $00000
Unused memory     $91334
i plik HEX:

Kod: Zaznacz cały

:06010000001122334455FA
:080200006162636465666768D2
:00000001FF
Zakładając, że to rzeczywisty wsad do załadowania do pamięci - rozsądnie napisany loaderek
spokojnie sobie z nim poradzi...po prostu z pierwszych bajtów rekordu ihex pobierze adres startowy
od niego począwszy będzie składował w pamięci nadsyłane dane.

Co nam pokaże Twój programik? Proszę:

Kod: Zaznacz cały

D:\DOWNLO~1\sbasm\src>hexinfo /s MACIEK.HEX

Code size (MACIEK.HEX): 264 bytes

Warning (262) !!!       Small characters 'a'...'f' in file!


D:\DOWNLO~1\sbasm\src>hexinfo /a MACIEK.HEX

File: MACIEK.HEX
===================================================================
Start address:          0100 h
End address:            0207 h

Warning (262) !!!       Small characters 'a'...'f' in file!
===================================================================


D:\DOWNLO~1\sbasm\src>
(btw: tego ostrzeżenia nie rozumiem, czy możesz kilka słów?)

I teraz tak - z pewnego punktu widzenia program ma rację - pierwszy wykorzystany w hex
adres się zgadza, wyliczony adres ostatniego - niby też...choć de facto wsad zawiera o wiele
mniej danych, pomiędzy którymi jest przerwa, tak?
Podobnie z wartością codesize - ona wynika z adresów, ale przy założeniu,
że to ciągły obszar danych a nie sieczka (o tym dalej).

Więc może byłoby warto wprowadzić opcję bardziej detalicznego raportowania co jest
w pliku hex i w którym miejscu, z inteligentnym wykrywaniem pustych miejsc.

Inna rzecz, chyba bardziej praktyczna (i relatywnie prostsza do oprogramowania) to
taki jakby alarm, że hex przekroczył dopuszczalną masę i pewnie się w kontroler nie da zapakować,
Myślę i dodatkowym parametrze podawanym z linii poleceń, który określałby limit pamięci.
Jeżeli program wykryje że coś ewentualnie nie wejdzie - jest monit:
"przekroczony limit rozmiaru kodu / memory limit exceeded"

a przykładowe (tak sobie wyobrażam) wywołanie to: hexinfo /m2048 anyfile.hex

Oczywiście takie ostrzeżenie powinno także ustawiać inny od success kod zakończenia
procesu. To umożliwi wykorzystanie programiku np. w skrypcie shell/bat na zasadzie:
gdy był taki warn - np. nie wywołuj loadera itp.

A co do sieczki, przykład z życia wzięty - okruch kodu źródłowego, którego wynikowy hex
jest ładowany do pamięci o dość nietypowej mapie...
mi osobiście bardzo by się przydał taki "raporter" ile i pod jakie adresy zostanie przez
loader wgrane...te informacje można wprawdzie pozyskać choćby z listingu,
ale chyba lepiej mieć jakieś specjalizowane narządko.

Kod: Zaznacz cały

			; dino-85 test code, v.1.0, n.biecek, 2008
			.cr	8085            
			.tf dino85_v1.hex,int
			.li on,mon,con
			.lf dino85_v1.lst , 60
			.in macros85.inc
					;
MAIN_START_POINT	.equ	$0000	; Z-POWER RAM area
USER_PROG_ENTRY 	.equ	$4000	; S-RAM
SAFE_AREA_ENTRY		.equ	$8000	; Z-POWER RAM area
USER_STACK 			.equ	$ffff	
					;
SYSTEM_PORT			.equ	$e0 ; system 8255 port address
STARTUP_IO_CFG		.equ	$89	; PA=out, PB=out, PC(hi/lo)=in, mode=0
IO_PA				.equ	0
IO_PB				.equ	1
IO_PC				.equ	2
IO_CTRL				.equ	3
					;	
			.or MAIN_START_POINT
			.TW   /'zero power ram area/,#$0D,#$0A					
			;
MAIN_START_POINT:					
			; user stack settings
			lxi h,USER_STACK
			sphl
			; initial system I/O setup
			mvi a,STARTUP_IO_CFG
			out SYSTEM_PORT + IO_CTRL
			; clear display and indication ports (PA,PB)
			mvi a,0
			out SYSTEM_PORT + IO_PA
			out SYSTEM_PORT + IO_PB
			;
			jp USER_PROG_ENTRY
			;
			;
			.or USER_PROG_ENTRY
			.TW   /'static ram area/,#$0D,#$0A	
			;
USER_PROG_ENTRY:
			mvi a,0				; zero PB 
LOOP:			out SYSTEM_PORT+IO_PB		; out on indication port
			inr a				; next value 2 displ.
			call DELAY			; wait a while
			jp	LOOP			; then repeat with next data
			;
			;
			.or SAFE_AREA_ENTRY
			.TW   /'zero power ram area - safe mode/,#$0D,#$0A
SAFE_AREA_ENTRY:					
			; 3 x NOP silly delay routine
DELAY:			push psw		; save cpu status
			mvi a,$ff		; init loop counter
DELAY_1:		nop			; simply do nothing
			nop
			nop
			dcr a			; counter--
			jnz DELAY_1		; repeat until != 0
			pop psw			; restore cpu stat.
			ret				
			;			

plik hex:

Kod: Zaznacz cały

'zero power ram area
:1000000021FFFFF93E89D3E03E00D3E0D3E0F200C8
:0100100040AF
'static ram area
:0B4000003E00D3E13CCD0080F2024006
'zero power ram area - safe mode
:0C800000F53EFF0000003DC20380F1C906
:00000001FF
Paradoksalnie, z takim wsadem poradzi sobie każdy loader, napisany tak, że jeżeli linia
nie zaczyna się od ":" lub zwyczajnie jest pusta - zostanie pominięta.
Twój programik się na tym wyłożył, co mnie nie ukrywam nieco zasmuciło....

Kod: Zaznacz cały

D:\DOWNLO~1\sbasm\src>hexinfo dino85_v.hex
Warning (2) !!! First character in file "dino85_v.hex" is not ':' !
D:\DOWNLO~1\sbasm\src>
pozdrawiam,
Natasza

Awatar użytkownika
Sagittarius
Użytkownik
Posty: 130
Rejestracja: 29 maja 2007, 9:29
Lokalizacja: Kujawsko-pomorskie
Kontakt:

Post autor: Sagittarius » 20 lut 2008, 7:11

Tasza napisała:
Fajne.
Nie prosiłeś wprawdzie o komentarze, ale pozwoliłam sobie na mały test i poniżej
z niego wnioski....może skorzystasz.
Do tej pory testowały program tylko dwie osoby, a jak wiadomo każdy program jest tak dobry i skuteczny, jak wiele testów przeszedł. Właśnie dlatego podałem link do programu. Jeśli ktoś odwiedzał stronę wcześniej możliwe, że trafił na hexinfo 0.81. Kod był napisany w C++ ale niestety były problemy z przenośnością i z rozmiarem generowanego programu na różnych platformach. Używam głównie Linuxa i nawet tu powstawały problemy z binariami na starszych wersjach jądra. Dodatkowo wspomniana wersja miała masę błędów. Sporo z nich usunąłem w aktualnej wersji, ale jest to jedna z początkowych wersji (nie ma nawet wersji 1). Wracając do tematu, mam nadzieję, że szersze grono testerów pozwoli mi odkryć błędy i rozwinąć funkcjonalność programu :-)
Wyobraźmy sobie taki "kawałek programu" ( składania SB-Assembler, http://www.sbprojects.com/sbasm/sbasm.htm )
...
Widać, że bloki stałych są ulokowane w dwóch miejscach - od adresu 100h i 200h
...
Zakładając, że to rzeczywisty wsad do załadowania do pamięci - rozsądnie napisany loaderek
spokojnie sobie z nim poradzi...po prostu z pierwszych bajtów rekordu ihex pobierze adres startowy
od niego począwszy będzie składował w pamięci nadsyłane dane.
Wiem o tym. Masz dużo racji, ale:
1) nie każdy loaderek jest rozsądnie napisany
2) nie zawsze początkowe linie programu zawierają faktyczny adres początkowy kodu i... ale o tym może dalej.
Co nam pokaże Twój programik?
...
(btw: tego ostrzeżenia nie rozumiem, czy możesz kilka słów?)
Ostrzeżenie wskazuje, że plik zawiera małe litery. Standardowy plik Intel Hex powinien zawierać duże litery. Na szczęście większość programów nie ma z tym problemów, ale jest to jednak pewne odstępstwo i zostało to zasygnalizowane.
I teraz tak - z pewnego punktu widzenia program ma rację - pierwszy wykorzystany w hex
adres się zgadza, wyliczony adres ostatniego - niby też...choć de facto wsad zawiera o wiele
mniej danych, pomiędzy którymi jest przerwa, tak?
Podobnie z wartością codesize - ona wynika z adresów, ale przy założeniu,
że to ciągły obszar danych a nie sieczka (o tym dalej).
Tak, racja. Pierwotnie codesize informował o objętości kodu. W którejś wersji została ta opcja usunięta i zastąpiona przez byte count, ale ostatecznie została przywrócona. Jest to celowo pozostawione. Informacją o ilości bajtów kodu jest byte count. W opcji –full (w windows /f) widać różnice między code size i byte count. Ta różnica właśnie wskazuje, że kod nie jest ciągłym łańcuchem bajtów. Trafiłem nawet na plik, gdzie rekordy nakładają się na siebie i ostatecznie adres początkowy i końcowy nie wskazują tego, ile bajtów jest w pliku. Taka sytuacja jest również sygnalizowana. Miałem okazję przetestować trochę „dziwactw”. Wiem, że plik może być taką „siateczką”. Kolejne wersje programu będą posiadały możliwość informacji o „dziurach” w programie. Może nie następna wersja, ale któraś kolejna z pewnością będzie posiadać zaimplementowaną obsługę takich informacji :-) Jak więc widzisz, problem był już „na warsztacie” zanim opublikowałem aktualną wersję :-)
Więc może byłoby warto wprowadzić opcję bardziej detalicznego raportowania co jest
w pliku hex i w którym miejscu, z inteligentnym wykrywaniem pustych miejsc.
Odpowiedź na tą ciekawą propozycję wyżej.
Inna rzecz, chyba bardziej praktyczna (i relatywnie prostsza do oprogramowania) to
taki jakby alarm, że hex przekroczył dopuszczalną masę i pewnie się w kontroler nie da zapakować,
Myślę i dodatkowym parametrze podawanym z linii poleceń, który określałby limit pamięci.
Jeżeli program wykryje że coś ewentualnie nie wejdzie - jest monit:
"przekroczony limit rozmiaru kodu / memory limit exceeded"

a przykładowe (tak sobie wyobrażam) wywołanie to: hexinfo /m2048 anyfile.hex

Oczywiście takie ostrzeżenie powinno także ustawiać inny od success kod zakończenia
procesu. To umożliwi wykorzystanie programiku np. w skrypcie shell/bat na zasadzie:
gdy był taki warn - np. nie wywołuj loadera itp.
Tak, ta opcja też jest na mojej liście „To do”. Jednak samo dodanie opcji /m nie wystarczy. Pozwoli ona na informację o tym, czy plik się zmieści dla domyślnego początku w adresie zerowym. Musi jednak być też możliwość określenia adresu początkowego, gdy np. program ładujemy do zewnętrznej pamięci. Lista wymaganych elementów jest trochę dłuższa. Dzięki Twoim uwagom widzę jednak, że mój punkt widzenia odnośnie kolejnych funkcji i opcji jest poprawny :-)
A co do sieczki, przykład z życia wzięty - okruch kodu źródłowego, którego wynikowy hex
jest ładowany do pamięci o dość nietypowej mapie...
mi osobiście bardzo by się przydał taki "raporter" ile i pod jakie adresy zostanie przez
loader wgrane...te informacje można wprawdzie pozyskać choćby z listingu,
ale chyba lepiej mieć jakieś specjalizowane narządko.
Postaram się spełnić Twoją prośbę. Proszę tylko o nieco cierpliwości.
Ciekawi mnie format komentarza w kodzie, który pokazałaś. Wygląda ciekawie, ale nie wiem, czy standard Intel Hex akceptuje takie dodatki. Jeśli tak, chętnie poczytam o tym i dodam opcję takiego komentarza :-)
Paradoksalnie, z takim wsadem poradzi sobie każdy loader, napisany tak, że jeżeli linia
nie zaczyna się od ":" lub zwyczajnie jest pusta - zostanie pominięta.
Twój programik się na tym wyłożył, co mnie nie ukrywam nieco zasmuciło....
To ostrzeżenie jest jednym z pierwszych, które powstało. Zostało użyte jako błąd. Kolejna wersja będzie posiadała kilka zmian. Jeśli pierwszym znakiem nie będzie ':' nie będzie to generowało błędu, może ewentualnie ostrzeżenie. Puste linie są również aktualnie błędem. W przyszłości będą posiadały status ostrzeżenia.
Aktualnie program wyświetla pierwszy napotkany błąd i przerywa sprawdzanie dalszych. W przyszłości chcę wprowadzić nieco inną zasadę. Chcę informować o wszystkich napotkanych błędach z ograniczeniem ilości błędów do np. pięciu. Chcę również generować odpowiednią informację w przypadku, gdy zawartość pliku nie jest plikiem Intel Hex. W dalszej kolejności chciałbym wprowadzić obsługę formatu rozszerzonego Intel Hex, ale tu problemem mogą być pliki testowe.

Tu jedna prośba. Jeśli ktoś zauważy problem, proszę o informację o nim oraz o plik, na którym błąd ten wystąpił. Sam posiadam około 40 plików testowych. Część wygenerowana przez różne kompilatory, część ręcznie obliczona. Zainteresowanym mogę udostępnić owe pliki.

Dziękuję za cenne uwagi i pozdrawiam ciepło.
Maciej

P.S. Kolejna wersja z większymi zmianami jest w trakcie przygotowywania.

[ Dodano: 2008-02-28, 07:49 ]
Umieściłem na stronie kolejną wersję programu. Zawiera ona kilka drobnych zmian i małych poprawek. Prace nad kolejną dużą wersją wciąż są w toku. Wszelkie uwagi mile widziane :-)

ODPOWIEDZ