Удвоить вхождение каждой цифры в тексте - Assembler
Формулировка задачи:
Доброго времени суток. В данный момент занимаюсь решением следующей задачи: на вход подаётся текст (не больше 100 символов), признак конца - точка. Нужно удвоить вхождение каждой цифры в этом тексте, причём все изменения производить в массиве (хитрить при вводе нельзя), дополнительную память для создания нового массива использовать нельзя. Если введён пустой текст или текст, длиной больше 100 символов, сообщить об этом. В случае успеха, вывести получившееся на экран. Столкнулся с такой проблемой при написании программы: программа вылетает с ошибкой аварийной остановки (по всей видимости, где-то на этапе вывода возникает какое-то несоответствие между размером регистра и задаваемым индексом, но это неточно). Возможно, аналогичная проблема возникла ещё на этапе ввода. Для удобства прикрепляю код на паскале (сначала написал на нём, чтобы было проще переписать на ассемблер) и сам код ассемблера.
Pascal:
MASM:
P. S. Я только в начале пути изучения языка Ассемблер, поэтому не ругайтесь за то, что пишу не оптимально, не использую процедуры и так далее) Очень сильно рассчитываю на вашу помощь
var a: array [1..201] of char; dlina,j,k: integer; c: char; begin write('Введите текст: '); c := '*'; dlina := 0; read(c); while ( c <> '.' ) do begin a[dlina+1] := c; inc(dlina); read(c); end; writeln; if ( dlina > 100 ) or ( dlina = 0 ) then writeln('Неверный текст') else begin j := 1; while j < dlina*2 do begin if a[j] in ['0'..'9'] then begin c := a[j+1]; a[j+1] := a[j]; for k := j + 2 to 2*dlina do swap(a[k],c); j := j + 2; end else inc(j); end; j := 1; for j:= 1 to dlina*2 do write(a[j]); end; end.
.NOLIST .NOLISTMACRO .586 .model flat,stdcall option casemap:none ;option casemap:all ;option casemap:notpublic ;option proc:private .stack 4096 include C:\masm32\include\io.inc ;include masm32.inc includelib C:\masm32\lib\masm32.lib includelib C:\masm32\lib\user32.lib includelib C:\masm32\lib\kernel32.lib includelib C:\masm32\lib\msvcrt.lib includelib C:\masm32\lib\io_proc.lib .data buf db 201 dup (?) .code begin: outstr "Input text not longer than 100 characters: " mov ebx, 0; на регистре bx будет храниться длина строки L: inchar buf[ebx]; ввод очередного символа inc ebx cmp buf, '.'; сравнение с точкой ja R; выход из цикла cmp ebx, 99 ja E; выход из цикла по причине ошибки jmp L; продолжение цикла E: outstr "Incorrect text length" jmp Q; переход на аварийный конец R: inc bx mov ax, bx add ax, bx; ax:= bx*2 outstrln " " mov bx, 1; теперь ebx индекс цикла L1: cmp bx, ax jae Q1; проверка на завершение работы цикла и переход на хорошую концовку cmp buf[bx], '0' jl L2 cmp buf[bx], '9' ja L2 jmp L3 L2: inc bx; увеличение индекса на 1, если не цифра jmp L1; просмотр следующего символа L3: mov dl, buf[bx+1] mov cl, buf[bx] mov buf[bx+1], cl mov si, bx add si, 2 XC: xchg buf[si], dl inc si cmp si, ax jl XC add bx, 2; увеличение индекса на 2, если цифра jmp L1 Q1: mov bx, 0 V: outchar buf[bx]; вывод получившейся строки inc bx cmp bx, ax ja Q jmp V Q: end begin
Решение задачи: «Удвоить вхождение каждой цифры в тексте»
textual
Листинг программы
.686P .model flat, stdcall option casemap: none include d:\masm32\include\windows.inc include d:\masm32\include\user32.inc include d:\masm32\include\kernel32.inc include d:\masm32\include\masm32.inc include d:\masm32\include\msvcrt.inc includelib d:\masm32\lib\user32.lib includelib d:\masm32\lib\kernel32.lib includelib d:\masm32\lib\masm32.lib includelib d:\masm32\lib\msvcrt.lib .data aszMsgInstance db 0Dh, 0Ah, 'Instance: ', 0Dh, 0Ah, 0 aszMsgResult db 0Dh, 0Ah, 'Result: ', 0Dh, 0Ah, 0 aszCrLf db 0Dh, 0Ah, 0 aszPressEnter db 0Dh, 0Ah, 0Dh, 0Ah, "Press ENTER to exit", 0 aszString db 'Str1ng 4u' Len equ $-aszString db Len dup(0) iStrLen dd Len .data? hConsoleOutput HANDLE ? hConsoleInput HANDLE ? Buffer db 1024 dup(?) BufLen dd ? lpBuffer dd ? .code start proc ; получение описателей ввода и вывода консоли invoke GetStdHandle, STD_INPUT_HANDLE mov hConsoleInput, eax invoke GetStdHandle, STD_OUTPUT_HANDLE mov hConsoleOutput, eax invoke ClearScreen invoke WriteConsole, hConsoleOutput, ADDR aszMsgInstance,\ LENGTHOF aszMsgInstance - 1, ADDR BufLen, NULL invoke WriteConsole, hConsoleOutput, ADDR aszString,\ [iStrLen], ADDR BufLen, NULL invoke WriteConsole, hConsoleOutput, ADDR aszCrLf,\ LENGTHOF aszCrLf - 1, ADDR BufLen, NULL mov ecx, [iStrLen] lea esi, [aszString] @@ForEachChar: lodsb cmp al, '0' jb @@Next cmp al, '9' ja @@Next push ecx push esi std dec ecx add esi, ecx mov edi, esi dec esi rep movsb cld pop esi pop ecx stosb inc esi inc [iStrLen] @@Next: loop @@ForEachChar invoke WriteConsole, hConsoleOutput, ADDR aszMsgInstance,\ LENGTHOF aszMsgInstance - 1, ADDR BufLen, NULL invoke WriteConsole, hConsoleOutput, ADDR aszString,\ [iStrLen], ADDR BufLen, NULL invoke WriteConsole, hConsoleOutput, ADDR aszCrLf,\ LENGTHOF aszCrLf - 1, ADDR BufLen, NULL ;ожидание нажатия ENTER invoke WriteConsole, hConsoleOutput, ADDR aszPressEnter,\ LENGTHOF aszPressEnter - 1, ADDR BufLen, NULL invoke ReadConsole, hConsoleInput, ADDR Buffer,\ LENGTHOF Buffer, ADDR BufLen, NULL invoke ExitProcess, 0 start endp end start