程序从指定文本中删除字符时发生异常

问题描述

任务:编写一个程序以删除给定文本中所有奇数长度的单词的中心字符。 我这样做了(算法的想法是(在第一个周期中)找到并写入空间所位于的索引,然后在必要时用缺少的字符重写字符串):

    .586
    .model flat,C
    option casemap: none
include c:\masm32\include\msvcrt.inc
include c:\masm32\include\kernel32.inc
 
includelib c:\masm32\lib\msvcrt.lib
includelib c:\masm32\lib\kernel32.lib
 
    printf PROTO C,:VaraRG
 
.data
        src         db 'hello masm32_ wrld lb 7',0
        len         equ $-src
        dest        db ' ',len dup(0),0
        end_index   db len/2 dup(0)
        msg2        db ' %d ',0 
        count_1     db 0
        count_2     db 0
 
 
 
.code
start:
        symbol      equ ' '
        xor ecx,ecx
        xor ebx,ebx
        lea esi,src
        dec ebx     
    next:
        inc ebx     
        cmp byte ptr [esi],symbol
        jnz notfound
        inc ecx
        mov byte ptr [end_index + ecx],bl
    notfound:
        inc esi
        cmp byte ptr [esi],0
        jz exit
        jmp next
    exit:
 
        lea esi,src
        lea edi,dest
        mov ebx,1
        xor ecx,ecx
    @@_next:
        
.if byte ptr [end_index + ebx] == 0
        jmp @@_ret
.endif
 
        mov al,byte ptr [end_index + ebx]
        mov ah,byte ptr [end_index + ebx - 1]
        sub al,ah
        xor ah,ah
        push ebx
        mov bl,2
        div bl
        pop ebx
        add al,byte ptr [end_index + ebx - 1]
        and eax,000000ffh      
.if al == cl
        inc count_1
        inc count_2
        inc ebx 
        jmp @@_next
.endif
        mov al,byte ptr [esi + count_1]
        mov byte ptr [edi + count_2],al
        inc count_1
        inc count_2
        jmp @@_next
    @@_ret:
        invoke printf,offset dest,0
    ret
end start

但是在循环的第一遍,我得到了

An exception was thrown at address 0x00042092 in asm_7_deb.exe: 0xC0000005: Read access violation at address 0x0008A045.

反汇编程序:

start:
00042020  xor         ecx,ecx  
00042022  xor         ebx,ebx  
00042024  lea         esi,[src (045000h)]  
0004202A  dec         ebx  
next:
0004202B  inc         ebx  
0004202C  cmp         byte ptr [esi],20h  
0004202F  jne         _start+18h (042038h)  
00042031  inc         ecx  
00042032  mov         byte ptr end_index (045032h)[ecx],bl  
notfound:
00042038  inc         esi  
00042039  cmp         byte ptr [esi],0  
0004203C  je          _start+20h (042040h)  
0004203E  jmp         _start+0Bh (04202Bh)  
exit:
00042040  lea         esi,[src (045000h)]  
00042046  lea         edi,[dest (045018h)]  
0004204C  mov         ebx,1  
00042051  xor         ecx,ecx  
@@_next:
00042053  cmp         byte ptr end_index (045032h)[ebx],0  
0004205A  jne         _start+3Eh (04205Eh)  
0004205C  jmp         _start+8Ch (0420ACh)  
@C0001:
0004205E  mov         al,byte ptr end_index (045032h)[ebx]  
00042064  mov         ah,byte ptr [ebx+45031h]  
0004206A  sub         al,ah  
0004206C  xor         ah,ah  
0004206E  push        ebx  
0004206F  mov         bl,2  
00042071  div         al,bl  
00042073  pop         ebx  
00042074  add         al,byte ptr [ebx+45031h]  
0004207A  and         eax,0FFh  
0004207F  cmp         al,cl  
00042081  jne         _start+72h (042092h)  
00042083  inc         byte ptr [count_1 (045045h)]  
00042089  inc         byte ptr [count_2 (045046h)]  
0004208F  inc         ebx  
00042090  jmp         _start+33h (042053h)  
@C0003:
00042092  mov         al,byte ptr count_1 (045045h)[esi]  ; <==== probably it happend here
00042098  mov         byte ptr count_2 (045046h)[edi],al  ;           but i do not understand why 
0004209E  inc         byte ptr [count_1 (045045h)]  
000420A4  inc         byte ptr [count_2 (045046h)]  
000420AA  jmp         _start+33h (042053h)  
@@_ret:
000420AC  push        0  
000420AE  push        offset dest (045018h)  
000420B3  call        _printf (041005h)  
000420B8  add         esp,8  
000420BB  ret

解决方法

要加载[esi + count_1],您需要先将count_1的值加载到寄存器中。否则,它将使用count_1的地址加上esi的值,这不是您想要的。

由于count_1是一个字节,请使用:

movzx edx,byte ptr [count_1]
mov al,[esi+edx]