MASM 字符串反转

发布于 2024-09-20 00:20:24 字数 827 浏览 4 评论 0原文

好吧,我正在讨论这个问题,可能是一个非常复杂的解决方案,但这是我脑海中浮现的第一件事。

我需要编写一个汇编语言程序来反转“源”字符串,而不使用“目标”字符串(临时变量)..这是我的尝试。

INCLUDE Irvine32.inc
.data
source BYTE "This is the source string", 0
count DWORD ? 

.code
main PROC

 mov ecx, LENGTHOF source 

L1: 
 mov count, ecx     ; save our outer loop count
 mov al,[source+0]    ; get the first character in the string

 mov ecx,LENGTHOF source  ; set out inner loop count
 mov esi, OFFSET source
 inc esi
L2:


 mov bl,[esi]
 dec esi
 mov [esi],bl
 add esi, 2
 loop L2

 mov ecx, count
 loop L1


 mov  edx,OFFSET source
 call WriteString

 exit
main ENDP

END main

现在......这个“算法”基本上是这样的:从字符串中取出第一个字符,将所有其他字符在字符数组中向下移动一个空格,将第一个取出的字符放入数组的后面。现在,我已经到了这太复杂的地步了。事实上,我如何到达数组的后面..我想我需要另一个循环?我当然不需要三个循环,甚至不想处理它。

也许我走在正确的道路上,只是自己不知道而已。任何建议、技巧、代码或不同的算法都会有帮助!

Alright, Im going about this, with what is probably a really complicated solution, but its the first thing that popped into my head.

I need to write an assembly language program that reverses a "source" string, without using a "target" string ( a temp variable ) .. this is my attempt at it.

INCLUDE Irvine32.inc
.data
source BYTE "This is the source string", 0
count DWORD ? 

.code
main PROC

 mov ecx, LENGTHOF source 

L1: 
 mov count, ecx     ; save our outer loop count
 mov al,[source+0]    ; get the first character in the string

 mov ecx,LENGTHOF source  ; set out inner loop count
 mov esi, OFFSET source
 inc esi
L2:


 mov bl,[esi]
 dec esi
 mov [esi],bl
 add esi, 2
 loop L2

 mov ecx, count
 loop L1


 mov  edx,OFFSET source
 call WriteString

 exit
main ENDP

END main

Now.. the "algorithm" for this is basically this: Take the first character out of the string, move all of the other characters down one space in the character array, put the character you first took out into the back of the array. Now, I'm to the point where this is much too complicated. Infact, how do I get to the back of the array.. I think I would need another loop? I certainly don't need three loops or even want to deal with that.

Maybe I'm on the right track and don't even know it. any suggestions, tips, code or a different algorithm would help!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

最单纯的乌龟 2024-09-27 00:20:24

可以用两个循环按照自己的方式完成。完成第一个循环后,您必须再次执行此操作,但长度减少一个,以便当前第一个(最初是第二个)字符被放置在 第二个 位置,留下当前单独的最后一个(最初是第一个)字符。然后继续下去,直到长度降至零。

但这是相当低效的,因为你有嵌套循环,O(n2)。这里有一个更好的算法,只使用一个循环,O(n):

set spointer to point to the first character
set epointer to point to the last character
while epointer is greater than spointer:
    save away [spointer] (the character pointed to by spointer) somewhere
    copy [epointer] to [spointer]
    copy the saved character to [epointer]
    add one to spointer
    subtract one from epointer

它基本上维护一个开始和结束指针,最初交换第一个和最后一个字符,然后指针移向彼此。

因此,第二次循环时,交换第二个和倒数第二个字符,第三次交换第三个和倒数第三个字符,依此类推。

当指针相等(对于奇数长度字符串)或起始指针大于结束指针(对于偶数长度字符串)时,此过程停止。

由于这可能是家庭作业(无论如何,您似乎都在加快 x86 的速度),因此您应该执行将其转换为汇编程序的练习。


如果事实证明这不是家庭作业,您可以使用下面的 masm32 代码作为基准。请不要试图将其冒充为您自己的教育工作,因为您几乎肯定会被抓住。如果您自己解决转换问题,您将学到更多(作为家庭作业或非家庭作业),如果您在解决问题时遇到困难,我只是提供一些后备代码。

.586
.model flat

.data
source byte "This is the source string", 0

.code
_main proc
    mov     esi, offset source   ; load up start pointer.

    mov     edi, offset source   ; set end pointer by finding zero byte.
    dec     edi
find_end:
    inc     edi                  ; advance end pointer.
    mov     al, [edi]            ; look for end of string.
    cmp     al, 0
    jnz     find_end             ; no, keep looking.
    dec     edi                  ; yes, adjust to last character.

swap_loop:
    cmp     esi, edi             ; if start >= end, then we are finished.
    jge     finished

    mov     bl, [esi]            ; swap over start and end characters.
    mov     al, [edi]
    mov     [esi], al
    mov     [edi], bl

    inc     esi                  ; move pointers toward each other and continue.
    dec     edi
    jmp     swap_loop

finished:
    int     3                    ; trap to enter debugger and check string.
                                 ; replace with whatever you need.
_main endp
end _main

You could do it your way with two loops. After doing your first loop, you then have to do it again but with the length reduced by one, so that the current first (originally second) character gets put at the second-last position, leaving the current last (originally first) character alone. Then keep going until the length drops to zero.

But that's pretty inefficient since you have the nested loops, O(n2). Here's a better algorithm that uses just one loop, O(n):

set spointer to point to the first character
set epointer to point to the last character
while epointer is greater than spointer:
    save away [spointer] (the character pointed to by spointer) somewhere
    copy [epointer] to [spointer]
    copy the saved character to [epointer]
    add one to spointer
    subtract one from epointer

It basically maintains a start and end pointer which initially swaps the first and last character, then the pointers are moved towards each other.

So the second time through the loop, you swap the second and second-last character, the third time the third and third-last character and so on.

This process stops when the pointers are equal (for an odd-length string) or the start pointer is greater than the end pointer (for an even-length string).

Since this may be homework (and you seem up to speed with x86 anyway), you should perform the exercise of converting that to assembler.


If it turns out not to be homework, you can use the masm32 code below as a baseline. Please don't try to pass this off as your own work for education since you'll almost certainly be caught out. You'll learn a great deal more (as homework or non-homework) if you tackle the conversion yourself, I'm just providing some fall-back code if you have trouble nutting it out.

.586
.model flat

.data
source byte "This is the source string", 0

.code
_main proc
    mov     esi, offset source   ; load up start pointer.

    mov     edi, offset source   ; set end pointer by finding zero byte.
    dec     edi
find_end:
    inc     edi                  ; advance end pointer.
    mov     al, [edi]            ; look for end of string.
    cmp     al, 0
    jnz     find_end             ; no, keep looking.
    dec     edi                  ; yes, adjust to last character.

swap_loop:
    cmp     esi, edi             ; if start >= end, then we are finished.
    jge     finished

    mov     bl, [esi]            ; swap over start and end characters.
    mov     al, [edi]
    mov     [esi], al
    mov     [edi], bl

    inc     esi                  ; move pointers toward each other and continue.
    dec     edi
    jmp     swap_loop

finished:
    int     3                    ; trap to enter debugger and check string.
                                 ; replace with whatever you need.
_main endp
end _main
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文