2015-05-21 10 views
5

Próbuję policzyć wystąpienia znaków w ciągu znaków. Moje kodu jest poniżej:Zliczanie częstotliwości znaków w tablicy znaków - Zgromadzenie x86

data segment 'DSEG' 
    text  db "This is a sentence.",0  ; string 
    textSize dw $ - text - 1    ; size of string, - 1 to account for null-termination character 
    freqTable dd 256 DUP(0) 
ends 'DSEG' 

code segment 'CSEG' 
start:       
mov ax, data  ; set segment registers 
mov ds, ax 
mov es, ax 
;--------------------------------------- 

sub cx, cx 
mov cx, textSize  ; number of times to loop 
L1: 
    mov ax, [OFFSET text + cx - 1] ; loop from back using cx, put character in ax 
    inc [OFFSET freqTable + 4*ax] ; increment table's index at the ascii value of character 
    LOOP L1 

;--------------------------------------- 
mov ax, 4c00h  ; return to OS 
int 21h 

ends 'CSEG' 
end start   ; set entry point 

zrobiłem tablicę DWORDS gdzie każdy indeks będzie reprezentować znak. Następnie przechodzę przez pętlę i próbuję zwiększyć tablicę przy wartości ascii każdego znaku.

Jednak otrzymuję błąd wrong parameters podczas próby zwiększenia pętli. Nie jestem pewien, co powoduje ten błąd. Zgaduję, że nie mogę po prostu zwiększyć tego, jak próbuję. Jak prawidłowo utworzyć tabelę częstotliwości? Czy brakuje mi czegoś małego?

+2

@jacksonblackson Nie rozumiem, co masz na myśli, mówiąc: "Szukając odpowiedzi z wiarygodnych i/lub oficjalnych źródeł". Odpowiedź udzielona przez SepRoland doskonale odpowiedziała na to pytanie! – Fifoernik

Odpowiedz

2

Aby pomóc ci zrozumieć, jak policzyć znaki, stworzyłem następny mały program z EMU8086 (kompatybilny z twoim zestawem): program prosi użytkownika o nazwę pliku, otwiera plik, czyta wszystkie znaki i policzy je, i zamyka plik .

Następne zdjęcie pokazuje, jak to działa: istnieje szereg częstotliwości ("freq_array") z 256 pozycjami. Każda pozycja jest konturem odpowiedniego znaku, na przykład pozycja 65 jest licznikiem dla "A" (chr (65)).

enter image description here

Everytime jeden char jest czytany z pliku, sam znak jest używany jako przesunięcie, aby osiągnąć swój licznik. Na przykład, jeśli znak 48 ("0") zostanie odczytany z pliku, liczba 48 zostanie dodana do przesunięcia macierzy (przesunięcie + 48), a pozycja ta zostanie zwiększona. Kiedy plik się kończy, wszystkie jego znaki zostały policzone.

Teraz kod:

.model small 
.stack 100h 

;----------------------------------------- 

.data 

freq_array dw 256 dup(0) ;ARRAY OF FREQUENCIES OF EACH ASCII CHARACTER. 

msj   db 13,10,'Enter name of file: $' 

filename  db 99  ;MAX NUMBER OF CHARACTERS ALLOWED (98). 
      db ?   ;LENGTH (NUMBER OF CHARACTERS ENTERED BY USER). 
      db 99 dup(0) ;CHARACTERS ENTERED BY USER. END WITH CHR(13). 

filehandler dw ?   ;FILE HANDLER. 

the_char  db ?   ;CHAR READ FROM FILE. 

;----------------------------------------- 

.code 
start: 

;INITIALIZE DATA SEGMENT. 
    mov ax, @data 
    mov ds, ax     

    call get_source_file  ;GET FILE NAME. 
    call count_chars   ;FILL FREQ_ARRAY WITH FREQUENCIES OF CHARS. 

;WAIT FOR ANY KEY.  
    mov ah, 7 
    int 21h 

;FINISH PROGRAM. 
    mov ax, 4c00h 
    int 21h 

;----------------------------------------- 

get_source_file proc 
;DISPLAY MESSAGE. 
    mov dx, offset msj 
    mov ah, 9 
    int 21h  

;CAPTURE FILENAME FROM KEYBOARD.          
    mov ah, 0Ah 
    mov dx, offset filename 
    int 21h     

;CAPTURED STRING ENDS WITH CHR(13), BUT FILES REQUIRE 
;THE FILENAME TO END WITH CHR(0), SO LET'S CHANGE IT. 
    mov si, offset filename + 1 ;STRING LENGTH. 
    mov cl, [ si ]  ;MOVE LENGTH TO CL. 
    mov ch, 0    ;CLEAR CH TO USE CX. 
    inc cx    ;ONE MORE BYTE TO REACH CHR(13). 
    add si, cx   ;NOW SI POINTS TO CHR(13). 
    mov al, 0 
    mov [ si ], al  ;REPLACE CHR(13) BY 0. 

    ret 
get_source_file endp 

;----------------------------------------- 
;READ ALL CHARACTERS FROM FILE INCREASING THE COUNTER OF 
;EACH CHARACTER IN THE ARRAY OF FREQUENCIES. EACH CHARACTER 
;IS USED AS THE OFFSET OF ITS OWN COUNTER, EXAMPLE: THE 
;COUNTER FOR 'A' IS THE POSITION 65 OF FREQ_ARRAY. 

count_chars proc 
;OPEN FILE. 
    mov ah, 3dh   ;SERVICE TO OPEN FILE. 
    mov al, 0   ;OPEN AS READ ONLY. 
    mov dx, offset filename + 2 
    int 21h 
    mov filehandler, ax ;NECESSARY FOR OPERATIONS ON FILE. 

;COUNT CHARACTERS. 
reading: 
;READ ONE CHAR FROM FILE. 
    mov ah, 3fh   ;SERVICE TO READ FROM FILE. 
    mov bx, filehandler 
    mov cx, 1   ;HOW MANY BYTES TO READ. 
    mov dx, offset the_char ;WHERE TO STORE THE READ BYTES. 
    int 21h    

;CHECK END OF FILE. 
    cmp ax, 0 
    je end_reading  ;IF READ ZERO BYTES, FINISH. 

;INCREASE COUNTER. THE CHAR ITSELF IS BEEN USED AS INDEX: THE 
;COUNTER FOR CHAR 65 ('A') IS IN THE 65th POSITION OF THE ARRAY. 
    mov si, offset freq_array 
    mov al, the_char  ;USE CHAR AS OFFSET OF ITS OWN COUNTER. 
    mov ah, 0   ;CLEAR AH TO USE AX. 
    shl ax, 1   ;AX * 2, BECAUSE EVERY COUNTER IS 2 BYTES. 
    add si, ax   ;SI POINTS TO COUNTER POSITION. 
    inc [ word ptr si ] ;INCREMENT COUNTER FOR CURRENT CHAR. 
    jmp reading   ;REPEAT PROCESS. 

end_reading:   
;CLOSE FILE. 
    mov ah, 3eh   ;SERVICE TO CLOSE FILE. 
    mov bx, filehandler 
    int 21h 

    ret 
count_chars endp 

;----------------------------------------- 

end start 

Nadzieja to pomóc.

Jest to 16 bitów, ponieważ tablica jest DW. Aby był on zgodny z 32 bitów (array DD), zmień następujące linie:

freq_array dd 256 dup(0) 

shl ax, 2    ;AX * 4, BECAUSE EVERY COUNTER IS 4 BYTES. 

inc [ dword ptr si ] ;INCREMENT COUNTER FOR CURRENT CHAR. 
5

X86 nie pozwala na adresowanie pamięci dzięki zastosowaniu AX i CX rejestruje jak ty. Możesz jednak użyć EAX i ECX do tego celu.
Troughout kolejne bity fragmentów kodu EAX [8,31] i ECX [16,31] pozostaną niezmienione.

Powiązane problemy