Witam,mam za zadanie zsumować elementy tablicy w asemblerze.Oto mój kod:
;Aplikacja korzystająca z otwartego okna konsoli
.386
.MODEL flat, STDCALL
;--- stale ---
STD_INPUT_HANDLE equ -10
STD_OUTPUT_HANDLE equ -11
;--- funkcje API Win32 ---
;--- z pliku user32.inc ---
CharToOemA PROTO :DWORD,:DWORD
;--- z pliku kernel32.inc ---
GetStdHandle PROTO :DWORD
ReadConsoleA PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD
WriteConsoleA PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD
ExitProcess PROTO :DWORD
wsprintfA PROTO C :VARARG
lstrlenA PROTO :DWORD
;-------------
includelib .\lib\user32.lib
includelib .\lib\kernel32.lib
;-------------
_DATA SEGMENT
hout DD ?
hinp DD ?
naglow DB "Autor aplikacji Jan Masztalski.",0
ALIGN 4 ; przesuniecie do adresu podzielnego na 4
rozmN DD $ - naglow ;liczba znaków w tablicy
zaprA DB 0Dh,0Ah,"Proszę wprowadzić kolejną liczbę: ",0
ALIGN 4
rozmA DD $ - zaprA ;liczba znaków w tablicy
zaprB DB 0Dh,0Ah,"Suma wprowadzonych liczb wynosi: ",0
ALIGN 4
rozmB DD $ - zaprB ;liczba znaków w tablicy
ALIGN 4
rout DD 0 ;faktyczna liczba wyprowadzonych znaków
rinp DD 0 ;faktyczna liczba wprowadzonych znaków
lZnakow DD 0
bufor DB 128 dup(?)
rbuf DD 128
liczby DB 10 dup(?)
rLiczby DD 10
_DATA ENDS
;------------
_TEXT SEGMENT
start:
;--- wywołanie funkcji GetStdHandle
push STD_OUTPUT_HANDLE
call GetStdHandle ; wywołanie funkcji GetStdHandle
mov hout, EAX ; deskryptor wyjściowego bufora konsoli
push STD_INPUT_HANDLE
call GetStdHandle ; wywołanie funkcji GetStdHandle
mov hinp, EAX ; deskryptor wejściowego bufora konsoli
;--- nagłówek ---------
push OFFSET naglow
push OFFSET naglow
call CharToOemA ; konwersja polskich znaków
;--- wyświetlenie ---------
push 0 ; rezerwa, musi być zero
push OFFSET rout ; wskaźnik na faktyczną liczba wyprowadzonych znaków
push rozmN ; liczba znaków
push OFFSET naglow ; wskażnik na tekst
push hout ; deskryptor buforu konsoli
call WriteConsoleA ; wywołanie funkcji WriteConsoleA
;--- zaproszenie A ---------
push OFFSET zaprA
push OFFSET zaprA
call CharToOemA ; konwersja polskich znaków
cld ;wyzerowanie flagi kierunku
mov EDI, OFFSET liczby ; pod tym adresem umieścimy wczytane liczby
mov ecx, 10
petla:
push ecx
;--- wyświetlenie zaproszenia A ---
push 0 ; rezerwa, musi być zero
push OFFSET rout ; wskaźnik na faktyczną liczba wyprowadzonych znaków
push rozmA ; liczba znaków
push OFFSET zaprA ; wskażnik na tekst
push hout ; deskryptor buforu konsoli
call WriteConsoleA ; wywołanie funkcji WriteConsoleA
;--- czekanie na wprowadzenie znaków, koniec przez Enter ---
push 0 ; rezerwa, musi być zero
push OFFSET rinp ; wskaźnik na faktyczną liczba wprowadzonych znaków
push rbuf ; rozmiar bufora
push OFFSET bufor ;wskażnik na bufor
push hinp ; deskryptor buforu konsoli
call ReadConsoleA ; wywołanie funkcji ReadConsoleA
lea EBX,bufor
mov EDX,rinp
mov BYTE PTR [EBX+EDX-2],0 ;zero na końcu tekstu
;--- przekształcenie A
push OFFSET bufor
call ScanInt ;pobraną liczbę mamy teraz w akumulatorze
stosb ; i przesyłamy ją do pamięci w miejce wskazywane przez EDI (po operacji edi zwiększany automatycznie o 1)
pop ecx
loop petla
mov eax,0
;ToDo - wykonaj stosowne obliczenia (wynik ma być zwrócowny w eax)
mov ebx,0
cld
mov esi,OFFSET liczby
mov ecx,lengthof liczby ; loop counter
L1: lodsb ; copy [ESI] into AL
add ebx, eax
loop L1
mov eax, ebx
;--- wyprowadzenie wyniku obliczeń ---
push EAX
push OFFSET zaprB
push OFFSET bufor
call wsprintfA ; zwraca liczbę znaków w buforze
add ESP, 12 ; czyszczenie stosu
mov rinp, EAX ; zapamiętywanie liczby znaków
;--- wyświetlenie wyniku ---------
push 0 ; rezerwa, musi być zero
push OFFSET rout ; wskaźnik na faktyczną liczbę wyprowadzonych znaków
push rinp ; liczba znaków
push OFFSET bufor ; wskaźnik na tekst w buforze
push hout ; deskryptor buforu konsoli
call WriteConsoleA ; wywołanie funkcji WriteConsoleA
;--- zakończenie procesu ---------
push 0
call ExitProcess ; wywołanie funkcji ExitProcess
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
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 ;liczba znaków
mov ECX, EAX ;liczba powtórzeń = liczba znaków
xor ESI, ESI ; wyzerowanie ESI
xor EDX, EDX ; wyzerowanie EDX
xor EAX, EAX ; wyzerowanie EAX
mov EBX, [EBP+8] ; adres tekstu
;--- cykl --------------------------
pocz:
cmp BYTE PTR [EBX+ESI], 0h ;porównanie z kodem \0
jne @F
jmp et4
@@:
cmp BYTE PTR [EBX+ESI], 0Dh ;porównanie z kodem CR
jne @F
jmp et4
@@:
cmp BYTE PTR [EBX+ESI], 0Ah ;porównanie z kodem LF
jne @F
jmp et4
@@:
cmp BYTE PTR [EBX+ESI], 02Dh ;porównanie z kodem -
jne @F
mov EDX, 1
jmp nast
@@:
cmp BYTE PTR [EBX+ESI], 030h ;porównanie z kodem 0
jae @F
jmp nast
@@:
cmp BYTE PTR [EBX+ESI], 039h ;porównanie z kodem 9
jbe @F
jmp nast
;----
@@:
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 @F
neg EAX
@@:
et4:;--- zdejmowanie ze stosu
pop EDI
pop ESI
pop EDX
pop ECX
pop EBX
;--- powrót
mov ESP, EBP ; przywracamy wskaźnik stosu ESP
pop EBP
ret 4
ScanInt ENDP
_TEXT ENDS
END start
Chodzi mi dokładnie o tą część:
mov ebx,0
cld
mov esi,OFFSET liczby
mov ecx,lengthof liczby ; loop counter
L1: lodsb ; copy [ESI] into AL
add ebx, eax
loop L1
mov eax, ebx
Z góry dzięki za pomoc
<code></code=asm>
? Wpisując kod znaczniki mają mieć postać<code=asm></code>
:)