assembly 循环期间跳过字符串中的空格,汇编回文

inn6fuwd  于 2023-06-30  发布在  其他
关注(0)|答案(1)|浏览(98)

我想做一个回文检查程序,我被困在跳过字符串中的空格。它适用于单个单词,但不适用于句子。
我尝试添加 skip_space1skip_space2,但它不适用于空格。
代码:

call getaddr  ; push on the stack the runtime address of format and jump to getaddr
format   db "evil olive"
length   equ $ - format
         db 0xA, 0

getaddr:
         mov ecx, length  ; ecx = length

         shr ecx, 1  ; ecx = ecx >> 1 = ecx / 2

         jecxz pass  ; jump if ecx is zero ; jump if ecx = 0

         mov esi, [esp]           ; esi = *(int*)esp = format
         lea edi, [esi+length-1]  ; edi = esi + length - 1

.loop    mov al, [esi]  ; al = *(char*)esi
         mov ah, [edi]  ; ah = *(char*)edi
         
         cmp al, ' '
         je skip_space1

         cmp ah, ' '
         je skip_space2

         cmp al, ah
         jne not_pass

         inc esi  ; esi++
         dec edi  ; edi--

         loop .loop

pass:
...
         
skip_space2:
         dec edi
         jmp .loop

skip_space1:
         inc esi
         jmp .loop

当我尝试在skip语句的末尾添加jmp .loop时,它返回:
palindrom0.asm:61:错误:符号skip_space2.loop未定义
palindrom0.asm:65:错误:符号“skip_space1.loop”未定义

mrzz3bfm

mrzz3bfm1#

以点开头的标签是NASM的本地标签。它们在任何两个正常aka全局标签之间有效。因为您有全局标签 pass:skip_space2:skip_space1:,所以它们之前的本地标签 .loop 不可访问。最清晰的解决方案是将所有这些标签声明为 getaddr: 的本地标签,因此 .loop:.pass:.skip_space2:.skip_space1:
在ECX中使用计数在这个任务中并不理想,因为每次需要跳过一个空格时,您都需要重新计算计数。无论如何,你永远不应该在32位代码中使用loop指令,因为它是一条慢指令。
只需设置指向第一个和最后一个字符的指针,并继续循环,只要低指针低于高指针。

建议(未测试)

getaddr:
  mov   esi, [esp]           ; points at first char
  lea   edi, [esi+length-1]  ; points at last char
.loopA:
  cmp   esi, edi
  jnb   .pass
  movzx eax, byte [esi]
  inc   esi
  cmp   al, ' '
  je    .loopA

.loopB:
  cmp   esi, edi
  jnbe  .pass
  movzx edx, byte [edi]
  dec   edi
  cmp   dl, ' '
  je    .loopB

  cmp   al, dl
  je    .loopA

.not_pass:
  ...

.pass:
  ...

如果字符串除了空格和[a,z]之外,还可以包含[A,Z],那么你可以通过在代码旁边添加以下内容来使其不区分大小写:

or    eax, 32    ; turns [A,Z] into [a,z]
  or    edx, 32    ; dito
  cmp   al, dl
  je    .loopA

相关问题