汇编:循环一系列字符并交换它们

时间:2016-11-06 18:27:59

标签: c++ loops assembly reverse masm

我的任务是在程序集中实现一个函数,该函数将执行以下操作: 循环遍历一系列字符并交换它们,使得最终结果是反向的原始字符串(100分) 提示:从用户收集字符串作为C字符串,然后将其与用户输入的字符数一起传递给汇编函数。要找出字符数,请使用strlen()函数。

我已经编写了c ++和汇编程序,并且它的工作范围很好:例如,如果我输入12345,输出正确显示为54321,但如果超过5个字符:输出开始不正确:对于例如,如果输入123456,则输出为:653241。我将非常感谢任何可以指出我的错误的人:

.code

_reverse PROC 
  push ebp     
  mov ebp,esp  ;stack pointer to ebp

  mov ebx,[ebp+8]       ; address of first array element
  mov ecx,[ebp+12]  ; the number of elemets in array
  mov eax,ebx   
  mov ebp,0         ;move 0 to base pointer 
  mov edx,0     ; set data register to 0
  mov edi,0

Setup:

  mov esi , ecx
  shr ecx,1
  add ecx,edx
  dec esi

reverse:

  cmp ebp , ecx
  je allDone

  mov edx, eax
  add eax , edi
  add edx , esi

Swap:
  mov bl, [edx]
  mov bh, [eax]

  mov [edx],bh
  mov [eax],bl

  inc edi
  dec esi

  cmp edi, esi
  je allDone

  inc ebp
  jmp reverse

allDone:
  pop ebp               ; pop ebp out of stack
  ret                   ; retunr the value of eax
 _reverse ENDP

END

这是我的c ++代码:

#include<iostream>
#include <string>

using namespace std;
extern"C"
char reverse(char*, int);

int main()
{
  char str[64] = {NULL};
  int lenght;

  cout << " Please Enter the text you want to reverse:";
  cin >> str;
  lenght = strlen(str);

  reverse(str, lenght);

  cout << " the reversed of the input is: " << str << endl;

  }

2 个答案:

答案 0 :(得分:3)

你没有评论你的代码,所以IDK到底想要做什么,但看起来你是用MOV / ADD手动进行数组索引而不是像[eax + edi]那样使用寻址模式。

然而,看起来您正在修改原始值,然后以一种在未经修改的情况下有意义的方式使用它。

  mov edx, eax         ; EAX holds a pointer to the start of array, read every iter
  add eax , edi        ; modify the start of the array!!!
  add edx , esi

Swap:
  inc edi
  dec esi

每一步都通过EDI增长EAX,EDI线性增长。所以EAX在几何上增加(整数(x * dx)= x ^ 2)。

在调试器中单步执行此操作应该很容易找到它。

顺便说一下,执行此操作的常规方法是向上移动一个指针,向下移动一个指针,并在它们交叉时从循环中掉出来。那么你不需要一个单独的计数器,只需cmp / ja。 (不要检查JNE或JE,因为它们可以相互交叉而不平等。)

答案 1 :(得分:0)

总的来说,你是正确的想法,从字符串和交换元素的两端开始,直到你到达中间。虽然实施很糟糕。

mov ebp,0         ;move 0 to base pointer

这似乎是循环计数器(评论无用甚至更糟);我想是交换length/2元素,这是完全没问题的。我只是比较指针/索引,一旦碰撞就退出。

mov edx,0     ; set data register to 0
...
add ecx,edx
mov edx, eax

无用且误导。

mov edi,0
mov esi , ecx
dec esi

看起来像索引开始/结束字符串。好。我打算用指针开始/结束字符串;但索引也有效

cmp ebp , ecx
je allDone

如果长度/ 2次迭代,则退出。行。

mov edx, eax
add eax , edi
add edx , esi

eaxedx指向要交换的当前符号。几乎可以,但这个clobbers eax !第二次后的每次循环迭代将使用错误的指针!这就是首先引起问题的原因。如果您使用指针代替索引,或者如果您使用偏移量寻址[eax+edi] / [eax+esi]

,则不会发生这种情况
...

交换部分没问题

cmp edi, esi
je allDone

第二次退出条件,这次比较索引碰撞!通常一个退出条件就足够了;几个退出条件通常是多余的或暗示算法中的某些缺陷。同样的比较还不够 - 索引可以在单次迭代中从edi<esi转到edi>esi