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