logo elektroda
logo elektroda
X
logo elektroda
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[Assembler-Linux] Proste pytanie a jednak trudne...

Frubi 21 Mar 2006 13:17 2082 8
  • #1 2440281
    Frubi
    Poziom 13  
    Posty: 111
    Pomógł: 2
    Ocena: 5
    Witam wszystkich.
    Mam taki program:
    ; wersja NASM
    
    section .text                           ; początek sekcji kodu.
        global _start                       ; linker ld chce mieć ten symbol global$
    
    _start:                                 ; punkt startu programu
    
            mov     eax, 4                  ; numer funkcji
                               ;systemowej: sys_write - zapisz do pliku
    
            mov     ebx, 1                  ; numer pliku, do którego piszemy.
                                            ; 1 = stdout = ekran (zazwyczaj)
    
            mov     ecx, tekst              ; ECX = adres (offset) tekstu
    
            mov     edx, dlugosc            ; EDX = długość tekstu
    
            mov     eex, bleble
    
            mov     efx, kociolek
    
            int     80h
    
            mov     eax, 1                  ; numer funkcji
                            ;systemowej (sys_exit - wyjdź z programu)
            int     80h                     ; wywołujemy funkcję
                                            ;systemową
    
    section .data                           ; początek sekcji danych.
    
    bleble  db 'lol', 'lola', 'lolita', 'lolek', 0aah
    
    kociolek equ  $ - bleble
    
    tekst   db      'Jestem',  ' ',  0aah
                                            ;nasz napis, ktory bedzie wyswietlony
    dlugosc equ     $ - tekst               ; długość napisu
    

    i rodzi się moje pytanie bo eex i efx są błędem :/ czy za każdym razem musze 4 rzeczy dać i przerwanie czy da sie jakoś zrobić aby eex efx nie było błędem? a może są jakieś inne komędy które mogą mi w tej chwili pomóc?

    PS: Ucze się z kursu http://rudy.mif.pg.gda.pl/~bogdro/
  • #2 2440736
    Sam Sung
    Poziom 33  
    Posty: 2044
    Pomógł: 227
    Ocena: 611
    Po pierwsze - zobacz, jakie są dostępne rejestry procesora. Ja nie słyszałem o EEX ani EFX, choć może w Pentium V się pojawią.
    Po drugie, nie wiem, co chcesz osiągnąć podając jakieś wartości w innych rejestrach. Funkcje systemowe mają ściśle określone argumenty.
  • #3 2441251
    Frubi
    Poziom 13  
    Posty: 111
    Pomógł: 2
    Ocena: 5
    to czym się różnią eax od ebx??? Kolejnością wykonania z tago co mi wytłumaczyli więc wnioskuje że są dalsze litery alfabetu między e i x ale chyba jestem w błędzie :| Więc jak zrobić aby ten program był w 2 przerwaniach i żeby działał?
  • Pomocny post
    #4 2442180
    elektryk
    Poziom 42  
    Posty: 11029
    Pomógł: 439
    Ocena: 241
    Frubi napisał:
    to czym się różnią eax od ebx??? Kolejnością wykonania z tago co mi wytłumaczyli więc wnioskuje że są dalsze litery alfabetu między e i x ale chyba jestem w błędzie
    No i są, ale rejestrów jest tylko 4 ;)
    Do tego EAX od EBX różnią się optymalnością rozkazów, niektóre rozkazy specjalnie traktują niektóre rejestry.
  • Pomocny post
    #5 2443145
    wiso
    Poziom 15  
    Posty: 92
    Pomógł: 12
    Ocena: 2
    Frubi napisał:
    to czym się różnią eax od ebx??? Kolejnością wykonania z tago co mi wytłumaczyli więc wnioskuje że są dalsze litery alfabetu między e i x ale chyba jestem w błędzie :| Więc jak zrobić aby ten program był w 2 przerwaniach i żeby działał?


    Intel 80x86 Family Architecture
    
    General Purpose Registers                 Segment Registers
    AH/AL AX (EAX) Accumulator             CS Code Segment
    BH/BL BX (EBX) Base                        DS Data Segment
    CH/CL CX (ECX) Counter                  SS Stack Segment
    DH/DL DX (EDX) Data                       ES Extra Segment
    	                                               (FS) 386 and newer
    (Exx) indicates 386+ 32 bit register 	(GS) 386 and newer
    
    Pointer Registers 	                       Stack Registers
    SI (ESI) Source Index 	                   SP (ESP) Stack Pointer
    DI (EDI) Destination Index 	          BP (EBP) Base Pointer
    IP Instruction Pointer
    


    radzę poszukać pełny manual do instrukcji, bez tego pisanie w asemblerze jest karkołomną sprawą :|
  • #6 2447561
    Frubi
    Poziom 13  
    Posty: 111
    Pomógł: 2
    Ocena: 5
    wiso napisał:
    radzę poszukać pełny manual do instrukcji, bez tego pisanie w asemblerze jest karkołomną sprawą :|

    I tu są schody bo ja angielskiego nic a nic i ostatnio mi translator padł:/
  • #7 2447659
    JanuszPulit
    Poziom 17  
    Posty: 175
    Pomógł: 14
    Ocena: 4
    Cóż jeżeli myślisz o programowaniu to nie masz wyjścia i angielski musisz poznać...
  • Pomocny post
    #8 2448836
    Akane
    Poziom 27  
    Posty: 638
    Pomógł: 144
    Ocena: 33
    ebx, esi i edi są rejestrami które musisz zachować w niezmienionej wersji wracając z funkcji.
    ebx z niczym extra mi się nie kojaży, ecx działa jako licznik w krótkich rozkazach typu "lawinowego":

    mov eax,0 ; szukamy zera czyli konca stringu (mov al,0 wystarczy, ale kto tak pisze)
    mov ecx,-1; max 0xFFFFFFFF znaków do przeszukania
    mov edi,lpString ; w tym stringu
    repne scasb ; szukaj bajtu al w [edi] (scasw szuka word ax, scasd szuka dword eax)


    samo scasb wykonuje się tylko raz, porównuje al z [edi], zwiększa(*) edi o jeden i zmniejsza(*) ecx o jeden
    repne - powtarzaj dopóki NE not-equal nie-zgodne,
    czyli byte[edi] != 0. Jeśli ecx zmniejszy się do zera szukanie jest przerywane.
    (*) - jeśli nie ustawisz flagi kierunku - cld/std - ta flaga standardowo jest wyzerowana przez system (więc edi się zwiększa) i powinna być zachowana przed jakimkolwiek odwołaniem się do systemu lub obcej funkcji:
    %include "asm.inc"
    main:
    	std              // ustaw flagę kierunku (experimental)
    	cdecl  strcat, "blah", "2"
    	invoke ExitProcess,0

    spowoduje exception w module crtdll, nie z powodu że statyczny string jest zmieniany bo jest on w sekcji .data (read/write), ale z powodu ustawionej flagi kierunku co powoduje że funkcja strcat nadpisuje string od pierwsze litery do tyłu, czyli (w tym przypadku) wychodzi poza obszar gdzie można modyfikować dane

    mov al,[esi albo edi albo ebp albo esp] jest mniejsze objętościowo od mov al,[eax,ebx,ecx albo edx], ale nic nie stoi na przeszkodzie żeby indexować tablice przez np edx.
    Często mam problem: esp i ebp wiadomo - esp to wierzchołek stosu, ebp to spód lokalnych zmiennych; edi i esi już wskazują na jakieś tablice/struktury, więc pozostaje eax,ebx...edx jako pointer.

    Wg. mnie intel skopał sprawę z ilością zwyczajnych rejestrów i z możliwościami kombinacji argumentów, te problemy były od czasu Z80 i nadal są: np scas* działa tylko z eax i edi, movs* -eax+esi ...
    nie można napisać scasb dl,edx bo jest ograniczenie, ba, nawet nie podaje się tutaj argumentów.

    Czyli dotychczasowe "super" procesory to zwykłe, ograniczone mikroprocesory 32 bitowe :)
    Owszem są zmienne w pamięci - stos, data, bss... ale każdy dodatkowy odczyt z pamięci spowalnia program, pisanie w assemblerze traci sens bo czas wykonania tego samego algorytmu jest taki sam jak programu w C


    standardowe użycie kilku rejestrów wygląda mniejwięcej tak:
    %include "asm.inc"
    main:
    	call   PoliczDlugoscStringuA, "elektroda.pl"
    	// eax=12
    	invoke ExitProcess,0
    
    // wywala okienko z napisem "string size=13"
    
    PoliczDlugoscStringuA: // ,string *lpString
    	push ebp
    	mov  ebp,esp
    	sub  esp,64  // bardziej oplaca sie enter 64,0
    
    	// mamy 64 prywatnych bajtów na stosie
    	push edi  // edi będzie modyfikowany
    	%define lpString [ebp+8] // argument funkcji
    	%define MyBuffor [ebp-64] // lokalne zmienne
    
    	mov   edi,lpString
    	xor   eax,eax
    	or    ecx,-1
    	repne scasb
    	dec   edi // edi przeskoczylo zero na koncu stringu
    	sub   edi,lpString // edi = strlen
    
    	// macro offset = lea eax, %1
    	cdecl  sprintf, offset MyBuffor, "string size=%d", edi
    	push   eax // zachowaj bo msgbox zmieni
    	invoke MessageBoxA, 0, offset MyBuffor, "wynik",MB_ICONINFORMATION
    	pop    eax
    
    	pop    edi
    	leave // mov esp,ebp / pop ebp
    	ret 4

    nie wzoruj się tym sposobem liczenia długości stringu bo jest on powolny (cena małego kodu)

    Jeśli standardowo piszesz w C to daruj sobie asemblera.
    Jeśli to delphi albo jakiś inny generator kodu to warto, jeśli lubisz nasm (prawdziwe rozkazy) to dysponuję wersją wspierającą unicode

    Questions?
  • #9 2454230
    Frubi
    Poziom 13  
    Posty: 111
    Pomógł: 2
    Ocena: 5
    Jak narazie to jedyny poważniejszy język programowania jakiego się uczyłem to C++ :D
    I chyba z assemblerem przesadziłem :/ Akane oczywiscie dostał to na co zasłużył i wszyscy są zadowoleni.

Podsumowanie tematu

LABEL_AI_GENERATED
Dyskusja dotyczy problemów z pisaniem prostego programu w asemblerze NASM pod Linux, wykorzystującego wywołania systemowe przez przerwanie 0x80. Autor programu używa nieistniejących rejestrów EEX i EFX, co zostało skorygowane przez uczestników wskazujących, że dostępne są tylko standardowe rejestry 32-bitowe EAX, EBX, ECX, EDX oraz inne rejestry ogólnego przeznaczenia (ESI, EDI, EBP, ESP). Podkreślono, że funkcje systemowe mają ściśle określone argumenty przekazywane w konkretnych rejestrach, a niepoprawne użycie rejestrów powoduje błędy. Omówiono różnice między rejestrami, ich przeznaczenie i optymalizację rozkazów, a także znaczenie znajomości angielskiego do czytania dokumentacji technicznej. Przedstawiono podstawowe informacje o architekturze Intel 80x86, rejestrach segmentowych i ogólnego przeznaczenia oraz wskazano na konieczność zachowania niektórych rejestrów (np. EBX, ESI, EDI) podczas wywołań funkcji. Podano przykłady użycia instrukcji asemblerowych takich jak MOV, INT 80h, REPNE SCASB oraz znaczenie flag kierunku (CLD/STD). Autor przyznał, że asembler jest dla niego trudniejszy niż C++.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA