Witam
Zaczynam uczyć się asemblera ...
Czy ktoś może mi napisać jaki jest najlepszy i jak się nim posługiwać. Zaczełem pisać własne programiki, ale nie umiem ich ort!. Na studiach mam laborki z asemblera i tam na razie działamy na AFD ucząć się działania systemu komputerowego. Ja chciałem ort! o krok dalej i zaczełem pisać coś swojego "użytkowego". Oczywiście chodzi mi o jakis ort! pod system windows xp...
Byłbym wdzięczny za szybką i konkretną odpowiedź.
Pozdrawiam
po pierwsze nie asemblerowanie a asemblowanie, a po drugie to fasm - świetny polski asembler:
http://flatassembler.net/ i http://decard.net/. Manual do fasma i przykłady wystarczą do nauczenia się składni a o samym asemblerze architektury x86\IA-32 to poczytaj w manualach intela:
http://www.intel.com/products/processor/manuals/index.htm
i ew. możesz zaglądnąć tu: http://www.rag.kgb.pl
jeśli chodzi o FASMa to się zgadzam - moim zdaniem najlepszy... Trochę podstawowych informacji znajdziesz na http://rudy.mif.pg.gda.pl/~bogdro/ . Jeśli chcesz programować pod Windows potrzebna ci będzie dokumentacja WinAPI
Nie no raczej chodziło mi o cos takiego co chodzi pod windowsem, ale ogólnie to jest dosowski - takie coś jak masm(ale niewiem jak sie tym posługiwać). Uczę się z książki Asembler dla procesorów intel - vademecum profecjonalisty i z tego co ja wiem to tam jest pod dosa.
Nie znam się ogólnie na asemblerze bo dopiero ort! się tego uczył - zaczynam poznawać z czego składa się procesor i podstawowe instrukcje w AFD. Jeśli ktoś by mógł by napisać jaki czy ten fasm też jest dobry do asemblera pod dosa to byłbym wdzięczny.
EDIT
Przy kompilowaniu takiego programu w fasm:
.model small
.stack 100h
.data
message db "Witaj swiecie!",0dh,0ah,'$'
.code
main proc
mov ax,@data
mov ds,ax
mov ah,9
mov dx,offset message
int 21h
mov ax,4C00h
int 21h
main endp
end main
Kompilator wywala mi błąd, że .modell small jest złe, a jak to usune to, że .stack 100h jest złe więc czego mam używać żeby to działało ? :-/
Sory, że jestem taki nerwowy, ale facet z laborek robi nam taką jazde, że chce się jak najszybciej zacząć ostro uczyć, ale bez ort! to ja nic nie zdziałam...
SI-Coder napisał(a)
Nie no raczej chodziło mi o cos takiego co chodzi pod windowsem
a fasm nie ma portu pod win? Chciałeś może asembler ze zintegrowanym edytorem? http://flatassembler.net/fasmw167.zip Gdybyś się nie połapał - 'fasmw.exe'.
SI-Coder napisał(a)
ale ogólnie to jest dosowski - takie coś jak masm
masm nie jest 'dosowski' /aktualnie nie jest ;P/ - to aplikacja konsolowa 32bit, ale pozwala na tworzenie plików MZ.
SI-Coder napisał(a)
Jeśli ktoś by mógł by napisać jaki czy ten fasm też jest dobry do asemblera pod dosa to byłbym wdzięczny.
jasne, że jest dobry... dowolnym portem fasm możesz wygenerować pliki binarne, MZ /dos/, PE /win/ PE64 /win64/, ELF /unix\lin/, ELF64 /chyba oczywiste/, i coś tam jeszcze... Btw. Fasm jako jedyny asembler nie potrzebuje linkera - sam 'wypluwa' binarki... oczywiście jest możliwość kompilacji do formatów COFF\M$ COFF. Byłbym wdzięczny gdybyś poczytał dokumentację dołączoną do fasma... Jak chcesz najpierw pisać pod dosa do ściągnij sobie paczkę fasma pod dosa - masz tak przykłady aplikacji typowo dosowych: http://flatassembler.net/fasm167.zip Oczywiście możesz programy dosowe pisać pod win w fasmw i kompilować oraz odpalać poprzez F9 :>
[EDIT:] // do powyższego edita
tamten program ma składnię masma, nie oczekuj, że jakikolwiek inny asembler /nie asemblator!/ to łyknie... pod fasmem będzie to wyglądać tak:
Format MZ ; deklaracja formatu pliku wynikowego - MZ /dos/
stack 100h ; rozmiar stosu
entry kod:main ; entry point /'poczatek' programu/
segment dane ; segment o nazwie 'dane'... wiadomo
message db 'Witaj swiecie', 0x0d, 0x0a, '$'
segment kod ; j\w tylko 'kod' ;)
main: ; etykieta... chyba wiadomo co to
mov ax, dane
mov ds, ax
mov ah, 9
mov dx, message ; pod fasmem nie potrzeba slowa 'offset'
int 21h
mov ax, 4c00h
int 21h
ew. można wywalić początkową dyrektywę 'entry' - można ją dać zamiast etykiety 'main'... czyli tak:
entry kod:$ ; czyli segment kodu : aktualna pozycja
mov ax, dane
...
p.s. nawet najnowszy masm ma troche bugów - np. dołączanie bibliotek z poziomu kodu działa dosyć ciekawie /czasem gdzieś te informacje giną/. Do tego dochodzi jeszcze błąd w obliczaniu wyrażeń, o którym pisał swego czasu bart /TAC#8 - http://woodmann.com/bart/download.php?id=tac08h.zip/ - dodasz gdzieś nopa czy cokolwiek a w całkiem innym miejscu kodu masm może źle coś obliczyć :/ w sumie to z czymś takim spotkałem się może raz, ale pod masmem pisałem z konieczności tylko kilka razy.
p.s. 2: w sumie większość czasu piszę pod win ale nie korzystam ze zintegrowanego edytora - vim rządzi :>
p.s. 3: coś czuję, że mnie M. opitoli za rzucenie n oczywistych linków... i za pisanie chyba 10 raz tego samego /asm rulez, fasm rulez i te sprawy ;P/
Aha dzięki teraz już kumam ...
Mam do Ciebie ostatnią prośbe bo widze, że znasz się na sprawie. Miałem do zrobienia kilka programów i został mi jeden do zrobienia, którego męcze od 3h i nie potrafie zrobić.
Czy mógłbyś mi podsunąć przynajmniej pomysł jak zrobić taki program (chodzi mi tylko o podpowiedź bez pisania całego kodu bo sam chce do tego dojść):
napisz program, który wyszukuje najwięjszą wartość 8 bitową bez znaku z z buforu(byle jakiego - załóżmy, że DS) adresowane za pomocą rejestrów:
DI- segment
SI- offset
...
Podana jest wartość CX - załóżmy, że jest to 0011h.
AL - wyjście.
Mam to wykonać w afd także składnia jest nieważna - moge używać pętli takich zwykłych, które zmniejszają cx i poleceń mov, add, sub, dec, inc, jni, xchg, shl, shr.
Byłbym wdzięczny za pomoc w rozwiązaniu tego problemu.
Pozdrawiam
raczej ciężko to opisać - najłatwiej zrobić to po ludzku ;) czyli bierzemy pierwszy z brzegu a potem następne i sprawdzamy czy kolejny element jest większy, jeżeli tak to zamieniamy... liczba 8bit bez znaku to /w uproszczeniu/ najbardziej naturalny format danych - zwykły bajt. Wiem, że miałem kodu nie pisać, ale tak dawno nic pod dosa nie pisałem :> przykładowy program - właściwy algorytm potraktowałem wcięciem:
Format MZ
segment kod
entry kod:$
mov cx, ilosc ; inicjowanie wedle Twoich zalozen
mov di, extra
mov si, cos
;------------------------------------------------------------------------------
; cx - liczba elementow, di - segment, si - offset
;------------------------------------------------------------------------------
push es ; zachowujemy es - w tym programie nie
xor ax, ax ; jest to konieczne, ale... ; ax = 0
mov es, di ; ustawiamy segment
_cmp_loop:
mov dl, [es:si] ; w dl aktualna wartosc, w al aktualnie
cmp al, dl ; najwieksza
jge @f
mov al, dl ; najwieksza = aktualna
@@:
inc si ; ++pozycja
loop _cmp_loop ; --licznik; jesli 0 - koniec
pop es ; odtwarzamy es
;------------------------------------------------------------------------------
; cx = 0, si - offset konca koniec, ax /a raczej al/ - najwieksza liczba
;------------------------------------------------------------------------------
mov ax, 4c00h
int 21h
segment extra
cos db 22, 1, 53, 63, 23, 96, 6, 2, 123, 43, 4, 54, 35, 3, 87
ilosc = $ - cos
oczywiście można to rozwiązać nieco inaczej - np. zamiast:
mov dl, [es:si]
można zastosować adresowanie względem rejestru bazowego z indeksowaniem /chyba tak to się nazywało - nie pamiętam ;P/ czyli:
mov dl, [es:bx+si-1]
ale w takim wypadku konieczne będzie zastosowanie zamiast loopa takiej konstrukcji:
dec si
jnz _cmp_loop
ale przy takim rozwiązaniu zachodzi konieczność zmiany rejestrów - offset ląduje w bx a ilość elementów /licznik/ w si... co kto lubi... To co powyżej - działa, ale może być napisane minimalnie lepiej\zgrabniej ;)
p.s. stosowanie wcięć w asm to moim zdaniem zboczenie ;P
p.s. 2: 3h? ciężko mi w to uwierzyć...
Spróbowałem jednak napisać coś sam bo inaczej się nie naucze ...
Jeśli mógłbyś zobaczyć czy jest to dobry program to byłbym wdzięczny:
xor ax,ax
podmiana:
mov al,DI[SI]
inc SI
petla:
cmp al,DI[SI]
JC podmiana
inc SI
INZ petla
zrobiłeś parę błędów, instrukcji 'INZ' w x86 nie ma - zapewnie miałeś na myśli 'JNZ'... ale przejdźmy do rzeczy - pozwoliłem sobie skomentować Twój kod:
xor ax, ax ; zerowanie ax - dobrze ;)
podmiana:
mov al, DI[SI] ; po 1 : pod fasmem pisze sie [seg:reg]
; po 2 : DI nie jest rejestrem segmentowym
inc SI ; wskaznik = wskaznik + 1
petla:
cmp al, DI[SI]
JC podmiana ; to samo co 'JB' jesli 2 arg wiekszy to skok
inc SI ; wskaznik = wskaznik + 1
INZ petla ; na to nie mam pomyslu 'co to'... chyba mialo
; jnz ale to nic nie da.
to INZ to chyba miał być loop, ale nie sprawdzasz stanu rejestru CX przy podmianie - może to poskutkować 'przeoczeniem' końca bufora. Po
inc SI
powinno być dec cx
jz koniec
a etykietę 'koniec' wiadomo gdzie dać... po moich drobnych poprawkach wygląda to tak:
```asm
push ds ; zachowujemy ds - bedzie wygodniej odwolywac
xor ax, ax ; sie do bufora /segment domyslny/ ; ax = 0
mov ds, di ; ustawiamy segment ds - segment danych
podmiana:
mov al, [si]
inc si
dec cx ; prawie to samo co loop - tylko w 2 strone ;)
jz _koniec
petla:
cmp al, [si]
jc podmiana ; to samo co 'JB' jesli 2 arg wiekszy to skok
inc si ; wskaznik = wskaznik + 1
loop petla ; i powtarzamy... az cx = 0
_koniec:
pop ds ; odtwarzamy ds
Pobaw się nieco szykiem instrukcji - parowanie przy podmianie /mov nie modyfikuje flag/ :> Jeżeli wolno wam używać instrukcji łańcuchowych to część oznaczoną jako 'podmiana' można zapisać tak:
dec cx ; klania sie parowanie instrukcji /jz/
lods byte [si] ; mov al. [si] \ inc si
jz _koniec ; lods nie modyfikuje flag
ew. 'lods byte [si]' można zapisać jako 'lodsb' - krótka forma :>
p.s. asm nie jest prostym językiem - wymaga odpowiedniego sposobu myślenia... ale głowa do góry, wyrobisz się ;)... ja siedzę w asemblerze od coś koło 5 lat i nie mogę powiedzieć abym opanował asma IA-32 idealnie - różne zawiłości instrukcji swoje robią /np. trzeba pamiętać, że inc\dec w przeciwieństwie do add\sub nie ustawiają flagi CF - przy testach na przekroczenia zera w którąś stronę trzeba opierać się na SF/.
Chciałem zrobić sobie sam sortowanie bąbelkowe buforu , ale niewiem czy dorze wykombinowałem. Jesli mógłbyś mi pomóc poprawić błędy w moim kodzie to byłbym wdzięczny.
xor ah,ah
push si
push cx
jzn petla
podmiana:
mov bl,[si+1]
mov bh,[si]
mov [si],bl
mov [si+1],bh
dec cx
inc si
inc ah
Jz _koniec
petla:
mov al,[si]
cmp al,[si+1]
jc zamiana
inc si
loop petla
_koniec:
cmp 0001h,al
pop cx
dec cx
pop SI
jc petla
Adres zawarty w DI, bufor - DS.
Pozdrawiam i prosze o wyrozumiałość :)
Jesli nie możesz połapac się w moim kodzie to jeśli możesz to napisz swoją wersję bubble sort.
Cóż, dzisiaj jestem trochę rozleniwiony więc napisałem własną implementację /a w sumie cały program - chciałem to pod SoftICE'm prześledzić ponieważ uważam, że nie jestem nieomylny ;P/:
Format MZ
segment dane
bufor db 7, 64, 46, 71, 142, 42, 237, 1, 8, 48, 91, 56, 167, 29
ilosc = $ - bufor
segment kod
entry kod:$
push dane
pop ds
mov cx, ilosc
mov bx, bufor
;------------------------------------------------------------------------------
_bs_loop:
mov si, cx
xor di, di ; 'znacznik' zmian
@@:
dec si
jz @f ; skok do nastepnego @@
mov ax, [bx+si-1] ; wygodne rozwiazanie
cmp al, ah ; ax to w koncu ah << 8 + al
jc @b ; skok do poprzedniego @@
xchg al, ah ; zamiana elementow
inc di ; ilosc zmian++
mov [bx+si-1], ax
jmp @b ; skok do poprzedniego @@
@@:
test di, di ; ZF = 1 jezeli di == 0
jz _end ; nie trzeba kolejnych iteracji
loop _bs_loop
;------------------------------------------------------------------------------
_end:
mov ax, 0x4c00
int 0x21
Gdzie jest algorytm - chyba widać ;) W sumie to po dodaniu 'znacznika zamiany' nie jest chyba zwykłe sortowanie bąbelkowe tylko przez wstrząśnięcie... ot, podrasowany 'bubel' ;P Jak widać na załączonym obrazku bufor przeniosłem do ds:bx aby zastosować adresowanie z indeksowaniem... tak dla zabawy :> Rejestr indeksowy robi dodatkowo za licznik. A poważnie to dobrym pomysłem na starszych procesorach jest zastosowanie 2 8bitowych części rejestru 16bit - zamiast 2 odwołań do pamięci przy zapisie\odczycie mamy jedno /na nowszych wpływa to negatywnie na wydajność - dostęp do wyższej części wymaga dodatkowych operacji/. Mam nadzieję, że nigdzie się nie machnąłem - pod debuggerem niby wszystko wygląda dobrze.
//dodane:
algorytm można nieco zmienić stosując parowanie instrukcji /np. przy pracy potokowej można odrobinę zniwelować negatywny wpływ skoków warunkowych/ i instrukcję 'loopnz':
;...
xor di, di ; 'znacznik' zmian
@@:
dec si
mov ax, [bx+si-1] ; w RM nie grozi GPF ;P
jz @f
cmp al, ah
xchg al, ah ; nie zmienia flag
jc @b
; reszta bez zmian...
test di, di ; ZF = 1 jezeli di == 0
loopnz _bs_loop
hmm... chyba odrobinkę przesadziłem [rotfl]
p.s. jak tak na to patrzę to myślę, że mógłbym zgarnąć parę złotych pisząc w asm dla inszych studentów [diabel]
@developerzy - przydałoby się poprawić kolorowanie składni dla asm - błędy: kolorowanie 'ch' w 'xchg' czy brak kolorowania liczb zapisanych jako 0x lub si przy indeksowaniu... A i jeszcze jedno - Coyote koloruje też liczby wchodzące w skład etykiet :/
Zarejestruj się i dołącz do największej społeczności programistów w Polsce.
Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.