这是反转字符串的代码 我真的很难完成这段代码。我找不到问题所在,但是输出错误。
mov esi, OFFSET source
mov edi, OFFSET target
add edi, SIZEOF target-2
mov ecx, SIZEOF source-1
L1:
mov al, [esi]
mov [edi], al
inc esi
dec edi
loop L1
答案 0 :(得分:1)
您将两个长度传递给函数有点奇怪。如果两者不匹配,可能会发生各种不良情况。
最好显式传递字符串的长度,或者让代码找出长度。
由于获取旧式C字符串的长度对于代码而言并非易事,但对于Google而言却不那么重要,因此我将仅将其作为参数传递。
'...输出错误。'
问题在于您的字符串需要以零结尾,但是您没有将结尾的零放在目标字符串上。
首先,如果要使字符串成为有效的c样式字符串,请确保添加一个终止零,例如:source db "test test",0
mov esi, OFFSET source ;Start of source
mov edi, OFFSET target ;start of dest
;length EQU SIZEOF source ;we are reversing source
mov ecx, SIZEOF source ;Length of the string
;(includes the terminating 0)
Setup:
;//a c-string must have a terminating 0!
xor eax,eax ;al=0, put the terminating zero in first
L1:
mov [edi+ecx-1], al ;if length(ecx)=1, then write to [edi] directly.
mov al, [esi]
inc esi
loop L1
代码注释
无需保持三个计数器飞行(edi
,esi
,ecx
),两个就足够了。 esi
递增计数,ecx
递减计数。
x86具有许多非常有用的寻址模式,这在性能上是免费的。
最后一次迭代将读取al
中的终止零,我们不需要将其反转,并且您已经在开始时编写了它,因此(静默)将其删除。
因为终止符为零,所以长度至少为1。这很好,因为如果以某种方式将0馈送到loop
中,它将循环'永远'; (“永远”是4+十亿次)。
请注意,您的代码未考虑Unicode,因此不适用于UTF8,但请假设这只是一个学习练习。
如果遵循ABI,则只需将参数传递到寄存器中,这意味着您可以跳过某些初始化。鉴于您的代码不会以任何原始速度赢得任何奖励,因此我跳过了这一步。