汇编 - 尝试反转字符串,但它在最终字符串上添加了一个额外的字符

发布于 2024-08-22 23:41:38 字数 2429 浏览 6 评论 0原文

我对汇编相当陌生(老实说,还有一般的编程)。我正在尝试玩堆栈。 此代码的目的:

  • 接收一个字符串,限制为 80 个字符
  • 重新打印输入的字符串 在将
  • 每个字符推入堆栈时
  • 打印每个字符 从堆栈中弹出时打印每个字符
  • 打印反转的字符串。

代码在最后一步失败。

如果输入的字符串是“Help”,则会打印出“pleHe”。最终字符串中的最后一个字符是原始字符串的第二个字符。

请帮我看看我哪里搞砸了!

.data
buffer WORD 81 DUP(0)
byteCount WORD ?
.code
main PROC
    call Clrscr                 ;Clear screen         
RS:
    mov edx, OFFSET buffer      ;Move String to edx
    mov cl, [SIZEOF buffer]-1   ;Set loop counter to (size of buffer) -1
    call ReadString             ;Read a User's String
    mov byteCount, ax           ;Move the size of User's String to byteCount
    cmp byteCount, 80           ;Compare byteCount with 80
    ja RS                       ;If byteCount is greater then 80, ask for another String
    call WriteString            ;Write User's String to screen
    call Crlf                   ;New Line
    call reverseIt              ;Reverse order of String
    exit

reverseIt PROC
    movzx ecx, byteCount        ;Set Loop1 Counter to size of String
    mov esi, 0                  ;Zero out ESI

L1:                             ;Loop1 - Pushes String into Stack one character at a time

    movzx eax, buffer[esi]      ;Dereference buffer and place in eax
    call Crlf                   ;New Line
    call WriteChar              ;Print current character to screen
    push eax                    ;Push current character to stack
    inc esi                     ;Move to next character
    loop L1

    call Crlf
    movzx ecx, byteCount        ;Set Loop2 Counter to size of String
    mov esi, 0                  ;Zero out ESI

L2:                             ;Loop2 - Pops Characters back into String in reverse order

    pop eax                     ;Retrieve character from top of stack
    call Crlf                   ;New Line
    call WriteChar              ;Print current character to screen
    mov buffer[esi], ax         ;Writes character to String
    inc esi                     ;Increase esi
    loop L2

    call Crlf                   ;New Line
    call Crlf                   ;New Line    
    mov edx, OFFSET buffer      ;Move String to edx for WriteString
    call WriteString            ;Prints String to Screen
    call Crlf                   ;New Line
    ret                         ;Return to main
    reverseIt ENDP
main ENDP
END main 

I'm rather new to Assembly (And programming in general, to be honest). I'm trying to play with the stack.
The purpose of this code:

  • Take in a String, limited to 80 characters
  • Reprint the String as entered
  • Print each character as it is pushed to the stack
  • Print each character as it is popped from the stack
  • Print the reversed String.

The code fails on the last step.

If the entered String is "Help", it will print out "pleHe". The last character in the final String is the 2nd character of the original String.

Please help me see where I'm messing up at!

.data
buffer WORD 81 DUP(0)
byteCount WORD ?
.code
main PROC
    call Clrscr                 ;Clear screen         
RS:
    mov edx, OFFSET buffer      ;Move String to edx
    mov cl, [SIZEOF buffer]-1   ;Set loop counter to (size of buffer) -1
    call ReadString             ;Read a User's String
    mov byteCount, ax           ;Move the size of User's String to byteCount
    cmp byteCount, 80           ;Compare byteCount with 80
    ja RS                       ;If byteCount is greater then 80, ask for another String
    call WriteString            ;Write User's String to screen
    call Crlf                   ;New Line
    call reverseIt              ;Reverse order of String
    exit

reverseIt PROC
    movzx ecx, byteCount        ;Set Loop1 Counter to size of String
    mov esi, 0                  ;Zero out ESI

L1:                             ;Loop1 - Pushes String into Stack one character at a time

    movzx eax, buffer[esi]      ;Dereference buffer and place in eax
    call Crlf                   ;New Line
    call WriteChar              ;Print current character to screen
    push eax                    ;Push current character to stack
    inc esi                     ;Move to next character
    loop L1

    call Crlf
    movzx ecx, byteCount        ;Set Loop2 Counter to size of String
    mov esi, 0                  ;Zero out ESI

L2:                             ;Loop2 - Pops Characters back into String in reverse order

    pop eax                     ;Retrieve character from top of stack
    call Crlf                   ;New Line
    call WriteChar              ;Print current character to screen
    mov buffer[esi], ax         ;Writes character to String
    inc esi                     ;Increase esi
    loop L2

    call Crlf                   ;New Line
    call Crlf                   ;New Line    
    mov edx, OFFSET buffer      ;Move String to edx for WriteString
    call WriteString            ;Prints String to Screen
    call Crlf                   ;New Line
    ret                         ;Return to main
    reverseIt ENDP
main ENDP
END main 

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

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

发布评论

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

评论(2

断舍离 2024-08-29 23:41:39

问题

您将 ASCII 字符视为单词而不是字节,因此您最终会一次反转两个字符:

当您一次反转字符串两个字符时,您最终会将这些值写入缓冲区:

esi+0: p-
esi+1: lp
esi+2: el
esi+3: He

在每次迭代期间,您的缓冲区如下所示:

Help--
p-lp--
plpp--
plel--
pleHe-

因此,您最终会将额外的 e 写入缓冲区。我假设 e 没有出现在您的 WriteChar 循环中。

解决方案

我还没有测试过你的代码,所以不能确定,但​​看起来你需要更改这一行:

mov buffer[esi], ax         ;Writes character to String

mov ptr byte buffer[esi], al         ;Writes character to String

也更改这一行可能是个好主意:

buffer WORD 81 DUP(0)

所以它使用 BYTE反而:

buffer BYTE 81 DUP(0)

Problem

You're treating your ASCII characters as WORDs rather than bytes, so you end up reversing two characters at a time:

When you reverse the string two characters at a time, you end up writing these values to the buffer:

esi+0: p-
esi+1: lp
esi+2: el
esi+3: He

During each iteration your buffer looks like this:

Help--
p-lp--
plpp--
plel--
pleHe-

So you end up writing that extra e to the buffer. I assume the e doesn't show up in your WriteChar loop.

Solution

I haven't tested your code so can't know for sure, but it looks like you need to change this line:

mov buffer[esi], ax         ;Writes character to String

to

mov ptr byte buffer[esi], al         ;Writes character to String

It's probably a good idea to change this line too:

buffer WORD 81 DUP(0)

so it uses BYTEs instead:

buffer BYTE 81 DUP(0)
内心旳酸楚 2024-08-29 23:41:39

谢谢你!我知道我使用的是 WORD,而不是 BYTE,因为第一部分限制了字符串的大小,不适用于 BYTE。它正在从中间切断绳子。

所以我没有将缓冲区更改为BYTE。

也就是说,我尝试进行其他更改(我想我以前也尝试过),但一直收到编译错误,指出两个操作数必须具有相同的大小。

我通过将 buffer[esi] 转换为字节来解决这个问题!
现在可以完美运行了!谢谢!

mov byte ptr buffer[esi], al

Thank you for this! I knew I was using WORDs instead of BYTEs because the first part, where it limits the size of the string, was not working with BYTEs. It was cutting the string off in the middle.

So I didn't change buffer to BYTE.

That said, I tried making the other change (which I think I had tried before, as well) but kept getting a compile error stating both operands must be the same size.

I fixed this by casting buffer[esi] as a byte!
Now it works perfectly! Thanks!

mov byte ptr buffer[esi], al

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文