Prosty kod, ćwiczenie z asma

0

Witajcie, ostatnio ucze się asemblera, cięęężko to idzie, ale jakoś powolutku do przodu.
ucze się z tutoriala http://home.elka.pw.edu.pl/~mkurdej1/asm/asm_pdf_linux.pdf na tej stronie.

I do zrobienia mam banalne zadanie, ale rady nie daje, prosił bym o wytłumaczenie, co w moim kodzie jest źle, jest krótki, na szczęscie :D

"Napisz program obliczający (nie wyświetlający) wartość 10*PI. Potem sprawdź, czy sinus tej liczby
jest zerem"

section .text
global _start
_start:
        finit
        fldpi                            ;st0 = pi , ładuje PI
        fmul dword [ten]        ;st0 = pi*10 ( nie chcialem ladowac zmiennej ten na stos bo chyba, można obliczyc tez tak)
        fsin                             ;st0 = sin(st0) ( Czy aby na pewno ;> ? )

        ftst                             ;czy st(0) == 0
        fstsw ax                     
        sahf                           ;rozumiem ze tu przenosimy flagi fpu do rejestru flag procesora

        jz tak              
         
        mov ecx, nie
        mov edx, nie_d

        jmp pisz
tak:
        mov ecx, tak1
        mov edx, tak1_d
pisz:
        mov eax, 4
        mov ebx, 1
        int 80h

        mov eax, 1
        xor ebx,ebx
        int 80h

section .data
tak1    db      "Jest równe zeru",0ah
tak1_d  equ     $-tak1

nie     db      "Nie jest równe zeru",0ah
nie_d   equ     $-nie

ten     dw      0ah

z góry za pomoc dziękuje :)

1

fmul dword [ten] pewnyś tego? Abstrachuje od nie używania segmentów, ale masz tu dw do którego wpisałeś inta, a fmul oczekuje że masz floata/double. Do mnożenia przez inta jest fimul.

0

kompiluje nasmem
Wypisują sie śmieci, niezgodne z zegarem, dla AH ( dziesiątki) to już w ogóle cuda wianki, literki, , dla jedności wieksza o jeden , potem o dwie, i trzy sekundy.

section .text
global _start

_start:
        mov eax, 101                    ;sys_ioperm
        mov ebx, 70h                    ; tego chcemy uzywac
        mov ecx, 20                     ; tyle bajtów
        mov edx, 71h                    ; max port
        int 80h

        cmp eax, 0                      ; czy blad
        jl koniec                       ; jesli blad

        mov eax, 4                      
        mov ebx, 1
        mov ecx, grant
        mov edx, grantl
        int 80h                         

        mov al, 0
        out 70h, ax
        mov ecx, 10000          ; aby opóznic bo ponoc cmos moze nie zdązyc z odpowiedzią na żadanie

        call nic1

        xor edx,edx                ; tu jest problem
        mov cx, 10                  ; dziele ax przez 10  zakres <0;59>
        div cx                          ;ah = reszta , al - iloraz

        add ah, 30h                ; mozliwe dane w ah, <0; 5>, w al <0,9> to nieco skok myślowy nie mam pojecia jak to inaczej przekonwertować w asmie :D
                                           ; teoretycznie teraz wystarczy dane wypisac , ale wychodza smieci, i z ah i z al
        mov [sec0], ah     

        mov eax, 4  ; wypisz dane
        mov ebx, 1
        mov ecx, sec0
        mov edx, 1
        int 80h

        mov eax,1  ; wyjscie
        mov ebx,0
        int 80h
koniec:
        mov eax, 4
        mov ebx, 1
        mov ecx, error
        mov edx, errorl
        int 80h

        mov eax, 1
        xor ebx,ebx
        int 80h
nic1:
        nop
        loop nic1
        in ax,71h ; Do ax zapisuje sobie bajcik danych, sekundy konkretnie
        ret

section .data
dwuka   db      ":"
dwukl   equ     $-dwuka

error   db      "nimo dostepu", 0ah
errorl  equ     $-error

grant   db      "dostep jest", 0ah
grantl  equ     $-grant

sec0    db      0
sec1    db      0
min0    db      0
min1    db      0
hrr0    db      0
hrr1    db      0

nl      db      0ah
nll     equ     $-nl

Takowięc, co ja robie źle, od rana nad tym siedze, i wychwycić nie moge co tu jest nie tak, wiem że czytanie asemblerowego kodu-makaronu, to ŻADNA przyjemność, ale może jakaś dobra dusza mi pomoże :D

/edit
Poza tym, czy dobrym pomysłem jest nauka asma, aby zrozumieć jak tak naprawde funkcjonuje komputer?
Na chwile zostawiłem c++ bo chciałem zrozumieć komputer że tak powiem, z niższego punktu widzenia.
I ewentualnie chciałem zahaczyć o RE, ale to chyba nie jest zabawa na chwile
Pozdrawiam

0

Pierwsze co rzuciło się w oczy to to, że źle wywołujesz funkcję. Chodzi mi o funkcję nic1. Na początku powinieneś tworzyć ramkę stosu.
Asemblera warto się uczyć.
Chociaż w pewnych kręgach można zobaczyć taką notkę:

"He who hasn't hacked assembly language as a youth has no heart. He who does so as an adult has no brain" - John Moore

na pewno opanowanie tego języka jest znacznie bardziej czasochłonne od innych (nie wliczając w to Javy).

0

@Elga co to za bzdury? o_O Nie ma tam żadnej "funkcji", to raz, dwa wcale żadnej ramki stosu ręcznie nie trzeba robić. "call" powoduje automatycznie odłożenie aktualnej wartości IP na stos i skok do podanej etykiety, "ret" powoduje zdjęcie ze stosu wartości i wrzucenie jej do IP oraz jej inkrementacje.

0

Ja bym w ogóle proponował przejście na Windows ponieważ jest tu o wiele więcej narzędzi do debuggowania, bardziej przyjaznych niż konsolowy GDB.

Proponuję OllyDbg v2:

http://www.ollydbg.de/version2.html

Pisząc w asm koniecznie musisz zaznajomić się z debuggerem, poprawianie kodu w pliku, odpalanie i sprawdzanie wyników nie jest dobrą metodą na dojście gdzie jest błąd, a tak odpalisz kod pod debuggerem i krok po kroku zobaczysz jak twoje instrukcje asm przekładają się na stan rejestrów (także FPU), jak działa stos, jakie flagi ustawiane są lub zerowane w wyniku wykonanych operacji i jak operacje np. zapisu wpływają na pamięć. Nie ma lepszej metody na zrozumienia funkcjonowania assemblera niż obserwowanie na żywo jak to wszystko się odbywa.

Tutaj jeden z ciekawszych tutoriali o programowaniu w asm pod Windows:

http://win32assembly.programminghorizon.com/tutorials.html

Co do twojego kodu to kilka uwag:

  1. Przesiądź się na pakiet MASM (http://www.masm32.com/)

  2. Naucz się jak pisać funkcje, ale nie w trybie raw, że ręcznie budujesz ramki stosu, tylko "funkcja proc uses esi edi ebx, Parametr1:dword, Parametr2:dword" np. zbuduj funkcję do wyświetlania tekstu na ekranie.

  3. Nie mieszaj kodu 32 bitowego z 16 bitowym jeśli to nie jest naprawdę konieczne.

0

@Shalom zgadza się, wszystko fajnie do czasu kiedy odłożysz coś na stosie. Napisałam, że jest to błędne podejście, ponieważ jest. Nic nie pisałam o tym, że może to przeszkodzić akurat w tym przypadku.

0

Pierwsze co rzuciło się w oczy to to, że źle wywołujesz funkcję. Chodzi mi o funkcję nic1. Na początku powinieneś tworzyć ramkę stosu.

Nie trzeba tworzyć żadnej ramki stosu. To konwencja stosowana przez kompilatory wyższego poziomu (np. C) i służy do alokacji miejsca na stosie na zmienne lokalne.

Tutaj nie widzę żadnych zmiennych lokalnych, więc ramka stosu niczemu nie służy.

0

To ja w takim razie mam jescze pytanie.
To kod ze stronki, rozumiem go poza 3 liniami, po co od eax odejmujemy 48, potem inkrementujemy i następnie znowu dodajemy 48?
@ edit
Zastanowiłem się, i rozpisałem sobie zawartość eax, po każdej iteracji i , zrozumiałem :)
Nieco sie pospieszyłem z pytaniem, ale czy dobrze to rozumiem?
eax 49

  1. iteracja
    sub 48 / eax = 1
    inc, /eax = 2
    add 48/ eax = 50
    2.iteracja
    sub 48 /eax = 2
    inc /eax = 3
    add 48/ eax = 51
  2. iteracja
    sub 48 / eax = 3
    inc / eax = 4
    add 48/ eax = 52
    // I tak aż do eax = 57
section    .text
    global _start         
_start:                    
    mov ecx,10
    mov eax, '1'
 
l1:
    mov [num], eax
    mov eax, 4
    mov ebx, 1
    push ecx
    mov ecx, num        
        mov edx, 1        
        int 0x80
    mov eax, [num]
    sub eax, '0'   ; tu
    inc eax          ;tu
    add eax, '0'   ;i tu
    pop ecx
    loop l1
    mov eax,1       
    int 0x80       
section    .bss
num resb 1
1

Podaję poprawiony kod z sekundami, może komuś się przyda

section .text
global _start
 
_start:
        mov eax, 101                    ;sys_ioperm
        mov ebx, 70h                    ; tego chcemy uzywac
        mov ecx, 20                     ; tyle bajtów
        mov edx, 71h                    ; max port
        int 80h
 
        cmp eax, 0                      ; czy blad
        jl koniec                       ; jesli blad
 
        mov eax, 4                      
        mov ebx, 1
        mov ecx, grant
        mov edx, grantl
        int 80h                         
 
        xor ax,ax
	out 70h, ax
        mov ecx, 10000          ; aby opóznic bo ponoc cmos moze nie zdązyc z odpowiedzią na żadanie
 

 nic1:
        nop
        loop nic1
        in ax,71h ; Do ax zapisuje sobie bajcik danych, sekundy konkretnie

	push eax		; przekazujemy parametr do funkcji
	call sekundy
	
        mov eax, 4  ; wypisz dane
        mov ebx, 1
        mov ecx, sec1
        mov edx, 1
        int 80h

        mov eax, 4  ; wypisz dane
        mov ebx, 1
        mov ecx, sec0
        mov edx, 1
        int 80h
 
        mov eax,1  ; wyjscie
        mov ebx,0
        int 80h
koniec:
        mov eax, 4
        mov ebx, 1
        mov ecx, error
        mov edx, errorl
        int 80h
 
        mov eax, 1
        xor ebx,ebx
        int 80h


sekundy:			;  
	push ebp		; 
	mov ebp, esp		;

	mov eax,[ebp+8]		; odczyt ze stosu
        mov dl,al               ; w al kod BCD sekund
        mov cl,0Fh              ; wartosc 0000 1111
        and al,cl               ; otrzymujemy dolne cztery bity
        add al,30h              ;
        mov [sec0], al          ;
        mov al,dl               ;
        ror al,4                ; przesunięcie o 4 bity w prawo
        and al,cl               ; wyczyszczenie smieci
        add al,30h              ;
        mov [sec1], al          ;

	pop ebp
ret 4				; dodanie do stosu 4 poniewaz odlozyliśmy 1 argument przed call'em


section .data
dwuka   db      ":"
dwukl   equ     $-dwuka
 
error   db      "nimo dostepu", 0ah
errorl  equ     $-error
 
grant   db      "dostep jest", 0ah
grantl  equ     $-grant
 
sec0    db      0
sec1    db      0
min0    db      0
min1    db      0
hrr0    db      0
hrr1    db      0
 
nl      db      0ah
nll     equ     $-nl

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