汇编:遍历一系列字符并交换它们
Assembly: loop through a sequence of characters and swap them
我的任务是在汇编中实现一个函数,该函数将执行以下操作:
遍历一系列字符并交换它们,使得最终结果是原始字符串的反向(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;
}
你没有评论你的代码,所以我知道你到底想做什么,但看起来你是用 MOV / ADD 手动进行数组索引,而不是使用 [=11= 这样的寻址模式].
但是,看起来您正在修改原始值,然后以未修改的情况下有意义的方式使用它。
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
EAX每一步增长EDI,EDI线性增长。所以 EAX 呈几何级数增长 (integral(x * dx) = x^2).
在调试器中单步执行这个应该很容易找到。
顺便说一句,通常的做法是向上走一个指针,向下走一个指针,当它们交叉时跳出循环。那么你不需要单独的计数器,只需cmp / ja
。 (不要检查 JNE 或 JE,因为它们可以在不相等的情况下相互交叉。)
总的来说,从字符串的两端开始交换元素直到到达中间是正确的想法。虽然实施很糟糕。
mov ebp,0 ;move 0 to base pointer
这好像是循环计数器(注释没用甚至更糟);我猜想法是交换 length/2
元素,这非常好。提示我只是比较 pointers/indexes 并在它们发生碰撞后退出。
mov edx,0 ; set data register to 0
...
add ecx,edx
mov edx, eax
无用且具有误导性。
mov edi,0
mov esi , ecx
dec esi
看起来像字符串 start/end 的索引。好的。提示我会使用指向字符串 start/end 的指针;但索引也有效
cmp ebp , ecx
je allDone
如果进行了 length/2 次迭代,则退出。好的。
mov edx, eax
add eax , edi
add edx , esi
eax
和 edx
指向要交换的当前符号。几乎可以,但是 这破坏了 eax!秒后的每次循环迭代都会使用错误的指针!这首先是导致您出现问题的原因。如果您使用指针而不是索引,或者如果您使用偏移寻址 [eax+edi]
/[eax+esi]
,就不会发生这种情况
...
交换部分可以
cmp edi, esi
je allDone
第二个退出条件,这次比较索引冲突!通常一个退出条件就足够了;几个退出条件通常是多余的或暗示算法中的某些缺陷。相等比较也是不够的——在单次迭代中索引可以从 edi<esi
变为 edi>esi
。
我的任务是在汇编中实现一个函数,该函数将执行以下操作: 遍历一系列字符并交换它们,使得最终结果是原始字符串的反向(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;
}
你没有评论你的代码,所以我知道你到底想做什么,但看起来你是用 MOV / ADD 手动进行数组索引,而不是使用 [=11= 这样的寻址模式].
但是,看起来您正在修改原始值,然后以未修改的情况下有意义的方式使用它。
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
EAX每一步增长EDI,EDI线性增长。所以 EAX 呈几何级数增长 (integral(x * dx) = x^2).
在调试器中单步执行这个应该很容易找到。
顺便说一句,通常的做法是向上走一个指针,向下走一个指针,当它们交叉时跳出循环。那么你不需要单独的计数器,只需cmp / ja
。 (不要检查 JNE 或 JE,因为它们可以在不相等的情况下相互交叉。)
总的来说,从字符串的两端开始交换元素直到到达中间是正确的想法。虽然实施很糟糕。
mov ebp,0 ;move 0 to base pointer
这好像是循环计数器(注释没用甚至更糟);我猜想法是交换 length/2
元素,这非常好。提示我只是比较 pointers/indexes 并在它们发生碰撞后退出。
mov edx,0 ; set data register to 0
...
add ecx,edx
mov edx, eax
无用且具有误导性。
mov edi,0
mov esi , ecx
dec esi
看起来像字符串 start/end 的索引。好的。提示我会使用指向字符串 start/end 的指针;但索引也有效
cmp ebp , ecx
je allDone
如果进行了 length/2 次迭代,则退出。好的。
mov edx, eax
add eax , edi
add edx , esi
eax
和 edx
指向要交换的当前符号。几乎可以,但是 这破坏了 eax!秒后的每次循环迭代都会使用错误的指针!这首先是导致您出现问题的原因。如果您使用指针而不是索引,或者如果您使用偏移寻址 [eax+edi]
/[eax+esi]
...
交换部分可以
cmp edi, esi
je allDone
第二个退出条件,这次比较索引冲突!通常一个退出条件就足够了;几个退出条件通常是多余的或暗示算法中的某些缺陷。相等比较也是不够的——在单次迭代中索引可以从 edi<esi
变为 edi>esi
。