TASM - 92
**Error** q178239.ASM(186) Symbol already defined elsewhere: @@NEXT
**Error** q178239.ASM(193) Relative jump out of range by 004Bh bytes
**Error** q178239.ASM(199) Symbol already defined elsewhere: @@NEXT
**Error** q178239.ASM(206) Relative jump out of range by 0059h bytes
LEN_DELIM equ $-delimiters
delimiters db 9, ' .,;:!?-'
20 0106 09 20 2E 2C 3B 3A 21+ delimiters db 9, ' .,;:!?-' ; массив разделителей слов
21 3F 2D
22 = 0009 LEN_DELIM equ $-delimiters
msgEnterWords db 13,10,'Enter several words: $'
msgLimit db 13,10,'Too many words in the input string.$'
msgNoWords db 13,10,'No words found in the input string.$'
msgExit db 13,10,10, 'Press any key to exit...$'
msgResult db 13,10,'Result:',13,10,'$'
Если не сложно можно поправить программу под ехе
1. что значит а)locals @@
б)LEN_DELIM equ $-delimiters
что значит это: MAX_WORDS*2
что значит запись типа mov [wordlen][bx],ax
i-e и j-e слово это какое ?
3. у нас есть несколько меток с одним именем к примеру @@next. как определить к какой из них идет переход ?
4. Пожалуйста если можно максимально упростите программу написана она у вас сложно (для меня). для этого можно убрать кое - что "лишнее"
-пропуск разделителей и слова (если это нужно то зачем?)
5. Если не сложно можно поправить программу под ехе (если это не усложнит ее)
убрать везде @@
Складывается впечатление, что Вы совершенно не знаете ассемблер.
Извиняюсь что столько много вопросов просто мне надо сдать эту программу полностью все разобрав
Складывается впечатление, что Вы совершенно не знаете ассемблер.
с моей точки зрения, в программе нет ничего лишнего
mov ax,@data
mov ES,ax ; DS установлен директивой .startup
1 55 0000 @Startup:
1 56 0000 BA 0000s MOV DX,@data
1 57 0003 8E DA MOV DS,DX
1 58 0005 8C D3 MOV BX,SS
1 59 0007 2B DA SUB BX,DX
1 60 0009 D1 E3 SHL BX,1
1 61 000B D1 E3 SHL BX,1
1 62 000D D1 E3 SHL BX,1
1 63 000F D1 E3 SHL BX,1
1 64 0011 FA CLI
1 65 0012 8E D2 MOV SS,DX
1 66 0014 03 E3 ADD SP,BX
1 67 0016 FB STI
[q=245680]и еще вопрос почему мы счетчик два раза инкрементируем ?
inc (si) | inc (di) | inc(bx)
inc (si) | inc(di) | inc(bx)
1 ; Вопрос № 178239
2 ; написать программу, которая объединяет слова, начинающиеся на один и
3 ; тот же символ и дописывает его (объединенное слово) в конец строки.
4 ; Результат вывести на экран. Слова вводить с клавиатуры.
5 ; Пример:
6 ; waba wordos absen ; вводим исходную строку
7 ; waba wordos absen wabawordos ; то что должно получиться
8 ; Платформа Dos, ассемблер TASM, процессор 8086
9
10 locals @@
11 0000 model small;tiny
12
13 0000 .data
14
15 0000 78 bufInput db 120 ; размер буфера
16 0001 00 lenInput db 0 ; длина введенной строки
17 0002 0104*(00) szInput db 260 dup(0) ; сюда будет помещена введенная строка,
18 ; а затем к концу будут присоединены объединенные слова (260=120*2+20)
19
20 0106 09 20 2E 2C 3B 3A 21+ delimiters db 9, ' .,;:!?-' ; массив разделителей слов
21 3F 2D
22 = 0009 LEN_DELIM equ $-delimiters
23
24 = 0014 MAX_WORDS equ 20 ; разрешаем до 20-ти слов
25 010F 14*(0000) wordptr dw MAX_WORDS dup(0) ; массив указателей на слова
26 0137 14*(0000) wordlen dw MAX_WORDS dup(0) ; массив длин слов
27 015F 14*(00) b_out db MAX_WORDS dup(0) ; массив признаков "слово выведено"
28 0173 0000 endptr dw 0 ; указатель на конец строки
29
30 0175 0D 0A 45 6E 74 65 72+ msgEnterWords db 13,10,'Enter several words: $'
31 20 73 65 76 65 72 61+
32 6C 20 77 6F 72 64 73+
33 3A 20 24
34 018D 0D 0A 54 6F 6F 20 6D+ msgLimit db 13,10,'Too many words in the input string.$'
35 61 6E 79 20 77 6F 72+
36 64 73 20 69 6E 20 74+
37 68 65 20 69 6E 70 75+
38 74 20 73 74 72 69 6E+
39 67 2E 24
40 01B3 0D 0A 4E 6F 20 77 6F+ msgNoWords db 13,10,'No words found in the input string.$'
41 72 64 73 20 66 6F 75+
42 6E 64 20 69 6E 20 74+
43 68 65 20 69 6E 70 75+
44 74 20 73 74 72 69 6E+
45 67 2E 24
46 01D9 0D 0A 0A 50 72 65 73+ msgExit db 13,10,10, 'Press any key to exit...$'
47 73 20 61 6E 79 20 6B+
48 65 79 20 74 6F 20 65+
49 78 69 74 2E 2E 2E 24
50 01F5 0D 0A 52 65 73 75 6C+ msgResult db 13,10,'Result:',13,10,'$'
51 74 3A 0D 0A 24
52
53 0201 .code
54 .startup
1 55 0000 @Startup:
1 56 0000 BA 0000s MOV DX,@data
1 57 0003 8E DA MOV DS,DX
1 58 0005 8C D3 MOV BX,SS
1 59 0007 2B DA SUB BX,DX
1 60 0009 D1 E3 SHL BX,1
1 61 000B D1 E3 SHL BX,1
1 62 000D D1 E3 SHL BX,1
1 63 000F D1 E3 SHL BX,1
1 64 0011 FA CLI
1 65 0012 8E D2 MOV SS,DX
1 66 0014 03 E3 ADD SP,BX
1 67 0016 FB STI
68 ; выводим пригласительное сообщение
69 0017 B4 09 mov ah,9 ; вывод строки на экран
70 0019 BA 0175r mov dx,offset msgEnterWords ; смещение выводимой строки
71 001C CD 21 int 21h
72
73 001E B4 0A mov ah,0Ah ; ввод строки с клавиатуры
74 0020 BA 0000r mov dx,offset bufInput ; смещение буфера
75 0023 CD 21 int 21h
76
77 ; в цикле разбираем строку и сохраняем указатели на начала слов и длины слов
78 0025 33 DB xor bx,bx ; счетчик слов * 2
79 0027 32 ED xor ch,ch
80 0029 8A 0E 0001r mov cl,[lenInput] ; CX = длина введенной строки
81 002D E3 2F jcxz @@no_words
82 002F FC cld
83 0030 BE 0002r mov si,offset szInput ; смещение введенной строки
84 0033 @@next:
85 0033 E8 00BB call skip_delimiters ; пропускаем разделители
86 0036 E3 22 jcxz @@str_end
87 0038 83 FB 28 cmp bx,MAX_WORDS*2 ; проверяем на переполнение
88 003B 72 05 jb @@ok
89 003D BA 018Dr mov dx,offset msgLimit ; слишком много слов
90 0040 EB 1F jmp short @@msg
91 0042 @@ok:
92 0042 8B D6 mov dx,si
93 0044 4A dec dx
94 0045 89 97 010Fr mov [wordptr][bx],dx ; сохраняем указатель на слово
95
96 0049 E8 00B3 call read_word ; пропускаем слово
97 004C 8B C6 mov ax,si
98 004E 2B C2 sub ax,dx
99 0050 89 87 0137r mov [wordlen][bx],ax ; сохраняем длину слова
100 0054 43 inc bx ; увеличиваем счетчик (*2)
101 0055 43 inc bx
102 0056 85 C9 test cx,cx ; здесь нельзя использовать loop, поскольку CX
103 0058 75 D9 jnz @@next ; может быть равно 0. Кроме того, здесь нельзя уменьшать CX.
104
105 005A @@str_end:
106 ; обработка и вывод результатов
107
108 005A 85 DB test bx,bx ; вообще, хоть одно слово было введено?
109 005C 75 07 jnz @@process
110 005E @@no_words:
111 005E BA 01B3r mov dx,offset msgNoWords ; смещение выводимой строки
112 0061 @@msg:
113 0061 B4 09 mov ah,9 ; вывод строки на экран
114 0063 EB 7C jmp short @@exit
115
116 0065 @@process:
117 0065 8D AF 010Dr lea bp,[wordptr-2][bx] ; BP = указатель на конец заполненной части массива
118 0069 89 36 0173r mov [endptr],si ; текущий указатель на конец строки
119
120 ; Приблизительный алгоритм поиска:
121 ; for( i=0; i < wordcount-1; ++i )
122 ; if( i-тое слово не было выведено ) {
123 ; for( j=i+1; j < wordcount; ++j )
124 ; if( wordptr[i][0] == wordptr[j][0] )
125 ; присоединить слово
126 ; }
127
128 006D BE 010Fr mov si,offset wordptr ; SI = адрес wordptr[i] (i=0)
129 0070 BB 015Fr mov bx,offset b_out
130
131 0073 @@loop_i:
132 0073 80 3F 00 cmp byte ptr [bx],0 ; очередное слово уже было выведено?
133 0076 75 51 jnz @@next_i ; да, идем к следующему
134 ; нет, сканируем остаток
135
136 0078 53 push bx ; сохраняем адрес b_out[i]
137 0079 8B D3 mov dx,bx
138 007B B4 00 mov ah,0 ; флаг: i-тое слово еще не добавлено в конец
139 007D 8B 1C mov bx,[si] ; BX = указатель на начало слова[i]
140 007F 8A 07 mov al,[bx] ; первый символ слова
141
142 0081 8B FE mov di,si ; DI = адрес wordptr[j]
143 0083 47 inc di
144 0084 47 inc di
145 0085 42 inc dx ; DX = адрес b_out[j]
146 0086 @@loop_j:
147 0086 8B 1D mov bx,[di] ; BX = указатель на начало слова [j]
148 0088 3A 07 cmp al,[bx] ; сравниваем первые символы слов
149 008A 75 35 jne @@next_j ; они не будут равны, если j-тое слово уже было +
150 добавлено
151
152 008C 84 E4 test ah,ah ; i-тое слово уже было добавлено?
153 008E 75 19 jne @@out
154 ; нет, добавляем
155 0090 57 push di
156 0091 56 push si
157 0092 8B 3E 0173r mov di,[endptr] ; указатель на конец строки
158 0096 C6 05 20 mov byte ptr [di],' ' ; не забудем про разделитель
159 0099 47 inc di
160 009A 8B 4C 28 mov cx,[si+MAX_WORDS*2] ; длина i-того слова
161 009D 8B 34 mov si,[si] ; адрес i-того слова
162 009F F3> A4 rep movsb ; копируем слово
163 00A1 89 3E 0173r mov [endptr],di ; сохраняем указатель на конец строки
164 00A5 5E pop si
165 00A6 5F pop di
166 00A7 B4 01 mov ah,1 ; i-тое слово добавлено в строку
167
168 00A9 @@out: ; добавляем j-тое слово
169 00A9 57 push di
170 00AA 56 push si
171 00AB 8B 4D 28 mov cx,[di+MAX_WORDS*2]
172 00AE 8B 35 mov si,[di]
173 00B0 8B 3E 0173r mov di,[endptr]
174 00B4 F3> A4 rep movsb
175 00B6 89 3E 0173r mov [endptr],di
176 00BA 5E pop si
177 00BB 5F pop di
178
179 00BC 8B DA mov bx,dx
180 00BE C6 07 01 mov byte ptr [bx],1 ; устанавливаем флаг: j-тое слово использовано
181 00C1 @@next_j:
182 00C1 42 inc dx ; продвигаем указатели, соответствующие j
183 00C2 47 inc di
184 00C3 47 inc di
185 00C4 3B FD cmp di,bp
186 00C6 76 BE jbe @@loop_j
187
188 00C8 5B pop bx ; адрес b_out[i]
189 00C9 @@next_i:
190 00C9 43 inc bx ; продвигаем указатели, соответствующие i
191 00CA 46 inc si
192 00CB 46 inc si
193 00CC 3B F5 cmp si,bp
194 00CE 72 A3 jb @@loop_i
195
196 ; выводим результат
197 00D0 8B 1E 0173r mov bx,[endptr]
198 00D4 C6 07 24 mov byte ptr [bx],'$' ; помещаем терминатор строки '$' в буфер
199
200 00D7 B4 09 mov ah,9 ; вывод строки на экран
201 00D9 BA 01F5r mov dx,offset msgResult ; переходим на новую строку
202 00DC CD 21 int 21h
203 00DE BA 0002r mov dx,offset szInput ; смещение нашей результирующей строки
204 00E1 @@exit:
205 00E1 CD 21 int 21h
206
207 00E3 BA 01D9r mov dx,offset msgExit ; смещение выводимой строки
208 00E6 CD 21 int 21h
209
210 00E8 32 E4 xor ah,ah ; ждем нажатия любой клавиши (чтобы увидеть результат,
211 00EA CD 16 int 16h ; прежде чем консоль в Windows закроется)
212
213 00EC B8 4C00 mov ax,4C00h ; завершаем программу с нулевым кодом
214 00EF CD 21 int 21h
215
216 ; пропуск разделителей
217 00F1 skip_delimiters proc
218 00F1 @@next:
219 00F1 51 push cx
220 00F2 AC lodsb
221 00F3 B9 0009 mov cx,LEN_DELIM
222 00F6 BF 0106r mov di,offset delimiters
223 00F9 F2> AE repne scasb
224 00FB 59 pop cx
225 00FC E1 F3 loope @@next ; пропускаем разделители
226 00FE C3 ret
227 00FF skip_delimiters endp
228
229 ; пропуск слова
230 00FF read_word proc
231 00FF @@next:
232 00FF 51 push cx
233 0100 AC lodsb
234 0101 B9 0009 mov cx,LEN_DELIM
235 0104 BF 0106r mov di,offset delimiters
236 0107 F2> AE repne scasb
237 0109 59 pop cx
238 010A E0 F3 loopne @@next ; пропускаем, пока не встретим разделитель
239 010C 75 02 jne @@ret ; эта проверка важна для последнего введенного слова
240 010E 4E dec si
241 010F 41 inc cx
242 0110 C3 @@ret: ret
243 0111 read_word endp
244
245 end
Symbol Name Type Value
??DATE Text "05/07/10"
??FILENAME Text "q178239 "
??TIME Text "20:17:16"
??VERSION Number 0200
@@EXIT Near _TEXT:00E1
@@LOOP_I Near _TEXT:0073
@@LOOP_J Near _TEXT:0086
@@MSG Near _TEXT:0061
@@NEXT Near _TEXT:00FF
@@NEXT Near _TEXT:0033
@@NEXT Near _TEXT:00F1
@@NEXT_I Near _TEXT:00C9
@@NEXT_J Near _TEXT:00C1
@@NO_WORDS Near _TEXT:005E
@@OK Near _TEXT:0042
@@OUT Near _TEXT:00A9
@@PROCESS Near _TEXT:0065
@@RET Near _TEXT:0110
@@STR_END Near _TEXT:005A
@CODE Text _TEXT
@CODESIZE Text 0
@CPU Text 0101H
@CURSEG Text _TEXT
@DATA Text DGROUP
@DATASIZE Text 0
@FILENAME Text Q178239
@MODEL Text 2
@STARTUP Near _TEXT:0000
@WORDSIZE Text 2
BUFINPUT Byte DGROUP:0000
B_OUT Byte DGROUP:015F
DELIMITERS Byte DGROUP:0106
ENDPTR Word DGROUP:0173
LENINPUT Byte DGROUP:0001
LEN_DELIM Number 0009
MAX_WORDS Number 0014
MSGENTERWORDS Byte DGROUP:0175
MSGEXIT Byte DGROUP:01D9
MSGLIMIT Byte DGROUP:018D
MSGNOWORDS Byte DGROUP:01B3
MSGRESULT Byte DGROUP:01F5
READ_WORD Near _TEXT:00FF
SKIP_DELIMITERS Near _TEXT:00F1
SZINPUT Byte DGROUP:0002
WORDLEN Word DGROUP:0137
WORDPTR Word DGROUP:010F
Groups & Segments Bit Size Align Combine Class
DGROUP Group
_DATA 16 0201 Word Public DATA
_TEXT 16 0111 Word Public CODE
Это не спасает от предупреждения линковщика
Об отсутсвии стека.
И ещё .startup сама все делает:
; в цикле разбираем строку и сохраняем указатели на начала слов и длины слов
xor bx,bx ; счетчик слов * 2
xor ch,ch
mov cl,[lenInput] ; CX = длина введенной строки
jcxz @@no_words
@@next:
call skip_delimiters ; пропускаем разделители
jcxz @@str_end
cmp bx,MAX_WORDS*2 ; проверяем на переполнение
jb @@ok
mov dx,offset msgLimit ; слишком много слов
jmp short @@msg
@@ok:
; обработка и вывод результатов
test bx,bx ; вообще, хоть одно слово было введено?
jnz @@process
@@no_words:
xor ah,ah ; ждем нажатия любой клавиши (чтобы увидеть результат,
int 16h ; прежде чем консоль в Windows закроется)
там больше нечего упрощать.
т.е. после 2 суток я не смогу здесь больше ничего спрашивать?
Если Вы уже зарегистрированы на Портале - войдите в систему, если Вы еще не регистрировались - пройдите простую процедуру регистрации.