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

Posted

技术标签:

【中文标题】编写汇编语言代码来反转字符串【英文标题】:Write an assembly language code to reverse a string 【发布时间】:2018-10-31 06:06:30 【问题描述】:

这是一个反转字符串的代码 我真的很难完成这段代码。我找不到它有什么问题,但是输出是错误的。

    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                    

【问题讨论】:

***.com/questions/33685870/… 你可以做mov edi, OFFSET target + SIZEOF target - 2。或者只是在目标缓冲区的末尾放一个标签,然后执行mov edi, OFFSET end_target - 2。无论如何,这段代码与您想要发生的事情有什么不同?它是否写入target 开头之前的 1 个字节或其他内容? @NgSharma,这个问题有很多,--unhelpful-- 至少可以说是答案。 【参考方案1】:

将两个长度传递给函数有点奇怪。如果两者不匹配,可能会发生各种不好的事情。 最好明确地传递字符串的长度,或者让代码计算出长度。 由于获取 old-skool c-string 的长度对于代码来说并非易事,但对于谷歌来说却是微不足道的,我将把它作为参数传递。

'...输出错误。' 问题是您的字符串需要以零结尾,但您没有将终止零放在目标字符串上。

首先,如果您想让字符串成为有效的 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,那么你可以只在寄存器中传递参数,这意味着你可以跳过一些初始化。鉴于您的代码不会因原始速度而赢得任何奖励,因此我跳过了这一步。

【讨论】:

它不是函数,MASM 中的 SIZEOF 运算符是静态数据的汇编时事物。从之前的问题来看,我认为 OP 在已知长度的静态缓冲区中有以 0 结尾的 C 字符串,并且他们很难在终止符之前反转数据,然后只复制终止符。 @PeterCordes,是的,我已经有一段时间没有使用 MASM 了。我是正确的关于 0 终止是问题,感谢您确认。 length EQU SIZEOF source 这行 mov ecx, length 给了我一个语法错误 @Jinna:使用mov ecx, SIZEOF source。或者在定义source 之后立即使用length = $ - source。 ($ 是当前位置,所以如果你把它放在其他任何地方,它会计算错误的大小。有关 NASM 版本,请参阅How does $ work in NASM, exactly?。我不确定 MASM 中的 EQU 是否正是你想要的,可能只是一个将在错误位置评估$ 的文本替换;我认为= 肯定会在您编写它的位置被评估为一个数字(但仍然是一个不占用数据部分空间的汇编时间常数) .)

以上是关于编写汇编语言代码来反转字符串的主要内容,如果未能解决你的问题,请参考以下文章

为啥这个字符串反转 C 代码会导致分段错误? [复制]

C语言试题二十六之请编写一个函数function(char *s),该函数的功反转字符串中的内容。

C语言试题二十六之请编写一个函数function(char *s),该函数的功反转字符串中的内容。

C 字符串反转

使用 x64 SSE / AVX 寄存器进行字符串反转

使用基本python运算符反转python中任何给定字符串的代码[重复]