Assembler i tablice wielowymiarowe

Assembler i tablice wielowymiarowe
grzesiek51114
grzesiek51114
  • Rejestracja:ponad 11 lat
  • Ostatnio:ponad 4 lata
  • Postów:2442
0

Krótko i do rzeczy: Zastanawiam się czy dobrze rozumiem wielowymiarowe tablice w ASM? [NASM 32bit konkretnie]

Zrobiłem dla testu coś takiego:

Kopiuj
 
global _main
extern _printf
extern _scanf

section .data
tab    dd    1, 11, 12, 13, 2, 21, 22, 23, 3, 31, 32, 33
fmt    db    "%d ", 0
nl     db    0ah, 0dh

section .bss
i    resd    1
j    resd    1

offset_1    resd    1
offset_2    resd    1

section .text
_main:
    mov ebp, esp; for correct debugging
    
    mov dword[i], 0
    mov dword[j], 0
    mov dword[offset_1], 0
    mov dword[offset_2], 4
    
pierwsza:
    mov edi, dword[offset_1]
    push dword[tab+edi+esi]
    push fmt
    call _printf
    add esp, 8
    
    mov dword[j], 0
    druga:
        mov esi, dword[offset_2]
        push dword[tab+edi+esi]
        push fmt
        call _printf
        add esp, 8
        
        mov dword[offset_2], esi
        add dword[offset_2], 4
        
        inc dword[j]
        cmp dword[j], 3
        jne druga
        
    push nl
    call _printf
    add esp, 4        
    
    mov dword[offset_1], edi
    add dword[offset_1], 4
    
    inc dword[i]
    cmp dword[i], 3
    jne pierwsza

koniec:
    xor eax, eax
    ret

Tab to tak naprawdę ciągły obszar pamięci ale cyfry 1, 2 oraz 3 oznaczają wiersze w tablicy 2D. Dwucyfrowe wartości to wartości kolumn tablicy 2D.

I teraz tak: skoro to jest ciągły obszar pamięci to tak naprawdę tablice wielowymiarowe można sobie implementować wedle uznania operując jedynie offsetami przesuwającymi kolumny i wiersze. :) Właściwie jak wskaźniki tablicowe w C (stąd to się przecież wzięło).

Pytanie początkującego asmowca: czy dobrze to rozumiem? :)

edytowany 2x, ostatnio: grzesiek51114
Akasei
Nie wiesz co jest w rejestrze ESI, to może być pułapka. Etykieta "pierwsza:", drugi wiersz "push dword[tab+edi+esi]"
Bartosz Wójcik
  • Rejestracja:około 14 lat
  • Ostatnio:ponad 4 lata
  • Postów:439
2

Dobrze to rozumiesz. To ciągłe obszary pamięci. Swoją drogą oczy mnie bolą od twojego kodu, jeśli piszesz w assemblerze to pisz w assemblerze i korzystaj z rejestrów zamiast z globalnych zmiennych. Przykładowo rejestr EBX jest wolny i nie jest modyfikowany pomiędzy wywołaniami funkcji, masz w kodzie często powtarzającą się wartość 0 w różnych operacjach, wyzeruj EBX na początku XOR EBX, EBX i używaj jego wartości w operacjach z zerem, np. AND DWORD[ZMIENNA],EBX zamiast MOV DWORD[ZMIENNA],0. Możesz też wywalić jakąś zmienną globalną (która potem nie jest nigdzie wykorzystywana) i zastąpić ją np. rejestrem EBX. Naucz się korzystać poprawnie z rejestrów, a twoje życie z assemblerem stanie się proste i przyjemne :)

grzesiek51114
grzesiek51114
  • Rejestracja:ponad 11 lat
  • Ostatnio:ponad 4 lata
  • Postów:2442
0

Wziąłem sobie do serca Twoje rady i rzeczywiście teraz kod jest bardziej czytelny. Jedyne zmienne to tak naprawdę sama tablica i wskaźniki na format danych oraz nową linię. Jeszcze wrzuciłem wskaźnik do funkcji do rejestru, bo gwarantuje to szybsze wywołanie.

Kopiuj
global _main
extern _printf

section .data
fmt    db    "%d ", 0
nl     db    0ah, 0dh

section .bss
tablica    resd    6; Tablica dwuwymiarowa

section .text
_main:
    xor edi, edi; Licznik pierwszego wymiaru
    xor ebx, ebx; Licznik drugiego wymiaru
    mov esi, _printf; Przekazanie wskaźnika do funkcji do rejestru
    
pierwsza:
    druga:
        mov eax, ebx; Przechowanie w eax licznika petli
        add ebx, edi; Sumowanie obu licznikow
        
        mov ecx, ebx; Przerzucenie wyniku do ecx
        mov ebx, eax; Odtworzenie stanu licznika petli
    
        mov dword[tablica+edi+ebx], ecx; Wrzucenie wyniku sumy jako elementu tablicy, żeby coś tam było jako dane testowe.
        
        push dword[tablica+edi+ebx]
        push fmt
        call esi
        add esp, 8
        
        inc ebx
        cmp ebx, 3
        jne druga    

    push nl
    call esi
    add esp, 4

    xor ebx, ebx
    inc edi
    cmp edi, 2
    jne pierwsza

koniec:
    xor eax, eax
    ret
edytowany 2x, ostatnio: grzesiek51114
Bartosz Wójcik
Coraz lepiej :), teraz naucz się konstruować funkcje i korzystać ze zmiennych lokalnych (zapisywanych na stosie), w ten sposób pozbędziesz się globalnych wartości, których potrzebujesz jedynie w ciele funkcji (np. tej tablicy). Skoro robisz mov dword[tablica+edi+ebx], ecx i w ECX masz tą wartość, to po co push dword[tablica+edi+ebx] wystarczy PUSH ECX juz tutaj. No i wychodzi, że nawet nie potrzebujesz tej zmiennej tablica skoro z jej wartości poza 1 miejscem w pętli nie korzystasz.
grzesiek51114
grzesiek51114
Jak znów wrócę do asma, co niebawem pewnie się stanie, to spróbuję zrobić jak mówisz. Teraz ostatnio pisałem qsorta w asm ale przy rekurencji niestety wysiadłem, bo na tak niskim poziomie kodowania trzeba pamiętać dodatkowo o wielu rzeczach. Funkcja wrzuca na stos różne rzeczy, które trzeba zdejmować, żeby dobrać się do właściwych danych etc. Ale przynajmniej partycjonowanie jest zrobione prawidłowo :) Dzięki za pomoc :)
Bartosz Wójcik
Na stosie w funkcji możesz mieć co chcesz, nawet rekurencyjnie jeśli wywołujesz tą samą funkcję, to wszystko samo się "odkręci" po wykonaniu instrukcji RET, wątpię żebyś miał tam tyle megabajtów żeby wyczerpać przydzielony limit pamięci. Poza tym jeśli trzymasz coś na stosie, to lepiej to trzymać w zmiennych lokalnych jeśli masz wątpliwości.
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)