【问题标题】:String Reverse in Assembly language x86汇编语言 x86 中的字符串反转
【发布时间】:2016-10-26 18:35:08
【问题描述】:

我是汇编语言的新手,我有这段代码可以反转字符串长度,现在我知道我已经接近了,但无论出于何种原因,程序都会不断地在我身上崩溃。问题出在STRREV PROC 中。我在这段代码中做错了什么?

INCLUDE Irvine32.inc
.data
    prompt BYTE "Enter String: ", 0
    response BYTE 50 DUP(0)
    message BYTE " Message entered. ",0
.code   

swap MACRO a,b 

    xor a,b
    xor b,a
    xor a,b

endM

STRQRY PROC
   push ebp
   mov  ebp, esp
   push edx
   push ecx

   mov edx, [ebp+8]
   call writestring

   mov ecx, SIZEOF response
   mov edx, OFFSET response
   call readstring


   pop ecx
   pop edx
   pop ebp  
   ret 4

STRQRY ENDP

STRLEN PROC 
           push ebp 
           mov  ebp, esp
           push ebx
           push ecx

           mov edx,[ebp+16]

           mov eax, 0


counter:
           mov cl,[edx+eax]

           cmp cl, 0       

           JE  done

           inc eax 

           jmp counter

done:
           pop ecx
           pop ebx
           pop ebp
           ret 4

STRLEN ENDP

STRREV proc
    push ebp
    mov  ebp, esp

    push OFFSET response   
    call STRLEN

    mov edx, [ebp+8]
    mov esi, 0
    dec eax

reverseloop:   

    mov ah, [edx+esi]
    mov al, [edx+eax]

    swap ah, al

    mov [edx+esi],ah
    mov [edx+eax],al

    inc esi
    dec eax

    cmp esi, eax
    jb reverseloop
    ja finish

finish:
    pop ebp
    ret 4

STRREV endp

main PROC

    push OFFSET prompt
    call STRQRY

    call writedec 

    mov edx,OFFSET message
    call WriteString

    push eax 
    call STRREV

    mov edx, OFFSET response
    call WriteString

     exit
main ENDP
END main

【问题讨论】:

  • 你为什么在STRLENmov edx, [ebp+16]
  • 第一个参数是+8,他错误地在mov ebp,esp之后为2x push添加了另一个+8,没有意识到push只影响esp,而不是ebp(这两个推送指令的值在[esp+0] == [ebp-8][esp+4] == [ebp-4] ...所以他正在做[ebp+16] 而不是[esp+16][ebp+8]。...反正他没有'甚至懒得调试它,否则他错过了strlen代码在那时加载错误的字符串地址这一事实。另外,我已经在SO上看到了这个源,我想知道他们是如何每次都产生相同的错误的,好笑。
  • 但该代码中存在更多错误。继续调试(一段时间后你可能会注意到,eaxal 共享一些位,ah 共享一些位,等等)

标签: string assembly x86 reverse irvine32


【解决方案1】:

您的函数中的主要问题是更改 AL 和 AH 寄存器,然后使用 EAX 作为指针。
我决定根据您的代码编写一个新函数,仔细阅读并使用正确的模拟器调试您的代码。

STRREV proc 

;opening the function 
push ebp
mov  ebp, esp

push OFFSET response  
call STRLEN

mov edx, [ebp+8]   ;edx = offset string to reverse 
mov esi, 0
dec eax    

mov ebx,edx       ;ebx stores the pointer to the first character  
add ebx,eax`       ;now ebx store the pointer to the last character before the '$'  

reverseloop:   


mov ah, [edx]    ;ah stores the value at string[loop count]
mov al, [ebx]    ;al stores the value at string[len-loop count-1]

;"swap ah,al"  is logiclly unnecessary
;better solution: 

mov [ebx],ah     ; string[loop count] = string[len-loop count-1]
mov [edx],al     ; string[len-loop count-1] = string[loop count]

inc edx          ;increment  of the right-most pointer
dec ebx          ;decrement of the right-most pointer 

cmp ebx, eax     ;compares the left-most pointer to the right-most 
jb reverseloop
jmp finish      ;"ja", there is no need to check a condition twice 

finish:
pop ebp
ret 4

STRREV endp

【讨论】:

  • 不使用同一寄存器的不同部分以提高性能,这会导致对某些 CPU 的错误依赖。例如使用movzx eax, byte [edx]movzx ecx, byte [ebx] 来避免写入部分寄存器。 (并且仍然存储为 mov [ebx], al / mov [edx], cl 与字节存储)。
猜你喜欢
  • 2014-05-06
  • 2014-06-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多