[asm]Zamienia mi pozycje bl i bh :(

0

Odczytuje z pamieci 2 bajty, mam yasm jako kompilator i jest ogolnie ok ale mam maly prblem a mianowicie:

Mam w pamieci pod adresem xxxx:0x022B slowo: 0x00, 0x01 i na logige powinno odczytac tak:

bl = 0x01
bh = 0x00

i tak odczytuje wczesniej na poczatku programu inne dane z pamieci i dziala jak nalezy

ale niestety zamiast tego mam odczytane tak:

bl = 0x00
bh = 0x01

czyli odwrotnie niz powinno :(

Tak odczytuje:

add ax, 0x002C
mov di, ax
mov bx, [di]
mov [blockout], bx

Moze cos przeoczylem? jakas dzika flaga albo cos?

Tu jest caly kod programu a raczej prawiec skonczonego bootloadera:

[bits 16]

;main boot		
start:			cli
				mov ax, 0x07C0
				mov ds, ax
				mov es, ax
				mov fs, ax
				mov gs, ax
				mov ax, 0x0000
				mov ss, ax
				mov sp, 0xFFFF
				sti
				mov ax,0x0003
				int 0x10 ;clear and set screen
				mov ax, 0x1112
				xor bl, bl
				int 0x10 ;8x8 fonts
				mov si, booting
				call message
				call discinfo
				mov ax, kerneldir
				mov [filename], ax
				mov ax, [longdir]
				mov [namelenght], ax
				mov ax, [rootdir]
				mov [blockin], ax
				call search ;searching first block of /kernel/
				mov ax, kernelfile
				mov [filename], ax
				mov ax, [longfile]
				mov [namelenght], ax
				mov ax, [blockout]
				
				;pusha
				;add ax, 20
				;mov ah, 0x0E
				;mov al, '.'
				;int 0x10
				;popa
				
				mov [blockin], ax
				call search ;searching second block of kernel.bin
				jmp loadit

;a20 start function
a20:			in al, 0x92
				test al, 0x02
				jnz a20end ;a20 is set
				or al, 0x02
				out 0x92, al
				
a20end:			ret

;disc information function
discinfo:		mov ax, 0x0001
				mov [block], ax
				call readit ;reading sector from floppy
				mov ax, [ds:0x022C]
				mov [rootdir], ax
				mov ax, [ds:0x0216]
				mov [tablestart], ax
				mov ax, [ds:0x0220]
				mov [datastart], ax
				ret

;variables for disc
rootdir			dw 0x0000
tablestart		dw 0x0000
datastart		dw 0x0000

;search function
search:			xor cx, cx

searchmain:		inc cx
				mov ax, [blockin]
				mov bx, [datastart]
				add ax, bx
				mov [block], ax
				call readit ;reading sector from floppy
				pusha
				mov cx, 0x0008
				mov ax, 0x0200
				
searchloop:		pusha
				cld
				mov di, ax
				mov si, [filename]
				mov cx, [namelenght]
				rep cmpsb
				je found ;found file on floppy
				popa
				add ax, 64
				loop searchloop
				jmp notfound

found:			popa
				add ax, 0x002C
				mov di, ax
				mov bx, [di] <<--- to smierdzi i nie dziala jak nalezy :(
				mov [blockout], bx
				
				pusha
				mov dh, bh
				mov dl, bl
				
				mov ah, 0x0E
				;mov al, '.'
				
				mov al, bh
				add al, 20
				int 0x10
				mov al, bl
				add al, 20
				int 0x10
				;mov al, dh
				;add al, 20
				;int 0x10
				popa
									;pusha
									;mov bx, 0x2000
									;add ax, bx
									;mov si, 0x0200
									;call message
									;popa
				
				popa
				ret

notfound:		popa
				cmp cx, 0x0800
				jae error
				mov dx, [blockin]
				mov [nextin], dx
				call nextblock
				mov dx, [nextout]
				cmp dx, 0xFFF0
				ja error
				mov bx, [nextin]
				cmp dx, bx
				je error
				mov dx, [nextout]
				mov [blockin], dx
				jmp searchmain

;variables for search
filename		dw 0x0000
namelenght		dw 0x0000
blockin			dw 0x0000
blockout		dw 0x0000

;nextblock function
nextblock:		pusha

				;pusha
				;mov ah, 0x0E
				;mov al, '|'
				;int 0x10
				;popa
				
				xor dx, dx
				mov ax, [nextin]
				mov bx, 256
				div bx
				mov cx, [tablestart]
				add ax, cx
				mov [block], ax
				call readit
				mov cx, 0x0200
				mov ax, 2
				mov bx, dx
				mul bx				
				add ax, cx
				
				
				;mov si, ax
				;call message

				
				mov si, ax
				mov bx, [ds:si]
				mov [nextout], bx
				popa
				ret
				
;variables for nextblock
nextin			dw 0x0000
nextout			dw 0x0000

;readit function
readit:			pusha
				xor dx, dx
				mov ax, [block]
				mov bx, 36
				div bx
				mov [scierzka], al
				mov ax, dx
				xor dx, dx
				mov bx, 18
				div bx
				mov [glowica], al
				inc dl
				mov [sektor], dl
				mov ah, 0x02
				mov al, 0x01
				mov cl, [sektor]
				mov ch, [scierzka]
				mov dl, 0x00
				mov dh, [glowica]
				mov bx, 0x0200
				int 0x13
				jc error
				popa
				ret

;variables for read
block			dw 0x0000
scierzka		db 0x00
sektor			db 0x00
glowica			db 0x00

;loadit jumper
loadit:			mov ax, [blockout]
				mov [nextin], ax
				mov cx, 0x0500 ;max 640KB kernel size
				
loaditloop:		pusha
				mov ax, [nextin]
				mov bx, [datastart]
				add bx, ax
				mov [block], bx
				call readit
				pusha
				;kopiujemy do pamieci tam hen hen przy pomocy a20 powyzej 1MB
				
				
				
				;pusha
				;mov ah, 0x0E
				;mov al, '.'
				;int 0x10
				;popa
				
				
				popa
				call nextblock
				mov ax, [nextout]
				mov [nextin], ax
				cmp ax, 0xFFFE
				je jumpit
				cmp ax, 0xFFF0
				ja error
				popa
				loop loaditloop
				jmp error
	
jumpit:			popa
				
				
				jmp jumpit
				
				call a20
				;skaczemy do jajka z ustawionymi odpowienio rejestrami
	
	
	
				
	
	
	
				
;error
error:			mov si, errormessage
				call message
				
for:			jmp for			

;message function
message:		cld
				mov ah, 0x0E
				
messagechar:	lodsb
				cmp al, 0x00
				jz messageend
				int 0x10
				jmp messagechar
				
messageend:		ret

;messages for bootloader
booting			db 'Booting', 0x00
kerneldir		db 'kernel', 0x00
longdir			dw 0x0007
kernelfile		db 'kernel.bin', 0x00
longfile		dw 0x000B
errormessage	db '.Error', 0x00

;times 510 - ($ - start) db 0
;db 0x55
;db 0xAA
0

nie jestem obeznany w asmie jak ty ale z tego co wiem to ładując wartość z rejestru do pamięci trzeba odwrócić bajty, zdejmując z pamięci też dostajemy odwrócone bajty, czyli jak w pamięci jest 0x1234 i zdejmujemy do AX to w AX jest 0x3412.

Może głoszę herezje, może mówię o czymś o czym wiesz od dawna ale jednocześnie proszę o potwierdzenie mnie w tych działaniach - tego że komunikacja rejestr-pamięć odwraca bajty w słowach.

0

zgadza się prgtw, architektura x86 jest little endian co oznacza, że najniższy bajt liczby jest zapisywany /w pamięci/ jako pierwszy, najwyższy zaś jako ostatni /kolejność odwrócona gdyby ktoś nie załapał ;P/. Swoją drobą który raz ja to tutaj powtarzam? W przeciągu tygodnia już ze 2 razy o tym wspominałem... chyba będzie trzeba napisać FAQ bo zaczyna mnie to już nudzić...

OMG, przykład różnic pomiędzy programistą a coderem:

                                mov ax, 0x0000

3 bajty, nie lepiej tak? /2 bajty/

                                xor ax, ax

OMFG WTF!?

                                xor dx, dx
                                mov ax, [nextin]
                                mov bx, 256
                                div bx
                                mov cx, [tablestart]
                                add ax, cx

do kurki siwej dzielenie przez potęgi 2 wykonuje się przesumięciami bitowymi w prawo... a tu jeszcze dzielenie przez 256/dla kretynów - 256 = 2^8 czyli 1 bajt/! Czy wy mnie, kurna, chcecie do grobu wpędzić!? i ten cx... po jakiego grzyba ładować dane do rejestru aby tylko raz je użyć?

                                movzx ax, byte [nextin+1]
                                add ax, [tablestart]

ew. jeśli nie chcesz odrobinę nowszych rozkazów to:

                                xor ax, ax
                                mov al, byte [nextin+1] 
                                add ax, [tablestart]

[edit] dodałem +1, przez ten temat sam już zapomniałem o little endian... dziwne, że nikt mnie jeszcze nie opitolił /chyba, że nikt nie czyta\nie rozumie tego co piszę/ ;P [/edit]

I w drugą stronę:

                                mov cx, 0x0200
                                mov ax, 2
                                mov bx, dx
                                mul bx                               
                                add ax, cx

Mnożenie akumulatora zawierającego 2 (!) przez liczbę. OMFG jeżeli wyjdzie TAC 0x0A to ten bootloader wyląduje w najgłupszych snippetach asm jak nic, już ja się o to postaram! Bx nie jest już potem odczytywany więc na logikę:

                                shl bx, 1
                                add bx, 0x0200 

Next cud:

                                mov ah, 0x02
                                mov al, 0x01

i podobny:

                                mov dh, bh
                                mov dl, bl

może jeszcze tak po jednym bicie inicjować? Ciekaw jestem jak to byś z eax zrobił ;P Kolejny przykład poprawnego myślenia:

                                mov ax, 0x0201
                                mov dx, bx

ciekawi mnie również inicjowanie rejestrów segmentowych fs i gs - przecież ich nie używasz :/ Momentami ten kod wygląda jak pociągnięty jakimś obfuscatorem, więcej 'cudownych' fragmentów nie mam siły przytaczać /w sumie pozostałe są podobne do już przedstawionych/.
Już pomijam stosowanie pusha(d) i popa(d) bo to bootloader i niby liczy się rozmiar /patrząc na ten kod mam co do tego wątpliwości/... Gdzie dyrektywa 'org' czy coś w tym stylu? bez tej dyrektywy asmeblery przyjmują, że początek kodu wynikowego znajdzie się pod adresem 0 a bootloader raczej ląduje gdzieś indziej. Niby można pisać bez orga ale co do powyższego kodu mam wątpliwości... /może o tej godzinie nie widzę ustawiania cs/

Dzięki za uwagę i polecam się na przyszłość :>

p.s. mam dziwne wrażenie, że to prowokacja

0

Kwiatkow jest duzo :P ale to dla tego ze do konca go nie napisalem i on jest raczej typu "jesli zadziala to jest ok" nie zajmowalem sie jeszcze optymalizacja tego kodu.

po prostu duzo razy zmienialem w kodzie i latwiej mi bylo zostawic takie cos typu dzielenie przez 256 bo nie wiedzialem do konca o ile bede dzielic itd, a tak w ogóle to wykozystuje reszte z tego dzielenia jak tez sam wynik, a tak mi wygodniej.

A co do org to nie musi byc bo wystarczylo ze ustawilem odpowienio rejestry i kompilator sam juz reszte zalatwia, bo po prostu wszystko dziala jak trzeba i nigdzie do adresu 0000:xxxx sie nie odwoluje xD

Tak w ogóle to dzieki za wytkniecie bledow z tymi rejstrami i przeanalizowanie kodu, ale jak juz mowilem to jest faza wstepna i nie zajmowalem sie optymalizacja a raczej sie modlilem zeby to w ogóle cos z dyskietki odczytalo xD

0

A jak jest dokladniej z tym bo mam wrazenie ze jak czytam z pamieci nie zawartej w kodzie to tam tylko trzeba przestawiac ?

mov ax, [di] <------ przestawiaja sie

mov ax, [etykieta] <------ jest ok

mov [etykieta], ax <--------jest ok

czy tylko mi tak sie zdaje?

0

Odwracanie kolejności zachodzi zawsze - niezależnie czy to Twoja pamięć, czy odczytujesz\zapisujesz z MMXa, SSE czy też rejestrów ogólnego przeznaczenia, jak pisałem - architektura little endian. Do tego trzeba się przyzwyczaić.

0

Czyli po prostu wychodzi na to ze po prostu jak zapisze do zmiennej a pozniej odczytam to 2 razy sie przestawia i jest tak jak powinno :d mam farta bo wszedzie mam podwojne przeniesienia :d

0

odwracanie kolejności bajtów następuje tylko przy przenoszeniu czegoś z pamięci do rejestru lub odwrotnie (np: pop eax lub movq mm0, [etykieta]). przy przenoszeniu czegoś z rejestru do rejestru (np: mov edx, eax lub movd eax, mm0) lub z pamięci do pamięci (np: movsd lub push [etykieta]) zamiana kolejności bajtów nie następuje.

myślę, że kwiatki typu:

                                mov ah, 0x02
                                mov al, 0x01

wynikały własnie z niewiedzy na temat 'endianess' (atsd: jak to jest po polsku?).

atsd:
po cholerę intel wprowadzał little- endian? bez tego dużo rzeczy dałoby się zrobić dużo szybciej, prościej i czytelniej. (wrrrr)

0

A ja sie zawsze dziwilem dlaczego mi nieraz program jajca wyrabia xD

Jak na moje to koles co to projektowal musial sie chyba niezle zalac :P

A jak ma sie sprawa z eax itp? jak dziada odwrocic na lewa strone ? bo ax latwo: xchg al, ah

0

Nie rozumiesz do końca zagadnienia. Z punktu widzenia programisty nie istnieje żaden problem w tej kwestii. Z twojego kodu można od razu poznać iż nie prześledziłeś zbyt dużej ilości programów napisanych przez innych programistów, ale to akurat sam nie wiem czy dobrze czy źle. W każdym razie postaram sie przedstawić jak to wygląda.

Jest sobie fragment pamięci o adresie powiedzmy 0010h i są w nim takie dane:
adres - dane
:0010 - 33 5C 2A FF EB FE 01 00 21 5A 91 00 00 CD 21 00

Tak więc wartość 2A ma adres 0012, wartość FE jest w komórce pamięci o adresie 0015. Jak wiadomo dane zapisywane do pamięci umieszczane są tak iż najpierw są zapisywane najmłodsze bajty. I tak po prostu jest.(To że jesteśmy przyzwyczajeni na co dzień robić to odwrotnie nie znaczy że ten sposób jest zły lub gorszy)

Prześledź teraz ten kod:
mov di, 0x12
mov ax, [di]

w rejestrze ax otrzymasz wartość ax=FF2A zamienione bajty kolejnością, ale to tylko kwestia zapisu bo tutaj po prawej masz młodsze bajty a przy zapisie w pamięci młodsze bajty idą do mniejszych adresów. W przypadku zapisu z rejestru do pamięci jest analogiczna sytuacja. Ale z punktu programisty w tym przypadku jest ci wszystko jedno bo to co zapiszesz do pamięci to dokładnie to samo odczytasz.

Dany ciąg pamięci można zapisać za pomocą kodu assemblera inaczej:
:0010 - 33 5C 2A FF EB FE 01 00 21 5A 91 00 00 CD 21 00

db 0x33,0x5C,0x2A,0xFF,0xEB,0xFE,0x01,0x00
db 0x21,0x5A,0x91,0x00,0x00,0xCD,0x21,0x00

db 0x33,0x5C
dw 0xFF2A
dw 0xEBFE
db 0x01,0x00
db 0x21,0x5A,0x91,0x00,0x00,0xCD,0x21,0x00

Oba kody 1. i 2. po skompilowaniu dadzą ten sam ciąg bajtów i jeżeli umieścisz go w pamięci pod adresem 0010h to wczytując mov ax, [12h] zawsze wczytasz wartość FF2Ah.

następny kod:
mov ah, [12h]
mov al, [13h]
mov bx, [12h]

No i jak już zrozumiałeś to powinieneś wiedzieć, że w rejestrze ax będziesz miał tą samą wartość co w bx.

Tak więc odpowiedz na pytanie:

A jak ma sie sprawa z eax itp? jak dziada odwrocic na lewa strone ? bo ax latwo: xchg al, ah

jest już ci nie potrzebna. No chyba, że do jakiś innych celów.

0

Bo jak chce odczytac wartosc z pamieci do eax i chce wykonywac na niej operacje matematyczne to by sie odwrocic ten rejestr no nie? Chyba ze sie myle.

Dzieki wszystkim za wytlumaczenie :)

A co do ilosci przeczytanch programow to ja raczej biore ksiazke z instrukcjami, manual lub opis do rzeczy co chce uzyskac np odczyt z dyskietki jak ona jest zrobiona (dziwnie tez sie odczytuje :P ale sie nauczylem i dokopalem jak :) ) i z tego wszystkiego probuje wyskrobac cos dzialajacego :d

0

Bo jak chce odczytac wartosc z pamieci do eax i chce wykonywac na niej operacje matematyczne to by sie odwrocic ten rejestr no nie? Chyba ze sie myle.

Jak już zapewne wiesz

dane db 0x10, 0x20, 0x30, 0x40
;...
mov eax, [dane]

da w efekcie eax = 0x40302010, do odwracania kolejności bajtów rejestru 32b jest specjalna instrukcja - bswap

bswap eax

teraz w eax mamy już 0x10203040.
Widzę, że wszystkie niejasności zostały wytłumaczone w powyższych postach, widzę róznież zasłużonego fasm-owca :-). Endiany to faktycznie zmora początkujących. Może by tak napisać o tym FAQ? :>

p. s. http://www.intel.com/products/processor/manuals/ - poczytaj te manuale a może będziesz kiedyś wymiatał lepiej ode mnie... i reszty coder'ów w tym kraju... no, dobra - na tym świecie ;P

0

Heheh, dzieki za pomoc :)

A te manuale intela mam od paru miesiecy na dysku :d ale duzo tego jak nie wiem co xD troche to poczytalem, a raczej czytalem o trybie chronionym itd ale dzieki za linka :)

Nie wiem dla czego ale nie lubie jezykow wysokiego poziomu typu Java, C# itd, wole pisac w C i asm chociaŻ co do tego drugiego nieraz mam dziwne niedoksztalcenia jak to w tym temacie :) ale po to pisze by sie nauczyc :) jak szkolikem sobie C to napisalem tez dosyc duzy projekt bo hexedytor pod konsole dla *nixa :) wyszlo cos takiego jak nano ale obok tekstu masz kolumne z wartosciami szestnastkowymi xD

0

Ja tylko dopowiem, ze litle endian ma ta 'zalete', ze jesli zapakujesz pod jakis adres dworda o wartosci np 5 i potem odczytaz to jako bajt to to dalej bedzie mialo wartosc 5.

Assesmaniac napisał(a)

A te manuale intela mam od paru miesiecy na dysku :d ale duzo tego jak nie wiem co xD troche to poczytalem, a raczej czytalem o trybie chronionym itd ale dzieki za linka :)

Zamow se papierowe, lepiej sie czyta ;]

0

Papierowa wersje za darmo przysla? czy jakies oplaty? bo bym pisal sie na takie cos :)

0

Za darmo przysyłają.

Bo jak chce odczytac wartosc z pamieci do eax i chce wykonywac na niej operacje matematyczne to by sie odwrocic ten rejestr no nie? Chyba ze sie myle.

Nie musisz. Jeżeli w dokumentacji jest napisane, że pod tym adresem jest przykładowo rozmiar pliku i jest to dana typu word to po:

mov ax, [costam]

w ax bedziesz juz mial ten rozmiar w "normalnej" postaci. Czyli będziesz mógł wykonywac na niej operacje matematyczne.

0
Assesmaniac napisał(a)

Papierowa wersje za darmo przysla? czy jakies oplaty? bo bym pisal sie na takie cos :)

Za darmo. Kurier przychodzi pod drzwi :)) Naprawdę warto, bo czyta się o niebo lepiej.

0

Jak zamawialiscie? Normalnie po prostu wyslaliscie im na e-mail nr katalogowy z danymi tak jak dali we wzorze? Tyle wystarczy? I ile tak to idzie mniej wiecej?

Jutro sobie zamowie wszystko do prockow 32b i 64b xD, AMD tez takie cos ma? Musze zobaczyc :)

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