Octal to hexadecimal in assembly language

74 Views Asked by At

I have written the code but it does not convert accordingly.

.MODEL SMALL
.STACK 100H

.DATA
    INPUT_MSG DB 'Enter an octal number: $'
    OUTPUT_MSG DB 'The hexadecimal number is: $'
    INPUT_NUM DW ?
    HEX_NUM DB 3 DUP(0)
    HEX_DIGITS DB '0123456789ABCDEF'

.CODE
MAIN PROC
    MOV AX, @DATA
    MOV DS, AX
    
    ; Display input message
    LEA DX, INPUT_MSG
    MOV AH, 9
    INT 21H
    
    ; Read octal input number
    MOV AH, 01H
    INT 21H
    SUB AL, 30H ; convert ASCII digit to binary
    MOV BL, AL ; save input number in BL
    
    MOV AH, 01H
    INT 21H
    SUB AL, 30H ; convert ASCII digit to binary
    MOV CL, AL ; save input number in CL
    
    MOV AH, 01H
    INT 21H
    SUB AL, 30H ; convert ASCII digit to binary
    MOV DL, AL ; save input number in DL
    
    ; Convert octal to hexadecimal
    MOV AL, BL ; load first digit
    AND AL, 07H ; mask upper bits
    MOV BH, 00H ; clear high byte of BX
    MOV BL, AL ; move first digit to low byte of BX
    MOV AL, BH ; clear AL
    MOV BL, HEX_DIGITS[BX] ; lookup hexadecimal digit
    MOV HEX_NUM[0], BL ; store first digit in HEX_NUM
    
    MOV AL, CL ; load second digit
    AND AL, 07H ; mask upper bits
    MOV BH, 00H ; clear high byte of BX
    MOV BL, AL ; move second digit to low byte of BX
    MOV AL, BH ; clear AL
    MOV BL, HEX_DIGITS[BX] ; lookup hexadecimal digit
    MOV HEX_NUM[1], BL ; store second digit in HEX_NUM
    
    MOV AL, DL ; load third digit
    AND AL, 07H ; mask upper bits
    MOV BH, 00H ; clear high byte of BX
    MOV BL, AL ; move third digit to low byte of BX
    MOV AL, BH ; clear AL
    MOV BL, HEX_DIGITS[BX] ; lookup hexadecimal digit
    MOV HEX_NUM[2], BL ; store third digit in HEX_NUM
    
    ; Display output message and hexadecimal number
    LEA DX, OUTPUT_MSG
    MOV AH, 9
    INT 21H
    
    MOV DL, HEX_NUM[0]
    MOV AH, 02H
    INT 21H
    
    MOV DL, HEX_NUM[1]
    MOV AH, 02H
    INT 21H
    
    MOV DL, HEX_NUM[2]
    MOV AH, 02H
    INT 21H
    
    ; Exit program
    MOV AH, 4CH
    INT 21H
MAIN ENDP

END MAIN
1

There are 1 best solutions below

2
Sep Roland On
INPUT_MSG DB 'Enter an octal number: $'

The input only becomes 'an octal number' (singular) once you start combining the octal digits (plural) that are part of that number.

An octal digit occupies 3 bits in the binary representation of the number and so the decomposition for a 3-digit octal number is:

FirstDigit * 64 + SecondDigit * 8 + ThirdDigit

A multiplication by 8 in assembly translates to a 3x shift to the left, and a multiplication by 64 is the result of doing that particular shift to the left twice.

Assuming the user input is valid (only using digits '0' thru '7' and not exceeding 377o), the code becomes:

; Read octal input number
MOV  CL, 3   ; CONST (to shift 3x to the left) [8086]
MOV  AH, 01h
INT  21h
SUB  AL, 30h ; convert ASCII digit to binary
MOV  BL, AL  ; Add FirstDigit

MOV  AH, 01h
INT  21h
SUB  AL, 30h ; convert ASCII digit to binary
SHL  BL, CL  ; Make room to add the following digit
             ; This is the 1st time that FirstDigit gets shifted to the left, so *8
OR   BL, AL  ; Add SecondDigit

MOV  AH, 01h
INT  21h
SUB  AL, 30h ; convert ASCII digit to binary
SHL  BL, CL  ; Make room to add the following digit
             ; This is the 2nd time that FirstDigit gets shifted to the left, so *64
             ; This is the only time that SecondDigit gets shifted to the left, so *8
OR   BL, AL  ; Add ThirdDigit

The BL register now holds the octal number. As an example consider the octal number 253o that leaves the decimal value 171 (2 * 64 + 5 * 8 + 3) in the register.
The next task is to print this value as the hexadecimal number ABh. An hexadecimal digit occupies 4 bits in the register and we need to print the most significant digit first:

; Display output message and hexadecimal number
MOV  DX, OFFSET OUTPUT_MSG
MOV  AH, 09h
INT  21h

MOV  BH, 0
MOV  SI, BX
MOV  CL, 4              ; CONST (to shift 4x to the right) [8086]
SHR  BX, CL             ; Only keep most significant hex digit
MOV  DL, HEX_DIGITS[BX] ; lookup hexadecimal digit
MOV  AH, 02h
INT  21h
AND  SI, 15             ; Only keep least significant hex digit
MOV  DL, HEX_DIGITS[SI] ; lookup hexadecimal digit
MOV  AH, 02h
INT  21h