Comparing AX register against zero on 8086

66 views Asked by At

I have a small program to convert a binary string into decimal. I store it in BX correctly but then a problem appears when I want to print BX in the following loop. It breaks, even with AX being bigger than zero:

LEA di, fdnum
mov cx,0ah
xor ax,ax 
mov ax,bx 
xor dx,dx
ST : ; bx still bigger than 0 

div cx
mov bx ,ax
add dl ,30h
MOV AH, 02h ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;tester
INT 21h ; print the length of the binary number
mov [di],dl
inc di
mov ax,bx 
xor dx,dx
CMP AX, 0
JG ST

This is the full code:

.model small
.STACK 300h
.data
    welcome DB 'Welcome, please enter binary number max(10 digits)',0Ah,0Dh,'Press e to end',0Ah,0Dh,'$'
    msg1 DB 0Ah,0Dh,'You entered: ',0Ah,0Dh,'$'
    error DB ' Not an option, sorry. Enter again: ',0Ah,0Dh,'$'
    obtions DB 0Ah,0Dh,0Ah,0Dh,'convert it to ',0Ah,0Dh,'1-decimal',0Ah,0Dh,'2-octal',0Ah,0Dh,'3-hexa',0Ah,0Dh, '9-End',0Ah,0Dh,'$'
    bnum DB 11 DUP(?) ; buffer to store the binary number
    rbnum DB 11 DUP(?) ; buffer to store the reversed binary number
    fdnum DB 11 DUP(?) ; buffer to store the final decimal answer number
    length_msg db 0Ah,0Dh,'Length is: ','$'
    lenght_bnum db 0 ; lenght of the binary number
    fans db 0 ; final answer
    hex_num db 5 DUP ('$') ; buffer to store the hexadecimal number
    endl DB 0Ah,0Dh
    
    dec_result db 6 dup (?) ; decimal result will be stored here 
    oct_result db 5 dup (?) ; octal result will be stored here 
    dec_result_len db 0
.code
MAIN PROC  
    .startup

    ; print welcome
    MOV ah ,09h
    LEA dx , welcome
    int 21h
    xor ax, ax ; clear ax register

    
    ; Read string
    LEA SI, bnum ; load the address of the buffer into SI
    MOV CX, 10 ; set the counter to 10
    mov bx, 0 ; counter for the lenght of the binary number
READ:
    MOV AH, 01h 
    INT 21H ; read a character
    MOV [SI], AL ; store the character in the buffer
    CMP AL, 0Dh ; if equal to carriage return "Enter", jump string_end
    JE string_end ; if equal, jump string_end
    INC SI ; increment the pointer
    XOR AX, AX
    inc bx 
    LOOP READ ; repeat until CX = 0
string_end:
    MOV BYTE PTR [SI], '$' ; add the string terminator
    ;;;reverse bnum
    dec si
    LEA di, rbnum ; load the address of the buffer into SI
    MOV CX, bx ; set the counter to 10
reverse:
    mov al ,[si] 
    mov [di] ,al
    inc di
    dec si
    loop reverse
    
    ; add the string terminator
    inc di
    MOV BYTE PTR [SI], '$' ;
    ;;;
    LEA DX, msg1 
    MOV AH, 09h 
    INT 21h ; print msg1 "You entered:"

    LEA DX, bnum 
    MOV AH, 09h 
    INT 21h ; print the binary number

    xor si, si
    lea dx, length_msg
    mov ah, 09h
    int 21h ; print "Length is:"

    mov lenght_bnum, bl ; store the lenght of the binary number in lenght_bnum
    mov dl, lenght_bnum
    add dl, 30h
    MOV AH, 02h
    INT 21h ; print the lenght of the binary number


    ; print obtions
obtion:
    mov ah, 09h
    LEA dx, obtions
    int 21h

    ; read obtion and store it in al
    mov ah, 01h ; 
    int 21h ; 
    
    
    ;switch
    cmp al,'1'
    je decimal
    cmp al,'2'
    je octal
    cmp al,'3'
    je hexadecimal
    cmp al,'9'
    je endd
    
    ; print error if not 1 or 2 or 3 or 9, and jump to obtion
    mov ah ,09h 
    LEA dx , error
    int 21h
    jmp obtion
    
decimal:
    mov cx ,bx 
    xor bx ,bx ;reset to zero to store answer
    mov dx ,1  ;
    LEA di, rbnum
cbd: ; covert binary to decimal loop
    cmp [di],'0'
    je novalue ;if current digit equal 0 skip
    add bx ,dx
novalue:
    inc di
    shl dx, 1 ;multi dx by 2 
    loop cbd
    
    ;;;;;;;;;;;;;;;;strore decimal in string 
    LEA di, fdnum
    mov cx,0ah
    xor ax,ax 
    mov ax,bx 
    xor dx,dx
    ST : ; bx still bigger than 0 
    
    div cx
    mov bx ,ax
    add dl ,30h
    MOV AH, 02h ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;tester
    INT 21h ; print the lenght of the binary number
    mov [di],dl
    inc di
    mov ax,bx 
    xor dx,dx
    CMP AX, 0
    JG ST
     dec di
     ;;;;;;;;;;;;;;;;;;;;
         mov ah ,2
         LEA si, fdnum
 printt :
     
     mov al , [di]
     int 21
     dec di
     cmp di,si
     jne printt
     mov bl , [di]
     int 21
    jmp endd
    
   
    
octal:
    jmp endd

hexadecimal:

    jmp endd
    
endd:
    .EXIT 
MAIN ENDP
END MAIN
1

There are 1 answers

0
Sep Roland On

Your displaying of the length will fail should the user decide to input the allowed maximum number of binary digits, which you have set at 10! This will happen because the simple conversion that reads add dl, 30h will then produce the character : that lies outside of the range ["0","9"]. Maybe set the limit to 9 binary digits instead?

Comparing AX register against zero 8086

Although convoluted, your conversion routine from a binary number to its reverse decimal representation is correct. The reason why you think something is wrong here, is that you don't actually display the result, and that is because you're not passing the character in the DL register that DOS is expecting! Moreover, you must invoke DOS via int 21h (so not via int 21), the hexadecimal suffix is very important here!

printt :
  mov al , [di]   <<<<<<<<<<<<<<  Needs to be DL
  int 21          <<<<<<<<<<<<<<  Needs to be 21h
  dec di
  cmp di,si
  jne printt
  mov bl , [di]   <<<<<<<<<<<<<<  Needs to be DL
  int 21          <<<<<<<<<<<<<<  Needs to be 21h

I don't see the point in adding a $ string terminator to the inverse of the input at rbnum. You will not use it afterwards, and anyway currently you erroneously write a "$" in front of the bnum buffer!
If you did want to display the reversed input then change:

; add the string terminator
inc di
MOV BYTE PTR [SI], '$' ;

into

; add the string terminator
MOV BYTE PTR [DI], '$' ;

Next code shows that you don't need the inverse string to calculate the binary value. You can arrive at it, straight from the original input at bnum:

decimal:
  xor  ax, ax     ; reset to zero to store answer
  dec  bx         ; BX is [0,9]
  js   wasEmpty
  mov  dx, 1      ; Weight of the current bit
cbd:              ; Convert binary to decimal loop
  cmp  BYTE PTR [bnum + bx], '0'
  je   novalue    ; if current digit equal 0 skip
  add  ax ,dx
novalue:
  shl  dx, 1      ; Multiply DX by 2 
  dec  bx
  jns  cbd
wasEmpty: