Asembler aplikacja graficzna - problem

0

Moze ktos pomóc mam program napisany w jezyku asemblera jego zadaniem jest sortowanie liczb całkowitych, po nacisnieciu przycisku, program czyta liczby z pliku i zapisuje je juz posortowane, problem tkwi w tym ze zawiesza sie, i nie wypisuje danych juz posortowanych do konsoli. Moze ktos to ogarnie.

 .586P
.MODEL flat, STDCALL

;--- struktury ---
LARGE_INTEGER UNION
STRUCT
LowPart DWORD ?
HighPart DWORD ?
ENDS
QuadPart QWORD ?
LARGE_INTEGER ENDS
;--- funkcje API Win32 ---
;--- funkcje
GetTickCount PROTO
;;DWORD GetTickCount(VOID) ;czas w milisekundach od uruchomienia komputera
QueryPerformanceFrequency PROTO lpFrequency:DWORD
;;BOOL QueryPerformanceFrequency(
;;LARGE_INTEGER *lpFrequency // address of current frequency );
QueryPerformanceCounter PROTO lpPerformanceCount:DWORD
;;BOOL QueryPerformanceCounter(
;;LARGE_INTEGER
;--- pliki ---------
include .\include\grafika.inc


;--- biblioteki ---------
includelib .\lib\user32.lib
includelib .\lib\kernel32.lib
includelib .\lib\gdi32.lib
INCLUDELIB  .\lib\masm32.lib


STD_INPUT_HANDLE                     equ -10
STD_OUTPUT_HANDLE                    equ -11
GENERIC_READ                         equ 80000000h
GENERIC_WRITE                        equ 40000000h
CREATE_NEW                           equ 1
CREATE_ALWAYS                        equ 2
OPEN_EXISTING                        equ 3
OPEN_ALWAYS                          equ 4

;---stale pomiaru czasu---
STD_INPUT_HANDLE equ -10
STD_OUTPUT_HANDLE equ -11

;--- funkcje API Win32 z pliku  .\include\user32.inc ---
CharToOemA PROTO :DWORD,:DWORD
GetStdHandle PROTO :DWORD
ReadConsoleA PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD
WriteConsoleA PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD
ExitProcess PROTO :DWORD
lstrlenA PROTO :DWORD
GetTickCount PROTO
GetStdHandle PROTO :DWORD
ReadConsoleA PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD
WriteConsoleA PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD
ExitProcess PROTO :DWORD
lstrlenA PROTO :DWORD
GetCurrentDirectoryA PROTO :DWORD,:DWORD  
CreateDirectoryA PROTO :DWORD,:DWORD      
lstrcatA PROTO :DWORD,:DWORD              
CreateFileA PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD 
lstrcpyA PROTO :DWORD,:DWORD  
CloseHandle PROTO :DWORD      
WriteFile PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD    
ReadFile PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD
CopyFileA PROTO :DWORD,:DWORD,:DWORD      
GetLastError PROTO
GetFileSize PROTO :DWORD, :DWORD


;--- stałe ---
CSstyle EQU CS_HREDRAW+CS_VREDRAW+CS_GLOBALCLASS
BSstyle EQU BS_PUSHBUTTON+WS_VISIBLE+WS_CHILD+WS_TABSTOP
WNDstyle EQU WS_CLIPCHILDREN OR WS_OVERLAPPEDWINDOW OR \
WS_HSCROLL OR WS_VSCROLL
STATstyle EQU SS_CENTER+WS_VISIBLE+WS_CHILD+WS_TABSTOP+WS_BORDER
kolor EQU 000000FFh ; czerwony ; kolory: G B R
;--- sekcja danych ------
_DATA SEGMENT
    hwnd    DD 0
    hinst   DD 0
    hdc     DD 0
    hbutt   DD 0
    hedt    DD 0
    hbrush  DD 0
    holdbrush DD 0
    hout    DD 0
    rout    DD 0

    hinp    DD 0
    rinp    DD 0
   
    nl      DB 0Dh,0Ah,0

    
;----zmienne dotyczace obliczenia czasu------
    wzor  DB 0Dh,0Ah,"Czas = %ld periodow przy czestotliwosci %ld periodow/sek", 0
    czas1 DD ?
    delta DD ?
    czest DD	?

;-----zmienne do pliku-----------------------

    newDirName     DB "\dane",0
    newDirNameSize DD $ - newDirName

    plik		 DB	"\dane_wejsciowe.txt",0
    file1Path	 DB	128 dup(?)
    file1IO		 DD	?
    plik2		 DB	"\Posortowane_liczby_calkowite.txt",0
    file2Path	 DB	128 dup(?)
    file2IO		 DD	?
    plik3		 DB	"\czas_wykonania_algorytmu.txt",0
    file3Path	 DB	128 dup(?)
    file3IO		 DD	?
    output         DB   "%ld",0Dh,0Ah,0

    consoleOut          DD    ?
    sth                 DB    0
    dir                 DB    128 dup(?)
    dirSize             DD    128
    buforSize           DD    128
    temp                DB    "%d ",0
    hfile   DD 0
    rfile   DD 0
    liczba  DB 1024 dup(?)
    
;-----zmienne do sortowania-----------------------
    tab1       DD 5000 dup(0)
    liczbaTmp  DD 1
    iloscLiczb DD 1
    i          DD 1
    j          DD 1
    n1         DD 1
    n2         DD 1
    tmp        DD 1
 ;-----zmienne dodatkowe----------------------------   
    naglow  DB "Autor programu: Ja.",0
    rozmN   DD $ - naglow ;ilość znaków w tablicy
    naglow4 DB "Temat: Sortowanie liczb całkowitych w tablicy metodą bombelkową.",0
    rozmN4  DD $ - naglow ;ilość znaków w tablicy

    puste   DB "_____________________" ; spacje
    rozmP   DD $ - puste ;ilość znaków w tablicy
    tytul   DB "Projekt z programowania niskopoziomowego.",0
    cname   DB "MainClass", 0
    MES1    DB "Lewy, myszy",0
    tbutt   DB "BUTTON", 0
    tstart  DB "SORTUJ", 0
    nagl    DB "Komunikat", 0
    terr    DB "Błąd!", 0
    terr2   DB "Błąd 2!", 0
    bufor   DB 128 dup(' ') ; bufor ze spacjami
    rbuf    DD 128 ; rozmiar buforu

	
;-----------------------------------------------------------------
    msg MSGSTRUCT <?>
    wndc WNDCLASS <?>
;-----------------------------------------------------------------
_BSS SEGMENT

	count1 							LARGE_INTEGER <>
	count2 							LARGE_INTEGER <>
	freq 							      LARGE_INTEGER <>
	
_BSS ENDS
_DATA ENDS

;--- sekcja kodu ---------
_TEXT SEGMENT

 ScanInt	PROC
    ;; funkcja ScanInt przekształca cišg cyfr do liczby, którš jest zwracana przez EAX
    ;; argument - zakończony zerem wiersz z cyframi
    ;; rejestry: EBX - adres wiersza, EDX - znak liczby, ESI - indeks cyfry w wierszu, EDI - tymczasowy
    ;--- poczštek funkcji
    	push	EBP
    	mov	EBP, ESP	; wska?nik stosu ESP przypisujemy do EBP
    ;--- odkładanie na stos
    	push	EBX
    	push	ECX
    	push	EDX
    	push	ESI
    	push	EDI
    ;--- przygotowywanie cyklu
    	mov	EBX, [EBP+8]
    	push	EBX
    	call	lstrlenA
    	mov	EDI, EAX	;ilosć znaków
    	mov	ECX, EAX	;ilosć powtórzeń = ilosć znaków
    	xor	ESI, ESI	; wyzerowanie ESI
    	xor	EDX, EDX	; wyzerowanie EDX
    	xor	EAX, EAX	; wyzerowanie EAX
    ;--- cykl --------------------------
    @@pocz:
    	cmp	BYTE PTR [EBX+ESI], 02Dh	;porównanie z kodem -
    	jne	@@et1
    	mov	EDX, 1
    	jmp	@@nast
    @@et1:
    	cmp	BYTE PTR [EBX+ESI], 030h	;porównanie z kodem 0
    	jae	@@et2
    	jmp	@@nast
    @@et2:
    	cmp	BYTE PTR [EBX+ESI], 039h	;porównanie z kodem 9
    	jbe	@@et3
    	jmp	@@nast
    ;----
    @@et3:	
    push	EDX	; do EDX procesor może zapisać wynik mnożenia 
    	mov	EDI, 10
    	mul	EDI		;mnożenie EAX * EDI
    	mov	EDI, EAX	; tymczasowo z EAX do EDI
    	xor	EAX, EAX	;zerowani EAX
    	mov	AL, BYTE PTR [EBX+ESI]
    	sub	AL, 030h	; korekta: cyfra = kod znaku - kod 0	
    	add	EAX, EDI	; dodanie cyfry
    	pop	EDX
    @@nast:	inc	ESI
    	loop	@@pocz
    ;--- wynik
    	or	EDX, EDX	;analiza znacznika EDX
    	jz	@@et4
    	neg	EAX
    @@et4:	
    ;--- zdejmowanie ze stosu
    	pop	EDI
    	pop	ESI
    	pop	EDX
    	pop	ECX
    	pop	EBX
    ;--- powrót
    	pop	EBP
    	ret
    ScanInt	ENDP

WndProc PROC
push EBP ; standardowy prolog
mov EBP, ESP ; standardowy prolog
;--- odkładanie na stos
push EBX
push ESI
push EDI
cmp DWORD PTR [EBP+0Ch], WM_CREATE
jne @F
jmp wmCREATE
@@:
cmp DWORD PTR [EBP+0Ch], WM_DESTROY
jne @F
jmp wmDESTROY
@@:
cmp DWORD PTR [EBP+0CH], WM_COMMAND
jne @F
jmp wmCOMMAND
@@:
;--- komunikaty nieobsługiwane ---
INVOKE DefWindowProcA, DWORD PTR [EBP+08h], \
DWORD PTR [EBP+0Ch], DWORD PTR [EBP+10h], \
DWORD PTR [EBP+14h]
jmp konWNDPROC
 wmCREATE:

;--- utworzenie klawisza ---
INVOKE CreateWindowExA, 0, OFFSET tbutt, OFFSET tstart, \ 
BSstyle, 140, 100, 120, 80, DWORD PTR [EBP+08h], 0, hinst, 0
mov hbutt, EAX
INVOKE SetFocus,hedt
;----------------------------------------------------
INVOKE CreateSolidBrush,kolor
mov hbrush,EAX
;----------------------------------------------
mov EAX,0
jmp konWNDPROC
wmDESTROY:
INVOKE DeleteObject, hbrush
INVOKE PostQuitMessage, 0 ; wysyłanie WM_QUIT
mov EAX, 0
jmp konWNDPROC
wmCOMMAND:
mov EAX,hbutt
cmp EAX,DWORD PTR [EBP+14h] ;czy LPARAM komunikatu \WM_COMMAND = hbutt?
je @F
jmp konWNDPROC 
@@:
   ;------ Otwieranie pliku ------
    invoke  GetCurrentDirectoryA,rbuf,OFFSET bufor      ; Pobiera bierzący katalog do bufora
    invoke  lstrcatA,OFFSET bufor,OFFSET plik        ; Łączy bierzący katalog z nazwą czytanego pliku
    invoke  CreateFileA,OFFSET bufor,GENERIC_READ,0,0,OPEN_EXISTING,0,0    ; otwiera plik
    mov     hfile,EAX 

    
    mov j,0
    mov iloscLiczb,0
@petla1:
    cmp     bufor,0
    je      @koniec1
    
        mov     EDX,OFFSET bufor
        mov     DWORD PTR [EDX],0
        
        invoke  ReadFile,hfile,OFFSET bufor,1,OFFSET rfile,0

        cmp     bufor,0Dh
        je      @koniec2
        cmp     bufor,0Ah
        je      @koniec3

            invoke  lstrcatA,OFFSET liczba,OFFSET bufor
            jmp     @koniec2
            
        @koniec3:
            push    OFFSET liczba
            call    ScanInt

            mov     ECX,j
            mov     EDX,OFFSET tab1
            mov     DWORD PTR [EDX+ECX],EAX

            add j,4
           ; inc     j
           ; inc     j
           ; inc     j
           ; inc     j
            inc     iloscLiczb
           
            @koniec4:

            mov     EDX,OFFSET liczba
            mov     DWORD PTR [EDX],0

            @koniec2:
            jmp     @petla1
            @koniec1: 
            mov EAX,iloscLiczb
            sub EAX,1
            mov iloscLiczb,EAX
;------ Zamknięcie pliku ------
    invoke  CloseHandle,hfile
;-------------------------------------------------------------
;------KONIEC WCZYTYWANIA LICZB DO TABLICY--------------------
;-------------------------------------------------------------
;-------------------------------------------------------------
;------Poczatek SORTOWANIA------------------------------------
;-------------------------------------------------------------
;-------przygotowanie koncowych wartosci petli---------
      mov EAX,iloscLiczb
      mov n2,EAX
      sub EAX,1
      mov n1,EAX


;----------POMIAR CZASU------------------------------- 
		      invoke	QueryPerformanceFrequency,OFFSET freq
		      mov	      eax, freq.LowPart
		      mov	      czest, eax	
		      invoke	QueryPerformanceCounter,OFFSET count1
   

 ;----sortowanie tablicy----------------------------    
     mov i,0 
petlaI: 
       mov EAX,iloscLiczb 
       sub EAX,1 
       mov j,EAX 

petlaJ: 
       mov EAX,4 
       imul j 
       mov EBX,EAX ; indeks j-tego elementu w tablicy 
       mov EAX,j 
       sub EAX,1 
       mov ECX ,4 
       imul ECX 
       mov ECX,EAX ; indekst j-1 elementu  w tablicy 
       mov EAX,[tab1+EBX] 
       mov tmp,EAX        ; j 
       mov EAX,[tab1+ECX] ;j-1 
        
       cmp tmp,EAX 
       jb  zamiana 
       jmp zmniejszJ 
zamiana: 
       mov EAX,[tab1+EBX] 
       mov tmp,EAX 
       mov EAX,[tab1+ECX] 
       mov [tab1+EBX],EAX 
       mov EAX,tmp 
       mov [tab1+ECX],EAX 
        
zmniejszJ: 
      
       mov EAX,j 
       sub EAX,1 
       mov j,EAX 
       mov EAX,i 
       cmp j,EAX 
       ja  petlaJ 
zwiekszI: 
       inc i 
       mov EAX,iloscLiczb 
       sub EAX,1 
       cmp i,EAX 
       jb  petlaI


;=------------KONIEC SOTROWANIA-----------------------------------
;---- koniec pomiaru czasu----
		      invoke	QueryPerformanceCounter,OFFSET count2
		      mov	      eax, count2.LowPart						 ; Załaduj do EAX wartość pomiaru czasu po sortowaniu
		      sub	      eax, count1.LowPart						 ; Odejmij od EAX wartość pomiaru czasu przed sortowaniem
		      mov 	      delta, EAX	

;------ pobieranie adresu katalogu------------------------
        invoke GetCurrentDirectoryA, dirSize,offset dir
;-------przygotowywanie adresu do pliku sortowanie.txt------
        invoke lstrcpyA, offset file3Path, offset dir
	  invoke lstrcatA, offset file3Path, offset plik3
;-------tworzenie nowego pliku:---------------------------
	  invoke CreateFileA, offset file3Path, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0
	  mov file3IO, EAX
 
         invoke wsprintfA, offset bufor, offset wzor,delta,czest
         mov buforSize, EAX
         invoke WriteFile, file3IO, offset bufor, buforSize, offset sth,0
         invoke  CloseHandle,hfile

;------ pobieranie adresu katalogu------------------------
        invoke GetCurrentDirectoryA, dirSize,offset dir
;-------przygotowywanie adresu do pliku sortowanie--------
        invoke lstrcpyA, offset file2Path, offset dir
	  invoke lstrcatA, offset file2Path, offset plik2
;-------tworzenie nowego pliku:---------------------------
	  invoke CreateFileA, offset file2Path, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0
	  mov file2IO, EAX

 ;--------wypisanie posortowanej tablicy na ekran i do pliku ----------------           
      mov i,0
      wypisz1:
         mov EAX,4
         imul i
         mov ECX,EAX
         mov EDX,OFFSET tab1
         mov EAX,DWORD PTR [EDX+ECX]
         mov liczbaTmp,EAX


         invoke wsprintfA, offset bufor, offset output,liczbaTmp
         mov buforSize, EAX
         invoke WriteFile, file2IO, offset bufor, buforSize, offset sth,0


         inc i 
         mov EAX,iloscLiczb
         cmp i,EAX
         jb wypisz1

invoke  CloseHandle,hfile

konWNDPROC:
pop EDI
pop ESI
pop EBX
pop EBP ; standardowy epilog
ret 16 ; zwolnienie komórek stosu
WndProc ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;--- start programu ---
Start:

;--- deskryptor aplikacji ----
INVOKE GetModuleHandleA, 0
mov hinst, EAX
;--- wypełnienie struktury okna WNDCLASS
mov EAX, hinst
mov [wndc.clsHInstance], EAX
mov [wndc.clsStyle], CSstyle
mov [wndc.clsLpfnWndProc], OFFSET WndProc
mov [wndc.clsCbClsExtra], 0
mov [wndc.clsCbWndExtra], 0
INVOKE LoadIconA, 0, IDI_APPLICATION ; ikona
mov [wndc.clsHIcon], EAX
INVOKE LoadCursorA, 0, IDC_ARROW ; kursor
mov [wndc.clsHCursor], EAX
INVOKE GetStockObject, WHITE_BRUSH ; tło
mov [wndc.clsHbrBackground], EAX
mov [wndc.clsLpszMenuName], 0
mov DWORD PTR [wndc.clsLpszClassName], OFFSET cname
;--- rejestracja okna ---

INVOKE RegisterClassA, OFFSET wndc
cmp EAX, 0
jne @F
jmp err0
@@:
;--- utworzenie okna głównego ---
INVOKE CreateWindowExA, 0, OFFSET cname, OFFSET tytul, \
WNDstyle, 40, 30, 500, 280, 0, 0, hinst, 0
cmp EAX, 0
jne @F
jmp err2
@@:
mov hwnd, EAX
INVOKE ShowWindow, hwnd, SW_SHOWNORMAL
INVOKE GetDC,hwnd
mov hdc,EAX


;naglowek
INVOKE lstrlenA,OFFSET naglow
mov rozmN,EAX
INVOKE TextOutA,hDC,120,20,OFFSET naglow,rozmN
INVOKE UpdateWindow, hwnd


;naglowek4
INVOKE lstrlenA,OFFSET naglow4
mov rozmN4,EAX
INVOKE TextOutA,hDC,10,40,OFFSET naglow4,rozmN4
INVOKE UpdateWindow, hwnd



;--- pętla obsługi komunikatów
msgloop:
INVOKE GetMessageA, OFFSET msg, 0, 0, 0
cmp EAX, 0
jne @F
jmp etkon
@@:
cmp EAX, -1
jne @F
jmp err0
@@:
INVOKE TranslateMessage, OFFSET msg
INVOKE DispatchMessageA, OFFSET msg
jmp msgloop
;--- obsługa błędów ---------
err0:
;--- okno z komunikatem o błędzie----
INVOKE MessageBoxA,0,OFFSET terr,OFFSET nagl,0
jmp etkon
err2:
;--- okno z komunikatem o błędzie----
INVOKE MessageBoxA,0,OFFSET terr2,OFFSET nagl,0
jmp etkon
;--- zakończenie procesu ---------
etkon:
INVOKE ExitProcess, [msg.msWPARAM]
_TEXT ENDS
END Start 
0

Pomóż sobie i nam trochę: odpal w ollydbg i klawiszami F7/F8 dojdź do momentu w którym się prox zawiesza i podaj tą funkcję/linijkę - będzie można Tobie dużo łatwiej/szybciej pomóc.

Teraz jestem świeżo po formacie, jak poinstaluje środowiska to może skompiluje twój prog.

0

Podaj z 5 linijek przed i po tym miejscu, postaraj się zaznaczyć gdzie to jest w twoim kodzi i przede wszystkim wartość eax i [eax] (pointer i co wskazuje z 10 bajtów wystarczy).

Prawdopodobnie wskaźnik ci uciekł i na jakiś chroniony fragment wskazuje.

0

w sumie mogę:
Proszę o:
-plik z kodem
-pliki na których program operuje
-plik ze skryptem od "kompilacji" (to co w konsoli wpisujesz zapisane jako plik textowy *.bat - być może tu tkwi problem).

0

plik komp.bat
@echo off
if exist %1%1.obj del %1%1.obj
if exist %1%1.exe del %1%1.exe
@echo %1%1
.\bin\ml /c /coff /Cp /Cx /Fo.%1%1.obj /Fl.%1%1.lst /Zi /Zd .%1%1.asm

plik kons.bat
.\BIN\link /SUBSYSTEM:CONSOLE /LIBPATH:.\LIB /OUT:.%1%1.exe /MAP:.%1%1.map /PDB:.%1%1.pdb .%1%1.obj

http://chomikuj.pl/kamilzuk24/Dokumenty/ASM,428670870.rar

a tutaj cały folder z programem

0

W tym miejscu [CIACH!] stos

 
        @koniec3:
            push    OFFSET liczba
            call    ScanInt

W wyniku tego retem wpierdalasz sie zamiast w wyjście poprzedniego calla na offset liczby

    ;--- powrót
            pop        EBP
            ret ;<-----daj tu  'ret 4' zamiast ret  i zalatasz tego buga
    ScanInt        ENDP

Nie chciało mi się kompilować a to się w oczy rzucało.

0

hmmm chyba nie skmyniłeś jak działa wsprinf albo nie dałeś całego kodu - w tym co tu podałeś nie masz nic co by chociaż próbowało w konsoli coś pisać.

Ps. Pokasuje te posty pod postami bo cie amin ochrzani :)

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