Удвоить вхождение каждой цифры в тексте - Assembler

Узнай цену своей работы

Формулировка задачи:

Доброго времени суток. В данный момент занимаюсь решением следующей задачи: на вход подаётся текст (не больше 100 символов), признак конца - точка. Нужно удвоить вхождение каждой цифры в этом тексте, причём все изменения производить в массиве (хитрить при вводе нельзя), дополнительную память для создания нового массива использовать нельзя. Если введён пустой текст или текст, длиной больше 100 символов, сообщить об этом. В случае успеха, вывести получившееся на экран. Столкнулся с такой проблемой при написании программы: программа вылетает с ошибкой аварийной остановки (по всей видимости, где-то на этапе вывода возникает какое-то несоответствие между размером регистра и задаваемым индексом, но это неточно). Возможно, аналогичная проблема возникла ещё на этапе ввода. Для удобства прикрепляю код на паскале (сначала написал на нём, чтобы было проще переписать на ассемблер) и сам код ассемблера. Pascal:
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.
MASM:
.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
P. S. Я только в начале пути изучения языка Ассемблер, поэтому не ругайтесь за то, что пишу не оптимально, не использую процедуры и так далее) Очень сильно рассчитываю на вашу помощь

Решение задачи: «Удвоить вхождение каждой цифры в тексте»

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

Оцени полезность:

10   голосов , оценка 4.3 из 5
Похожие ответы