[Asm] Dlaczego Org 0000

0

Prosze spojrzec do tej strony : http://colony.devtown.net/site/Kurs_pisania_OS_-_tryb_rzeczywisty.html i podpunkt 07h. Zupelnie nie wiem czemu autor tego textu pisze ze jesli wrzucimy kod jadra pod adres 0800h:0000h to wtedy zaczynamy od 0000h i piszemy ORG 0000... rozumiem ze ORG zmienia tylko adresy etykiet, ale przeciez zeby napisac ze zaczynamy od 0000h to musimy wiedziec ze CS bedzie ustawione na 0800h bo inaczej to nie ma sensu. Skad to wie ten autor ?</email>

0

Wie to z tej linijki :

jmp 0800h:0000h

jest to daleki skok pod adres 0800h:0000h czyli do cs ląduje pierwsza częśc ( 0800h ) a do ip druga.
Gdyby skoczył do 0000h:8000h to wtedy miałby w cs zero ale wymagane byłoby użycie org 8000h.
Pierwsze rozwiązanie jest dużo lepsze ;p

0

jestes pewien ? bo mi sie to nie podoba po pierwsze dla tego ze te dwa adresy sa takie same : 0800:0000 i 0000:8000 a po drugie zobacz sobie ta sama strone i podpunkt 06h. Koles pisze ze BIOS laduje bootloadera pod adres 07C0:0000 a mimowszystko umieszcza w bootloaderze dyrektywe ORG 7C00. Wiec co ty na to ?

0

a przepraszam co ma kod jądra do boot loadera? boot loadera wrzucasz pod 7c00 a ten z kolei wrzuca kernel pod 8000

0

CyberKid: o co ci chodzi ? bootloader ma do jadra tyle ile jest napisane na stronie w linku wyzej...

0

wielkie pardon. Jak dla mnie to troszkę późna pora i mózg mi trochę szwankuje. Co do głównego problemu to radzę Ci sprawdzić CS w momencie gdy boot loader przejmuje kontrolę ;) Chociaż wydaje mi się, że autor odruchowo przetłumaczył adres 07c0:0000 na 0:7c00. Zresztą zaraz zbacze w kursie na 4p co tam piszą o punkcie startowym boot loadera

[edited]
okazuje się, że kurs na 4p i ten podany przez autora postu to jedno i to samo ... Co do ORGa to znalazłem w sieci jeden manual o pisaniu programów bootujących i rzeczywiście użyli tam org 0 ...

Mam nadzieję, że w miare logicznie napisałem i nie napociłem żadnych głupot. A teraz idę na zasłużony odpoczynek :P

[edited2]
Wydaje mi się, że jednak boot loader jest ładowany do 0:7c00 ;)

http://kos.enix.org/pub/bootwrit.html napisał(a)

mov ax,0x7c0 ; BIOS puts us at 0:07C0h, so set DS accordinly
mov ds,ax ; Therefore, we don't have to add 07C0h to all our data

0

eh... dlaczego nie mozecie mi odpowiedziec na najprostsze pytania ( moze faktycznie nie sa takie proste, ale sa na pewno podstawowe ) ? Juz sie mecze z tym od dawna. Duch napisal cos co zupelnie nie przystaje do tego co napisal autor strony ktora umiescilem wyzej. Bo gdyby postapic tak jak pisal Duch to trzebaby traktowac adres 07c0:0000 tak jakby do CS byl wpisywany 7c0... a jak 0000:7c00 wtedy 0000. Ale jak juz pisalem autor strony o ktorej pisalem wyzej mowi ze adres pod ktory ladowany jest bootloader to 07c0:0000 a i tak w bootloaderze pisze ORG 7c00. Jak sami widzicie te dwa zdania Ducha i Wolverina ( bo to on jest autorem tamtej strony ) sie jakby wykluczaja... Ja powiem wam ze ni potrafie zrozumiec tutaj jednej rzeczy zalozmy ze BIOS laduje jakis kod pod adres abcd:efgh moje pytanie brzmi: jaki jest adres poczatku segmentu do ktorego zaladowany jest kod , co bedzie wstawione do CS'a , jakie powinno byc przesuniecie dyrektywa ORG ? Czy w ogole mozna po takich danych to przewidziec ? To jest dla mnie powazny problem.

pzdr.

0

zalozmy ze BIOS laduje jakis kod pod adres abcd:efgh moje pytanie brzmi: jaki jest adres poczatku segmentu do ktorego zaladowany jest kod , co bedzie wstawione do CS'a , jakie powinno byc przesuniecie dyrektywa ORG ? Czy w ogole mozna po takich danych to przewidziec ? To jest dla mnie powazny problem.

CS = abcd
IP = efgh

IMO teraz zakladajac, ze DS = 0 dajemy ORG = efgh (gdyby DS bylo >0 to trzeba juz to policzyc albo wyzerowac). Ale sam juz sie pogubilem.

0

To co napisał Wolverin i ja się nie wyklucza ;p Ja pisałem tutaj o KERNELU a nie o bootloaderze.
Musisz zrozumieć to że cs:ip w momencie startu jest ustawione na 0:7c00h ale tylko CS i IP, kiedy odwołujesz sie do danych ( przez rejestr DS lub ES ) możesz korzystać z zestawienia 07C0h : 0000 bo na to samo wyjdzie w końcu to ten sam adres fizyczny.
Przykład :

[ORG 0h]   
mov ax, 07C0h   
mov es, ax
mov ds, ax        ; ładujemy adres segmentu ( adres liniowy div 16 ) do segmentów       
                ;danych (DS, ES) - pod ten adres załadował nasz bot bios =]
cli                   ; wyłączamy przerwania bo chcemy ustawić stos                                 
mov ss, ax               
mov sp, 0xffff        ; stos zaczyna się pod adresem  0x07C0 : 0xffff
sti                              ; można włączyć przerwania

mov si, msg        ; ładujemy ADRES tekstu do si
next_char:    
 mov al, [si]        ; wczytujemy znak z pod adresu si
 or al, al            ; operacja logiczna nie zmieni wartości al,
                  ;ale ustawi flage Z = 1 gdy al = 0
 jz char_end        ; jeżeli Z = 1 to koniec ; al = 0 =P
 inc si            ; przeskocz do następnej literki  => si := si + 1
 mov ah, 0eh        ; \
 int 10h            ; /  funkcja wyświetla znak o kodzie w al.
 jmp next_char        ; skok do &#8222;next_char&#8221;
char_end:        ; tutaj dojdziemy gdy skończy pisać

     
jmp     $                    ;  skacze sam do siebie ($ - aktualny adres)
              ;zawiesza żeby nie poszło dalej .. bo tam  nie ma kodu

msg  DB 'Witaj w boot sektorze.', 13, 10, ' I to tyle :P ', 13, 10, 0   ; nasz tekst

times 510-($-$$) db 0      ; uzupełnienie pliku tak aby zawierał 510 bajtów

dw 0xAA55                ; sygnaturka (2 bajty), plik ma razem 512 bajtów (200h)

I działa :]

A jeżeli chodzi o kernela to jużod ciebie zależy czy CS:IP będzie ustawione jako 0800h : 0000 (jmp 0800h:0000) czy 0000h : 8000h ( jmp 0000: 8000h )
ale uzywanie ogr można też zastąpić jak tutaj w zamieszczonym bootloaderze :]
Czemu lepiej korzystać z adresu 0800h : 0000 ? ponieważ jak wiesz ( albo i nie ) IP jest dwu bajtowe, tak więc jest ograniczone do 65536 bajtów! kiedy liczysz od zera masz całe 65536 bajtów do dyspozycji, natomiast licząc od 8000h masz już IP ograniczone o 32768 bajtów czyli o połowę! tak wiec kernel może mieć max 32 Kib a nie 64Kib

0

Notak cały ten tutorial wydaje sie być dobrze napisany bo sprawdzałem sam kod i działa. Jest pewnie kilka błędów w opisie tego kodu. No jednym jest właśnie napisanie, że BIOS ładuje boot loader pod adres 07C0:0000 i sacze pod niego. Lepiej było by napisać:
BIOS ładuje BootL pod adres 0000:7C00 i skacze pod ten adres
albo:
BIOS ładuje BootL pod adres 0x7C00 i skacze pod adres 0000:7C00
else:
BIOS ładuje BootL pod adres 07C0:0000 i skacze pod adres 0000:7C00

Bo sama kwestia ładowania nie jest taka ważna tylko to jak tam się potem idzie.

0

Wiec mam rozumiec ze mozna to opisac jednym zdaniem:

adres 07c0:0000 jest rozny od adresu 0000:7c00 tym w skoku ze w pierwszym mamy taki ustawienie rejestrow :

CS = 7c0
IP = 0000

w drugim natomiast:

CS = 0000
IP = 7c00

tak ?

( Jesli tak to Twoje odpowiedzi duchu z wolverinem sie wykluczaly, chyba ze wolverin popelnil po prostu literowke piszac : "BIOS ładuje pierwsze 512 bajtów z dysku (dyskietki, płyty CD/DVD czy czegokolwiek innego) do pamięci pod adresem 07C0:0000 ( tutaj powinno byc 0000:7c00 ) i skacze w to miejsce" a pozniej w kodzie: "org 7C00h" )

0
opx napisał(a)

Wiec mam rozumiec ze mozna to opisac jednym zdaniem:

adres 07c0:0000 jest rozny od adresu 0000:7c00 tym w skoku ze w pierwszym mamy taki ustawienie rejestrow :

CS = 7c0
IP = 0000

w drugim natomiast:

CS = 0000
IP = 7c00

tak ?

Przecież cały czas ci to powtarzałem... na przykładzie kernela i bootloadera.

opx napisał(a)

( Jesli tak to Twoje odpowiedzi duchu z wolverinem sie wykluczaly, chyba ze wolverin popelnil po prostu literowke piszac : "BIOS ładuje pierwsze 512 bajtów z dysku (dyskietki, płyty CD/DVD czy czegokolwiek innego) do pamięci pod adresem 07C0:0000 ( tutaj powinno byc 0000:7c00 ) i skacze w to miejsce" a pozniej w kodzie: "org 7C00h" )

ehhh co za różnica czy ładuje go pod adres 0x07C0 : 0000 czy 0x0000 : 0x7C00 skoro to jest TO SAMO MIEJSCE W PAMIECI?

Dodane:

[ORG 0x0C00]   
mov ax, 0x0700   
mov es, ax
mov ds, ax
                
cli             
mov ss, ax               
mov sp, 0xffff  
sti                   
mov si, msg     
next_char:    
 mov al, [si]     
 or al, al          
                  
 jz char_end
 inc si         
 mov ah, 0eh 
 int 10h         
 jmp next_char 
char_end:        

     
jmp     $           
          

msg  DB 'Witaj w boot sektorze.', 13, 10, ' I to tyle :P ', 13, 10, 0  

times 510-($-$$) db 0   

dw 0xAA55    

Ten kod też działa .... no to gdzie teraz jest załadowany? ;-)

0
ADuch napisał(a)

ehhh co za różnica czy ładuje go pod adres 0x07C0 : 0000 czy 0x0000 : 0x7C00 skoro to jest TO SAMO MIEJSCE W PAMIECI?

no moim zdaniem roznica jest taka ze w pierwszym wypadku CS = 07c0 a ip = 0000,
w drugim zas CS = 0000 a ip = 7c00. W twoim przykladzie ktory teraz pokazales oczywiste jest ze niezaleznie od tego jak ustawiony jest CS i IP ty i tak dostaniesz sie do danych i pobierzesz je i kod bedzie dzialal. Dzieje sie tak poniewaz dzialasz z innymi rejestrami niz IP i CS i wiesz dokladnie gdzie fizycznie ten kod lezy... Ale gdy chcesz dzialac wylacznie z CS i odwolywac sie np tak do danych, mov ax,cs:[msg] bo jedyna poszlake o miejscu w pamieci programu odczytujesz z CS to bardzo wazne jest jak ustawisz ORG'a i wtedy musisz wiedziec czy kod jest wywolywany przez 07c0:0000 czy 0000:7c00. Ja wiem ze to jest niby troche bez sensu bo jesli znasz adres w pamieci to mozesz posluzyc sie metoda taka jak podales ale jesli chcesz byc elegancki i pisac kod pod siebie to musisz to wiedziec. Ogolnie jednak org mozna zastowac prawie dowolny i mozna zrobic ze i tak bedzie dzialalo... dzieki za odpowiedzi...

0

No teraz ci przyznaje racje :] Ale popatrz na to tak, są różne biosy .. różne wersje i np u jednego może bios wchodzić przez jmp 0x07C0 : 0x0000 a inny bios np przez jmp 0x0000 : 0x7C00 albo jeszcze inaczej :P to pewnie jest uzależnione od biosu. Jeżeli jednak chcesz sie w to bawić nie widzę przeszkód w napisaniu prostego bootloadera wypisującego zawartośc CS i IP w momencie startu :]

Dodane:

[ORG 0]   
DB 0xE8, 0x00, 0x00, 0x5D, 0x83, 0xED, 0x03

cli             
mov ax, cs
mov ss, ax               
mov sp, 0xffff 
sti

mov si, msg
next_char:    
 mov al, [cs:si+bp] 
 or al, al    
              
 jz char_end  
 inc si       
 mov ah, 0eh  
 int 10h      
 jmp next_char
char_end:     

     
jmp     $  
           

msg  DB 'Witaj w boot sektorze.', 13, 10, ' I to tyle :P ', 13, 10, 0  

times 510-($-$$) db 0  

dw 0xAA55  

Ten kod załatwia sprawe adresowania :P nie musisz w ogóle wiedzieć gdzie znajduje się bootloader, program itd. sam wszystko pobiera :]
Zawsze w tym wypadku dajesz org 0 :P

Dodane 2:
mam jeszcze inny pomysł ... po prostu sam na początku zresetuj CS i IP :] Początek bootloadera wyglądałby wtedy tak :

[org 0]
jmp 0x07C0 : start
start:
mov ax, cs
mov ds, ax
mov es, ax

Teraz masz pewność co do ustawienia rejestrów CS i IP

0

Pisząc na stronie, że bootloader jest ładowany pod adres 0x07c0:0x0000 popełniasz zwykły błąd, ogłupiając tym samym czytelnika. Równie dobrze mogłeś napisać, że bootloader ładowany jest pod adres 0x0123:0x69D0 (przecież to ten sam adres fizyczny co 0x0000:0x7C00 !!!). Nie ma znaczenia że 0x07c0:0x0000 i 0x0000:0x7c00 to ten sam adres fizyczny. W trybie rzeczywistym operuje się na adresach logicznych a te dwa adresy logiczne są po prostu różne. Każdy kto zna sie na programowaniu w trybie rzeczywistym i adresach logicznych po przeczytaniu informacji że adres bootloadrea to 0x07c0:0x0000, zaczął by pisać taki loader od dyrekrywy "org 0x0000" a nie od "org 0x7c00".

0

mczarny: dlaczego ten drugi kod mialby sie nie wykonac ? dlatego ze uzyles call, ale nie rozumiem za
za bardzo co call zmienia... jak zdeasemblowalem twoj kod ktory ma sie niby nie wykonac nic znaczacego co mogloby zaklocic dzialanie programu nie pojawilo sie...

Ogolnie zastanawia mnie pewna rzecz: skoro skok jmp jest skokiem wzglednym to dlaczego gdy deasembluje kod nie widac wartosci o ile trzeba przesunac ip tylko widac juz tak naprawde podana wartosc
ktora trzeba wstawic do ip tak jakby jmp nie bylo skokiem wzglednym.

Dalej mam taki problem z jmp far i jmp nearr. Co tak naprawde dzieje sie podczas tych dwoch skokow czym one sie od siebie roznia ?

0
opx napisał(a)

mczarny: dlaczego ten drugi kod mialby sie nie wykonac ? dlatego ze uzyles call, ale nie rozumiem za
za bardzo co call zmienia... jak zdeasemblowalem twoj kod ktory ma sie niby nie wykonac nic znaczacego co mogloby zaklocic dzialanie programu nie pojawilo sie...

Faktycznie namieszałem :-/ . Co do tego call to faktycznie kod sie wykona ponieważ call tak samo jak jmp nie wpisuje do ip domyślnej wartości tylko dodaje do niego przesunięcie. Tak że wielkie sorki za zamieszanie.

Ale tan kod juz nie zadziała, ponieważ do bx ładowany jest offset który później wstawiany jest do ip:

[ORG 0x0C00]   
mov ax, 0x0700   ;adres tego rozkazu to 0000:7C00 
mov es, ax
mov ds, ax
                
cli             
mov ss, ax               
mov sp, 0xffff  
sti                   
mov si, msg
     
mov bx, offset next_char  
call bx     ;do ip zostanie wpisana wartość 0C18 , a powinna być wpisana wartośc 7C18
     
jmp     $           
          
next_char:    
 mov al, [si]     ;adres tego rozkazu to 0000:7C18
 or al, al          
                  
 jz char_end
 inc si         
 mov ah, 0eh 
 int 10h         
 jmp next_char 
char_end:
 ret        

msg  DB 'Witaj w boot sektorze.', 13, 10, ' I to tyle :P ', 13, 10, 0  

times 510-($-$$) db 0   

dw 0xAA55    
opx napisał(a)

Ogolnie zastanawia mnie pewna rzecz: skoro skok jmp jest skokiem wzglednym to dlaczego gdy deasembluje kod nie widac wartosci o ile trzeba przesunac ip tylko widac juz tak naprawde podana wartosc
ktora trzeba wstawic do ip tak jakby jmp nie bylo skokiem wzglednym.

Zależy jakiego deasemblera używasz. Deasemblery są dla ludzi i automatycznie obliczają adresy ip po skoku po to żeby dana osoba wiedziała gdzie nastapi skok , bo inaczej sama musiała by to liczyć co jest raczej rzeczą nieciekawą. Np. zdeasemblowany rozkaz skoku wyglada tak (cała linijka z W32Dasm):

:0001.0D31 E9B0FE jmp 0BE4

Pierwszy jest adres logiczny czyli cs:ip. Następnie widać kod rozkazu E9 - skok near, B0FE - przesunięcie tyle że trzeba zamienić miejscami bajty czyli przesunięcie wynosi FEB0 (jest ujemne). no i na koncu masz zdeasemblowany rozkaz. No i deasembler robi tak: patrzy jaki jest aktualnie adres logiczny rozkazu a dokładnie offset (w trybie rzeczywistym) i do niego dodaje przesunięcie po czym pisze wynik po jmp czyli: 0D31 + FEB0 = 0BE4 (oczywiście liczymy w kodzie U2), wiec deasembler pisze "jmp 0BE4"

opx napisał(a)

Dalej mam taki problem z jmp far i jmp nearr. Co tak naprawde dzieje sie podczas tych dwoch skokow czym one sie od siebie roznia ?

Różnią się tym, że jak widziałeś wyżej skok near powoduje dodanie przesunięcia do ip, czyli za pomocą tego skoku możesz skoczyć tylko w obrębie segmentu. Natomiast skok far nie dodaje przesunięcia do ip. Ten skok wpisuje konkretne wartości do cs i ip.

0

po pierwsze: nawet nie moge zkompilowac twojego kodu poniewaz nasm ktorego uzywam nie ma w swoim repertuarze czegos takiego jak offset... ( przynajmniej na to by wygladalo ), ale udalo mi sie wsadzic to do tasma i zrobic z tego plik obj... i wlasnie zastanawiam sie czy czasem "offset jakis_label" w tasmie nie jest rownowazny "jakis_label" w nasmie... ( bo ogolnie dziala podobnie ale czy pod kazdym wzgledem jest takie same )

po drugie: dlaczego nasm nie obsluguje (przynajmniej na razie nie znalazl nic na ten temat) dyrektywy segment ?

po trzecie:

dobrze wiec jaka jest roznica w rozkazach:

jmp far label
jmp label

nastepnie tych:

jmp far "jakis_seg":"jakis_offset"
jmp "jakis_seg":"jakis_offset"

nastepnie:

jmp near label
jmp label

I w jaki sposob moge zastosowac skok wzgledny o wartosc okolo +/-32000 ?

0

[diabel] [diabel] [diabel] [diabel] [diabel] [diabel] [diabel] [diabel]
PRZECZYTAJ SOBIE MANUALA POBRANEGO ZE STRONY PRODUCENTA
KAPISZI

[glowa] [glowa] [glowa] [glowa] [glowa] [glowa] [glowa] [glowa]


dobijasz mnie. naucz się dobrze asma zanim przystąpisz do pisania os'a
bo jak zobacze kolejny taki post to zwymiotuje
I nie kompiluj asemblera AT&T w kompilaorze ze skladnia Intela.
i jeszcze se sunSPARC z x86 nie pomyl
bu jak mnie wnerwiles.

0

A w którym miejscu w temacie użyto składni AT&T?
Które z rozkazów nie działają na x86?
Z tego co zrozumiałem opx nie zamierzał tutaj pisać OS-a.

0

sck7: to moze chlopie sie tak nie denerwuj bo na starosc jeszcze bedziesz musial przez rurke srac jak ci z pol jelita wytna...

btw.
Staram sie szukam informacji po calym internecie, jak wiadomo manuale sa czesto dosc obszerne i czasami jest ciezko znalezc cos co naprawde cie interesuje dlatego odzywam sie tutaj...

Jak juz uprzedzil mnie szablozebny: nie wiem gdzie uzyta jest skladnia AT&T.
Jak na razie Os'a zadnego nie pisze... raczej staram sie dowiedziec czegos wlasnie z zakresu asemblera i teoretycznych podstaw pisania Os'ow.

Moje ostatnie pytania sa nadal aktualne...

0
opx napisał(a)

wlasnie zastanawiam sie czy czasem "offset jakis_label" w tasmie nie jest rownowazny "jakis_label" w nasmie...

Tak, w nasmie etykieta to offset do etykiety, [etykieta] to wartosc pod adresem etykiety. W tasmie nie wiem jak jest, w ogole tasm sux.

opx napisał(a)

po drugie: dlaczego nasm nie obsluguje (przynajmniej na razie nie znalazl nic na ten temat) dyrektywy segment ?

Moze dlatego, ze do niczego sie nie przydaje? Jak chcesz sekcje w PE, ELFie itp to masz dyrektywe section

opx napisał(a)

dobrze wiec jaka jest roznica w rozkazach:[...]

Odpowiem na polowe, jmp seg:offs skacze wiadomo gdzie, jmp offs skacze do cs:offs, ale juz np mov ax, [offs] pobiera dane z ds:offs.

1 użytkowników online, w tym zalogowanych: 0, gości: 1