如何在nasm中反转字符串中的每个单词?

时间:2013-12-14 03:39:07

标签: string assembly nasm reverse

我必须编写一个程序,该程序读取25个字符的字符串并返回相同的字符串,每个单词的字母以asm语言翻转

例如:

Input >> Hello world. How are you?
Output >> olleH .dlrow woH era ?uoy

这就是我所做的:

%include "asm_io.inc"
segment .data

prompt1 db    "Insert the strin: ", 0       ; don't forget nul terminator
prompt2 db    "The string is: ", 0
prompt3 db    "The reverse string is: ", 0

segment .bss

vector  resb 25
vectorInvert resb 25   
aux resb 1 
aux2 resb 1                                          

segment .text
        global  asm_main
asm_main:


        mov     eax, prompt1      ; print out prompt
            call    print_string


        mov edi, vector ;vetor e do tipo byte
        mov ecx, 25
        read:
            call read_char  
            stosb       
        loop read

        mov eax, 0
        mov edx, 0
        mov esi, vector
        mov ecx, 25
        stack:
            mov al, [esi]
            cmp al, " "
            jz stack2
            movzx eax, al
            push eax
            add eax, 1  
            add esi, 1
        loop stack

        stack2:
            mov [aux], ecx
            mov [aux2], eax         
            mov ecx, 25
            sub ecx, eax
            mov edi, vectorInvert           
            lp:
                pop eax
                add edx, 1
                mov [edi], eax
                add edi, 1
            loop lp
            add eax, 1
            add edx, 1
            add esi, 1
            add edi, 1
            mov ecx, [aux]
            mov eax, [aux2]
            cmp eax, 25
            jz out
            jnz stack


        out:

            mov     eax, prompt3
            call    print_string

            mov edi, vectorInvert
            mov ecx, 25
            print:
                lodsb
                call print_char 
            loop print
            call print_nl

            leave                     
            ret

我被困在那里,我不知道如何继续前进。我非常感谢这些代码的一些帮助。 我正在使用这里的库:drpaulcarter.com/pcasm/linux-ex.zip (请注意,我是集会的新手。)

2 个答案:

答案 0 :(得分:1)

使用堆栈反转字符串:

  1. 复制stackpointer
  2. 按0字节(如果使用DOS则按'$')
  3. 推送字符串的每个字符
  4. 将stackpointer作为字符串地址
  5. 打印它(或复制它或用它做的任何事情)。
  6. 恢复stackpointer
  7. 可能需要注意的事项:如果堆栈指针变为奇数,则可能会导致问题,因此在这种情况下,可能会先推送一个额外的0字节以保持堆栈对齐。

答案 1 :(得分:1)

嗯......我看到发布的代码存在一些小问题。除了拼写“strin”rong之外,变量auxaux2太小了。如果您要将32位寄存器放入其中,则需要32位 - 4个字节 - resd 1resb 4(两者都可以)。我认为你可能不需要这些变量,但要使它们的尺寸合适。

然后,如果您要在leave末尾使用asm_main,则需要从enter 0, 0开始。我认为卡特博士的所有例子都是这样做的。

您的输入例程看起来会起作用,但会强制用户准确输入25个字符,即使它们有一个较短的“strin”。这样做的好处是你知道你有多少个角色,但不是很灵活。 Carter博士的库提供了一个read_string,它返回一个以零结尾的字符串。我们可以对此进行stringlen,但由于我们无论如何都要检查每个角色,我们只能注意零。

然后你似乎在push eax做得很好。然后你add eax, 1。咦?看起来你打算eax同时成为角色和反击者。这不会起作用!

我想到了推动每个角色,计算它,然后检查它是什么。这会将“Hello”变成“olleH”(当我们pop'时)。还不错,但是当我们到达目的地时它会导致问题(如果我们使用的是零终止字符串)。我决定首先检查字符,仅推送(并计算)非空格(和非零)字符......

mov esi, string
mov edi, reverse

nextword:
xor ecx, ecx ; counter - per word
pushloop:
lodsb
cmp al, ' '
jz poploop
cmp al, 0
jz cleanuploop
push eax ; if not, save it (plus garbage)
inc ecx
jmp pushloop

poploop:
pop eax ; including garbage
stosb ; store al only, ignoring garbage
loop poploop
mov al, ' '
stosb
jmp nextword

cleanuploop:
pop eax
stosb
loop cleanuploop
mov al, 0 ; zero-terminate our string for "print_string"
stosb

这“有效”。你看到了这个缺陷吗?如果讨厌的用户输入一个空格作为第一个字符(或最后一个字符,或者什么都不输入),我们会在poploop(等等)中结束ecx已经为零。 loop指令递减ecx并且如果非零则跳转。如果ecx已经为零,则递减为0FFFFFFFFh。这循环很多次。在火焰中崩溃!

我这样解决了......

mov esi, string
mov edi, reverse

nextword:
xor ecx, ecx
pushloop:
lodsb
cmp al, ' '
jz poploop
cmp al, 0
jz cleanuploop
push eax
inc ecx
jmp pushloop

poploop:
jecxz skippop ; bail out if ecx is zero
pop eax
stosb
loop poploop
skippop:
mov al, ' '
stosb
jmp nextword

cleanuploop:
jecxz skippop2
pop eax
stosb
loop cleanuploop
skippop2:
mov al, 0
stosb

显示它,然后干净利落地退出。如果你在后面添加换行符会更好看。

在推送movzx eax, al之前,您执行eax。没有伤害,但我们可以push eax高位字节中的任何内容。弹出它后,只需忽略al以外的所有内容。你不能只是push al ......

我希望这不太像“为你做” - 我想不出更好的解释方法。有不同的方法来做到这一点。希望这会给你一些如何继续的想法。

编辑:他们不会让我添加评论(?)。试试这个: enter 0, 0push ebp / mov ebp, esp的效果相同。如果第一个参数非零,它将从esp中减去该数量 - 为局部变量腾出空间。 leavemov esp, ebp / pop ebp的效果相同。来自asm_main的{​​{1}}函数的Prolog和epilog。请转到示例中的driver.c