Я полный новичок в программировании на ассемблере. Мне нужна помощь в написании программы на ассемблере, чтобы получить строку от пользователя, подсчитать и отобразить количество раз, когда каждое слово встречается в введенной пользователем строке.
Например, если пользователь вводит:
Hello Hello what is new Hello what is not new
Вывод должен быть:
Hello 3
what 2
is 2
not 1
new 2
У меня есть следующий код ниже, который даст мне частоту символов в строке. Однако я не знаю, как редактировать, чтобы отслеживать слова, а не только символы, а затем отображать эти слова с соответствующей частотой.
INCLUDE Irvine32.inc
Get_frequencies PROTO,
pString:PTR BYTE, ; points to string
pTable:PTR DWORD ; points to frequency table
.data
freqTable DWORD 256 DUP(0)
;aString BYTE 1,2,"This is extremely difficult for the experienced",0
aString BYTE 80 DUP(0),0
str1 BYTE "*** Constructing a Frequency Table *** (DEMO)",
0dh,0ah,0dh,0ah,
"Enter between 1 and 80 characters: ",0
.code
main PROC
call Clrscr
mov edx,OFFSET str1
call WriteString
mov ecx,SIZEOF aString - 1
mov edx,OFFSET aString
call ReadString
INVOKE Get_frequencies, ADDR aString, ADDR freqTable
call DisplayTable
exit
main ENDP
;-------------------------------------------------------------
Get_frequencies PROC,
pString:PTR BYTE, ; points to string
pTable:PTR DWORD ; points to frequencey table
;
; Constructs a character frequency table. Each array position
; is indexed by its corresponding ASCII code.
;
; Returns: Each entry in the table contains a count of how
; many times that character occurred in the string.
;-------------------------------------------------------------
mov esi,pString
mov edi,pTable
cld ; clear Direction flag (forward)
L1: mov eax,0 ; clear upper bits of EAX
lodsb ; AL = [ESI], inc ESI
cmp al,0 ; end of string?
je Exit_proc ; yes: exit
shl eax,2 ; multiply by 4
inc DWORD PTR [edi + eax] ; inc table[AL]
jmp L1 ; repeat loop
Exit_proc:
ret
Get_frequencies ENDP
;-------------------------------------------------------------
DisplayTable PROC
;
; Display the non-empty entries of the frequency table.
; This procedure was not required, but it makes it easier
; to demonstrate that Get_frequencies works.
;-------------------------------------------------------------
.data
colonStr BYTE ": ",0
.code
call Crlf
mov ecx,LENGTHOF freqTable ; entries to show
mov esi,OFFSET freqTable
mov ebx,0 ; index counter
L1: mov eax,[esi] ; get frequency count
cmp eax,0 ; count = 0?
jna L2 ; if so, skip to next entry
mov eax,ebx ; display the index
call WriteChar
mov edx,OFFSET colonStr ; display ": "
call WriteString
mov eax,[esi] ; show frequency count
call WriteDec
call Crlf
L2: add esi,TYPE freqTable ; point to next table entry
inc ebx ; increment index
loop L1
call Crlf
ret
DisplayTable ENDP
END main
Это то, что у меня есть до сих пор в моей попытке реализовать поиск грубой силы, предложенный в ответе Питера:
.data
str2 BYTE "one two three",0
.code
main proc
mov edi,OFFSET str2
Mov esi,edi
Mov Ecx, 0 ;reset ecx to 0
Not Ecx ;set Ecx to -1 or highest possible integer
Mov Al, ' ' ;Initialize a1 to delimiter of (space) ' '
Cld ;Clear Direction Pointer
Repne Scasb ;scan edi one byte at a time until delimiter found
Not Ecx
Lea Eax, [ecx-1] ;Set Eax to index of found delimiter
Xchg Esi, Edi ;Take Edi which is now equal to string after found delimiter and put in esi
mov edx, esi
call WriteString
main endp
end main
Это печатает «два три», но я хочу, чтобы он печатал «один».
WriteString
. Вот почему он печатает остальную часть строки. Это говорит о том, что ваш код работал и остановился после первого слова. Какие аргументы принимаетWriteString
? Я никогда не использовал Irvine32. Если для этого требуется указатель и длина, вы сможете его использовать. В противном случае, если он просто печатает до 0-терминатора, вы не можете использовать его таким образом. (Вы можете заменить' '
разделителем'\0'
, но это имеет значение только для отладочной печати.) - person Peter Cordes   schedule 21.05.2016mov ecx, -1
не вести себя как нормальный человек? Вы бы использовали толькоnot ecx
илиdec ecx
для экономии байтов при генерации -1, выполнивxor ecx,ecx / dec ecx
(всего 3 байта в 32-битном коде, 4 байта в 64-битном коде) вместоmov ecx, -1
(5 байт). Кстати, я проверил, иWriteString
просто печатает строку с завершающим нулем, переданную вedx
. Я не знал, почему ты что-то вычисляешь вeax
. Кстати, полезно сохранить длину слова для будущих циклов илиrep cmpsb
. (например,mov eax, ecx
/neg eax
, если только у меня нет ошибки "один на один".) Интересен не индекс разделителя. - person Peter Cordes   schedule 21.05.2016