[ASM]Posortowanie tablicy (bufora)

0

Witam

Muszę wprowadzić do bufora łańcuch znaków a następnie go posortować.
Póki co wykonałem wprowadzanie znaków oto kod:

Kod:
.model small
.stack 100H
.data
napis DB "Twoja tablica moze miec 100 znakow" ,13,10,'$'
bufor DB 100,?,100 dup('$')
nL DB 13,10,'$'
.code
main:

    MOV AX, 0003H
    INT 10H

    MOV AX, @data
    MOV DS, AX

    MOV DX, OFFSET napis
    MOV AH, 09H
    INT 21H

    MOV DX, OFFSET bufor
    MOV AH, 0AH
    INT 21H

    MOV DX, OFFSET nL
    MOV AH, 09H
    INT 21H

    MOV AH, 01H
    INT 21H
    CMP AL, 'k'
    JNE main

    MOV AH, 08H
    INT 21H
    CMP AL, 27

    MOV DL, 'A'
    MOV AH, 02H
    INT 21H

exit0:
MOV AH, 4CH
MOV AL, 00H
INT 21H
end main
pytanie co teraz zrobić aby ten łancuch po wpisaniu sie sortował tzn. posortować bufor...

0

Zaimplementować dowolny algorytm sortowania.

0

Właśnie tu jest problem jak ma wyglądać ten algorytm sortowania, nie mam zielonego pojęcia jak go napisać...

0
pinio27 napisał(a)

Właśnie tu jest problem jak ma wyglądać ten algorytm sortowania, nie mam zielonego pojęcia jak go napisać...

Wez sobie nawet jakis prosty algo sortujacy, na przyklad sortowanie babelkowe, ktore jest banalne.
Masz mnostwo przykladow tego w C na necie.

Jeszcze zastanawia mnie po co Ci na poczatku int 0x10 dla al 0x03 ? Wydaje mi sie, ze od poczatku jestes w trybie tekstowym i nie ma potrzeby uzywac tego przerwania, ale moge sie tutaj mylic.

0

To fakt w necie jest sporo przykładów w C, ale nie wiem jak je przerobić do assemblera, dobra powiem wprost jakby ktoś mi napisał ten kawałek kodu to bym był wdzięczny ;) bo ja już nie mam do tego siły...

0

Przejrzałem backupy, przykład pod Fasma, pisany ze 4-5 lat temu na potrzeby kogoś z 4p albo inszego znajomego forum:

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

Na oko sortowanie bąbelkowe, całkiem nieźle zaimplementowane - przeanalizuj i wykorzystaj. Nie chce mi się wrzucać w google, ale chyba gdybyś sensownie poszukał to byś ten kod znalazł.

0

Nie napisze za Ciebie, ale mam chwile, wiec spojrz:

for (i=0; i<n-1; ++i) 
{
       change = 0;
       for (j=0; j<n-1-i; j++)
       { 
          if (a[j+1] < a[j])   //porównanie sąsiądów
          {  
              tmp = a[j];      
              a[j] = a[j+1];
              a[j+1] = tmp;    //wypchanie bąbelka     
              change=1;
          }
       }
       if(!change) break;      // nie dokonano zmian - koniec!
  }
  1. Musisz jakos zdobyc dlugosc tej tablicy ;p daj ja do zmiennej "lenght_t"
  2. Masz zmienna change, wiec tez tworzysz sobie zmienna, aby rejestrow nie zasmiecac na razie "change_b"
  3. Jeszcze zmienna tmp, wiec niech to bedzie "tmp_s"

dalej w skladni nasm, bo tasma ni w zab nie znam ;p

  1. widac, ze dlugosc ma byc zmniejszona o 1, wiec dajesz przed petla: mov eax, dword [lenght_t] oraz
    dec eax orax mov dword [lenght_t], eax

  2. zmienna 'i' z C dajmy na to niech bedzie rejestrem ecx, czyli dajesz xor ecx, ecx przed pierwsza petla

  3. zmienna 'j' z C niech bedzie rejestrem edx, czyli dajesz od razu w pierwszej petli xor edx, edx

  4. Szkielet tych petli, wiec wyglada tak:

for_1:
      change_b = false
 
      xor edx, edx
   for_2:
      ; cialo petli drugiej

      inc edx
      cmp edx, dword [lenght_t]
      jne for_2

      or dword [change_b], dword [change_b]
      jz next

      inc ecx
      cmp ecx, dword [lenght_t]
      jne for_1

next:
     ; dalsze cos tam

Zostalo Ci w ciele petli drugiej daj porownanie, czyli cmp oraz skok ewentualny do zamiany ;)

0

Tam po or powinno byc jnz, ale i tak juz Świętowit dal gotowca, wiec nie wazne.

0
Świętowit napisał(a)

Na oko sortowanie bąbelkowe, całkiem nieźle zaimplementowane - przeanalizuj i wykorzystaj. Nie chce mi się wrzucać w google, ale chyba gdybyś sensownie poszukał to byś ten kod znalazł.

Znalazłem :P

Wyskakują mi niestety dwa błedy po kompilacji :
Operand types do not matches
Unexpected end of file encountered

Użyłem tego kodu od Świętowita
??

0

Jak wyskakuje to popraw, przecież to co najwyżej niewielkie różnice w składni. Zgaduję, że chodzi o początek:

        push    @dane
        pop     ds
        
        mov     cx, offset ilosc
        mov     bx, offset bufor
0

Spokojnie, w sumie było 5 błędów tylko te dwa mi zostały do znalezienia, a teraz już tylko jeden:

Unexcepted end of file encountered

ale jeszcze z nim powalczę ;)

No nadal mi wywala ten jeden błąd, kod wygląda tak, nie wiem o co chodzi:

.model small
.stack 100H
.data
bufor   db 7, 64, 46, 71, 142, 42, 237, 1, 8, 48, 91, 56, 167, 29
ilosc   = $ - bufor
.code


main:$

        push    @dane
        pop     ds
        
        mov     cx, OFFSET ilosc
        mov     bx, OFFSET 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 @@
  @1:
        test    di, di                  ; ZF = 1 jezeli di == 0
        jz      _end                    ; nie trzeba kolejnych iteracji
        loop    _bs_loop        
;------------------------------------------------------------------------------
_end:
        mov     ax, 4c00H
        int     21H

0

Wywal '$' po main ('$' oznacza bieżący adres, fasmowa dyrektywa entry zaś miejsce, w którym ma się rozpocząć wykonywanie programu). Tutaj już masz main i raczej starczy, na koniec dodaj end main, tak jak w swoim kodzie z pierwszego postu masz.

0

Aha, po cholerę drugie '@@' zmieniłeś na '@1'? '@@' to specjalna dyrektywa tworząca nienazwaną etykietę, może ich być wiele, odwołanie do następnej/poprzedniej względem miejsca użycia to @f/@b (forward/backward) w kodzie.

0

Resztę poprawiłem jak mówiłeś, za to jak daje @@ to wywala takie błędy:

http://yfrog.com/18screenbiej

0

No cóż, praktycznie wszystkie assemblery to wspierają, widać tasm jest tak archaiczny, że starej jak świat koncepcji nie obsługuje...

.model small
.stack 100h

.data
bufor   db 7, 64, 46, 71, 142, 42, 237, 1, 8, 48, 91, 56, 167, 29
ilosc   = $ - bufor

.code
main:
        push    @data
        pop     ds
        
        mov     cx, offset ilosc
        mov     bx, offset bufor
;------------------------------------------------------------------------------
_bs_loop: 
        mov     si, cx                  
        xor     di, di
_bs_loop_swap: 
        dec     si
        jz      _bs_loop_next
        mov     ax, [bx+si-1]
        cmp     al, ah
        jc      _bs_loop_swap
        xchg    al, ah
        inc     di
        mov     [bx+si-1], ax
        jmp     _bs_loop_swap
_bs_loop_next:
        test    di, di
        jz      _end 
        loop    _bs_loop 
;------------------------------------------------------------------------------       
_end:
        mov     ax, 4c00h
        int     21h
end main

Chyba coś takiego.

0

No skompilowało się, ale nic się nie dzieje po uruchomieniu ;/

0

Jak nic się nie dzieje? Tablica 'się' sortuje, program się potem zamyka.

0

No tak, ale nie powinno się coś wyświetlać, albo inaczej jak zrobić żeby się wyświetlało, bo moje zamierzenie kodu było takie jak w pierwszym poście czyli uruchomienie programu->wpisanie z klawiatury 100 znaków->a dalej chciałem żeby się wszystko ładnie posortowało itd

0

Umiesz napisać wczytywanie i wypisywanie? Wczytujesz, bufor wrzucasz w bx, ilość znaków do posortowania w cx, leci _bs_loop, dojdzie do _end to wypisujesz. I tak dostałeś gotowca algorytmu sortowania.

0

Wiem, wiem wielkie dzięki za wszystko ;)

Dobra zrobiłem wczytywanie (przynajmniej tak mi się wydaje), ale wyświetlenia posortowanego łańcucha nie mogę ogarnąć,
litości siedzę nad tym już pół dnia :-/

.model small
.stack 100h

.data

bufor   db 20 dup('$')

ilosc   = $ - bufor

.code
main:
	mov ax,SEG bufor ; 
  	mov ds,ax  

	mov ah,0aH
	int 21H
	
	mov ah,08H
	int 21H
	
        
	push    @data
        pop     ds
        
        mov     cx, OFFSET ilosc
        mov     bx, OFFSET bufor
;------------------------------------------------------------------------------
_bs_loop: 
        mov     si, cx                  
        xor     di, di
_bs_loop_swap: 
        dec     si
        jz      _bs_loop_next
        mov     ax, [bx+si-1]
        cmp     al, ah
        jc      _bs_loop_swap
        xchg    al, ah
        inc     di
        mov     [bx+si-1], ax
        jmp     _bs_loop_swap
_bs_loop_next:
        test    di, di
        jz      _end 
        loop    _bs_loop 
;------------------------------------------------------------------------------       


_end:
        mov     ax, 4c00h
        int     21h
end main
0

Masz tam liczby, wiec zeby wyswietlic to za pomoca na przyklad drugiej(AH = 2) funkcji przerwania 21h musisz kazda liczbe zwiekszyc o 48, aby powstal z niej znak(patrz ASCII) odpowiadajacy liczbie i wyswietlic to w petli znak po znaku.

Mozesz takze zwiekszyc w petli kazda liczbe o te 48, a nastepnie dopisac 0 na koniec lancucha i skorzystac raz z innego przerwania wypisujacego caly lancuch znakow.

0

@t0m_k, o czym Ty pieprzysz? Przeczytaj pierwszy post. Podany kod sortuje bajty, czyli właśnie znaki...

0

Masz racje, nie spojrzalem na to db ;/ W takim razie pozostaje tylko uzyc, ktorejs z funkcji przerwania 21h, a mysle ze to juz nie bedzie problemem skoro nawet nie trzeba dodawac tych 48, wystarczy tylko zajrzec do jakiegos spisu przerwan, czy kursu.

0

Dobra ogarnę to już jutro bo mi bania pęka :P

Czyli rozumiem, że ostatni kod, który pokazałem jest ok, tylko trzeba do niego dodać jeszcze jakąś funckje przerwania żeby się coś w końcu wyświetliło..hmm.. dam znać jutro co mi wyszło, bo na chwilę obecną to już mam chaos w głowie...

0

Dobra tutaj masz ta funkcje z 21h, bo juz sie zakrecilem kompletnie myslalem ze o liczby chodzi...

funkcja 9 - wyświetl napis:
Argumenty:
    * AH = 9
    * DS:DX = adres łańcucha znaków zakończonego znakiem dolara "$"
0

Przerwania przypadkiem nie są już archaikiem z 16 bitowców? Bo na mojej 64-bit Win7ce - bez wsparcia dla programów dosowych - z przerwaniami się musiałem pożegnać...

0
MSM napisał(a)

Przerwania przypadkiem nie są już archaikiem z 16 bitowców? Bo na mojej 64-bit Win7ce - bez wsparcia dla programów dosowych - z przerwaniami się musiałem pożegnać...

Super, tylko to właśnie jest 16-bitowy kod pod DOS, takiego asma się na studiach uczy.

0
t0m_k-tmp napisał(a)

Dobra tutaj masz ta funkcje z 21h, bo juz sie zakrecilem kompletnie myslalem ze o liczby chodzi...

funkcja 9 - wyświetl napis:
Argumenty:
    * AH = 9
    * DS:DX = adres łańcucha znaków zakończonego znakiem dolara "$"

No wiem, że jest taka funkcja, używaliśmy jej na ćwiczeniach. Tylko pytanie gdzie mam ją wstawić przed pętlą po prostu, bo już naprawdę mam mętlik w głowie i będzie ona wyglądała tak ?:

mov dx ,OFFSET bufor
mov ah, 09H
int 21H

?

0

Daj ja od razu po etykiecie _end, jesli OFFSET w skladni tasm daje adres tego bufora i masz zakonczony dolarem.

0

Zrobiłem tak:

.model small
.stack 100h

.data

bufor   db 20 dup('$')

ilosc   = $ - bufor

.code
main:
	mov ax,SEG bufor ; 
  	mov ds,ax  

	mov ah,0aH
	int 21H
	
	mov ah,08H
	int 21H
	
        
	push    @data
        pop     ds
        
        mov     cx, OFFSET ilosc
        mov     bx, OFFSET bufor
;------------------------------------------------------------------------------
_bs_loop: 
        mov     si, cx                  
        xor     di, di
_bs_loop_swap: 
        dec     si
        jz      _bs_loop_next
        mov     ax, [bx+si-1]
        cmp     al, ah
        jc      _bs_loop_swap
        xchg    al, ah
        inc     di
        mov     [bx+si-1], ax
        jmp     _bs_loop_swap
_bs_loop_next:
        test    di, di
        jz      _end 
        loop    _bs_loop 
;------------------------------------------------------------------------------       


_end:
        mov     ax, 4c00h
        int     21h

	mov dx, OFFSET bufor
	mov ah, 09H
	int 21H
end main

i nadal mi się nie wyświetla ;/

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