views:

713

answers:

2

Hi folks. 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 
+2  A: 

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)
Martin
Thank you, this helped!
sunnyohno
A: 

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

sunnyohno