I have this program that should return the inverse of a character or characters eg A -> Z, B -> Y etc. The code works and properly converts the character but the program doesn't display it on screen or loop when it should, instead, it returns control at int 21h
.
.8086
.model small
.data
; Variables
prompt_in db 0Dh, "Input: $"
prompt_out db 0Dh, 0Ah, "Output: $"
.code
main proc
; Load Variables
mov ax, @data
mov ds, ax
; Display Input Prompt
mov dx, offset prompt_in
mov ah, 09h
int 21h
mov cl, 00
mov ah, 01h
; Read input and push to BX until User presses Return (Enter)
read:
int 21h
mov bl, al
push bx
inc cx
cmp al, 0Dh
jz return
jmp read
; Display Output Prompt
return:
mov dx, offset prompt_out
mov ah, 09h
int 21h
; Calculate Inverse Letter and Display
calc:
mov ah, 00
pop bx
cmp bl, 0Dh
jz calc
mov al, bl
sub al, 41h
mov cl, 19h
mov ch, 2
mul ch
sub cl, al
add bl, cl
mov dl, bl
int 21h ; Stops Code Here without Displaying anything more
loop calc ; Doesn't Loop Here
mov ah, 4Ch
int 21H
main endp
end main
The DOS service to write a character to standard output is int 21h
with ah = 02h
. But that's not what you are doing:
Just after the calc
label you load ah
with the value 00
, not 02h
.
A few lines later, you have a mul ch
instruction. Remember that mul
on x86 is widening; an 8-bit multiply produces a 16-bit result in ax
, which in particular overwrites ah
. Now in your program, the result will probably fit in 8 bits, so that ah
is set to zero again.
When you call int 21h
with ah = 0
, you invoke the terminate program service (a deprecated predecessor to int 21h / ah = 4Ch
), which is why your program terminates at this point.
The quick solution is to insert mov ah, 02h
just before the int 21h
, and remove the earlier mov ah, 00
which is wrong and also redundant.
You can improve the program further by noticing that multiplication by 2 is the same as a left shift by 1, which is faster and doesn't involve so many registers. It won't be quite the same if the result overflows 8 bits (the high part of the result is lost, instead of being put in ah
) but you don't expect to handle that case anyway. So your mov ch, 2 / mul ch
can be replaced with simply shl al, 1
. This moreover doesn't touch ah
at all.