编写汇编语言代码以反转字符串

时间:2018-10-31 06:06:30

标签: string loops assembly x86 masm

这是反转字符串的代码 我真的很难完成这段代码。我找不到问题所在,但是输出错误。

    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                    

1 个答案:

答案 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 

代码注释
无需保持三个计数器飞行(ediesiecx),两个就足够了。 esi递增计数,ecx递减计数。
x86具有许多非常有用的寻址模式,这在性能上是免费的。
最后一次迭代将读取al中的终止零,我们不需要将其反转,并且您已经在开始时编写了它,因此(静默)将其删除。
因为终止符为零,所以长度至少为1。这很好,因为如果以某种方式将0馈送到loop中,它将循环'永远'; (“永远”是4+十亿次)

请注意,您的代码未考虑Unicode,因此不适用于UTF8,但请假设这只是一个学习练习。

如果遵循ABI,则只需将参数传递到寄存器中,这意味着您可以跳过某些初始化。鉴于您的代码不会以任何原始速度赢得任何奖励,因此我跳过了这一步。