Logical error
mov al, byte ptr[si+1]
mov dx:[di], [si] <<-- there is no dx:[di] register.
mov byte ptr[si+1], dx:[di] <<-- memory to memory move not allowed.
mov byte ptr[si], al <<-- `byte ptr` is superflous, because `al` is already byte sized.
You can use a segment register here, but because you're only working with the ds
segment there's no need for that.
So this would be valid:
mov DS:[di],si <-- ds segment (but DS is already the default)
Note that a memory to memory move is not allowed, data has to either come from a constant:
mov [di],1000 <-- direct assignment using a constant
Or has to pass through a register
mov ax,[di]
mov [si],ax <--- memory to memory must be a 2 step process.
Remember [reg]
is memory; reg
is a register
Another error is here:
inc [si] <<-- error, increases some memory location, not `si` the pointer.
dec cl ;decreasing inner loop counter
jnz inner ;back to the beginning of inner loop until counter reaches 0 (resetting in the outer loop)
jmp outer ;if counter reaches zero, get back to outer
This should be:
inc si ;next char in the string
dec cl ;decreasing inner loop counter
jnz inner ;back to the beginning of inner loop until counter reaches 0 (resetting in the outer loop)
jmp outer ;if counter reaches zero, get back to outer
Simplification
Flipping two values around does not require mov
s. Replace this code:
mov bh, al ;main problem-switching values, tried a few different
mov al, ah ;ways of doing it (will show them below), but to no avail
mov ah, bh ;using familiar C syntax
With this much simpler variant, saving a register in the process:
xchg ah, al ;flip chars around
After you're done flipping al
and ah
around you need to write them back to memory, otherwise all that work is for nothing.
xchg ah, al ;flip chars around
mov [si],al ;save flipped values
mov [si+1],ah
Reading past the end of the string
In this snippet you've got the correct idea, but because you're letting [si]
run all the way to the end of the string you're reading 1 byte too many.
inner: ;inner loop
mov al,byte ptr[si] ;<<-- both are correct, but [si+1] will read
mov ah, byte ptr[si+1] ;<<-- past the end of the string at the last byte
So you need to change this section:
DEC cl ;correcting the values, since count goes
dec ch ; from 0 to n-1 instead of 1 to n
To this:
sub bl,2 ;if bl is used to reset inner loop counter it must be
;adjusted as well.
;sub cl,2 ;inner loop from 0 to n-2
mov cl,bl ;bl=cl, so a mov makes more sense
dec ch ;outer loop from 0 to n-1 instead of 1 to n
Finally efficiency tips
Never read from memory if you don't have to.
Change this code:
MOV si, offset buffer
INC si ;going from buffer size to actual length
;of the string
MOV cl, [si] ;string length - loop counter
mov ch, [si] ;string length - loop counter
mov bl, [si] ;bl will be used to reset inner loop counter
To this:
MOV si, offset buffer+1 ;start at length byte of the string
MOV cl, [si] ;string length - loop counter
mov ch, cl ;string length - loop counter
mov bl, cl ;bl will be used to reset inner loop counter
There are more speed optimizations that can be done but I don't want to overcomplicate things.