Search code examples
assemblymasmirvine32

MASM - How to convert binary to hexa?


I'm using the MASM syntax with Irvine32 Library on Visual Studio.

I've attempted to make this program convert binary to decimal and vise versa, and now I'm stuck on how to convert binary to hexa and vise versa

Here's my code

INCLUDE Irvine32.inc



.data
    str1 BYTE ">>> Please select the conversion type: ", 0
    str2 BYTE " 1. Binary to Decimal", 0
    str3 BYTE " 2. Decimal to Binary", 0
    str4 BYTE " 3. Exit", 0 
    str5 BYTE "-----------------------------------------", 0
    str6 BYTE "Enter your choice: ", 0
    str7 BYTE "Please Enter 8-bit binary digits (e.g., 11110000): ", 0
    str8 BYTE "The decimel integer of ", 0
    str9 BYTE " is ", 0
    str10 BYTE " ", 0
    str11 BYTE "Please Enter a decimal integer less than 256: ", 0
    str12 BYTE "The binary of ", 0
    str13 BYTE " is ", 0
    str14 BYTE " ", 0
    str15 BYTE "Bye.", 0
    choice DWORD ?
    num1 BYTE 9 DUP(? )
    num2 WORD ?
    numLength DWORD 0
    outLoop DWORD 0
    base DWORD 2
    deciNum DWORD ?

.code
main PROC
    
    _mainprog :             ;USED TO DISPLAY THE MENU & EXIT
    mov edx, offset str1 
    call WriteString
    call crlf
    mov edx, offset str2
    call WriteString
    call crlf
    mov edx, offset str3
    call WriteString
    call crlf
    mov edx, offset str4
    call WriteString
    call crlf
    mov edx, offset str5
    call WriteString
    call crlf
    mov edx, offset str6
    call WriteString
    call ReadDec            ;DISPLAY OUTPUT
    mov choice, eax         ;EAX = 1
    cmp choice, 1           ;IF = 1
    je _proc1               ;JUMP TO PROC1
    cmp choice, 2           ;IF = 2
    je _proc2               ;JUMP TO PROC2
    cmp choice, 3           ;IF = 3
    je _proc3               ;JUMP TO PROC3

    _proc1 :                ;BINARY TO DECIMAL
    mov edx, offset str7    
    call WriteString
    mov edx, offset num1    ;ASSIGN NUM1 TO EDX TO WRITE THE BINARY IN STRING FORMAT
    mov ecx, sizeof num1    ;ASSIGN TO ECX TO ACT AS THE COUNTER (COUNT THE LENGTH OF THE BINARY DIGIT)
    call ReadString         ;USER INPUT BINARY NUMBER
    mov numLength, eax      ;USER INPUT EAX STORED IN NUMLENGTH
    mov eax, 0              ;EAX ASSIGNED TO 8
    mov esi, 0              ;ESI TO ACCESS THE STRING BINARY INPUT THAT WE ENTERED
    mov ecx, numLength      
    whileProc1 :
    cmp ecx, 0              ;COMPARE COUNTER WITH 0
    je printResult          ;IF ECX =/ 0, IT WILL NOT JUMP TO PRINT RESULT
    mov outLoop, ecx        ;8 ASSIGNED TO OUTLOOP AND ASSIGNED TO REGISTER ECX
    ifProc :                
    cmp num1[esi], '0'      ;IF 1ST VALUE IN THE BINARY DIGIT = 0
    je incEsiProc           ;JUMP TO INCREASE ESI PROC
    elseIfProc:
    cmp num1[esi], '1'      ;IF 1ST VALUE IN BINARY DIGIT = 1
    mov ecx, numLength      ;NUMLENGTH ASSIGNED TO ECX
    sub ecx, esi            ;
    dec ecx
    mov eax, 1
    whileProc2 :
    je stopProc
    mov ebx, base
    mul ebx
    dec ecx
    jmp whileProc2
    stopProc :
    add deciNum, eax
    jmp incEsiProc
    incEsiProc :
    inc esi
    mov ecx, outLoop
    dec ecx
    jmp whileProc1
    printResult :
    mov edx, offset str8
    call WriteString
    mov edx, offset num1
    call WriteString
    mov edx, offset str9
    call WriteString
    mov eax, deciNum
    call WriteDec
    mov edx, offset str10
    call WriteString
    call crlf
    call crlf
    jmp _mainprog

    _proc2:                 ;DECIMAL TO BINARY
    mov edx, offset str11
    call WriteString
    mov edx, offset num2
    call ReadInt
    mov num2, ax
    mov ebx, 1
    mov edx, offset str12
    call WriteString
    mov ax, num2
    call WriteDec
    mov edx, offset str13
    call WriteString
    call WriteBinB
    mov edx, offset str14
    call WriteString
    call crlf
    call crlf
    jmp _mainprog

    _proc3:
    mov edx, offset str15
    call WriteString
    call crlf
    call WaitMsg
    exit
main ENDP
END main


Able to ask user for input a number and convert hexa to binary/decimal and vise versa


Solution

  • This is how program looks now, I used this algorithm for conversion binary string to integer. :)

    1. Binary to Decimal
    2. Decimal to Binary
    3. Binary to Hex
    4. Hex to Binary
    include \masm32\include\Irvine32.inc
    includelib \masm32\lib\Irvine32.lib
    includelib \masm32\lib\kernel32.lib
    includelib \masm32\lib\user32.lib
    
    .data
        menu             BYTE "-----------------------------------------",13,10         
                         BYTE "    Please select the conversion type ",13,10 
                         BYTE "-----------------------------------------",13,10
                         BYTE " 1. Binary to Decimal",13,10
                         BYTE " 2. Decimal to Binary",13,10
                         BYTE " 3. Binary to Hex",13,10
                         BYTE " 4. Hex to Binary",13,10
                         BYTE "-----------------------------------------",13,10                     
                         BYTE " 5. Exit",13,10
                         BYTE "-----------------------------------------",13,10
                         BYTE "Enter your choice: ",0
        menu_error       BYTE "*** You entered wrong number. Try again.", 0    
       
        bin_input_msg    BYTE "Please enter 8-bit binary digits (e.g., 11110000): ", 0
        bin_string_error BYTE "*** Cannot convert binary string to integer. Try again.", 0 
    
        bin_msg_1        BYTE "The binary of ", 0
    
        dec_input_msg    BYTE "Please enter a decimal integer less than 256: ", 0
        dec_input_error  BYTE "*** Enter value from range 0 - 255.", 0
    
        dec_msg_1        BYTE "The decimal integer of ", 0    
    
        hex_input_msg    BYTE "Please enter a hex value: ", 0
      
        hex_msg_1        BYTE "The hex of ", 0
    
        is               BYTE " is ", 0    
        exit_msg         BYTE "Bye.", 0
        
        binary_string    BYTE 9 DUP(0)
     
        InitFlag         DB 0
        consoleInHandle  DWORD ?        ; handle to console input device
        consoleOutHandle DWORD ? 
    ;----------------------------------------------------------------------   
        CheckInit MACRO
    
        ; Helper macro
        ; Check to see if the console handles have been initialized
        ; If not, initialize them now.
    
       LOCAL exit
          cmp InitFlag,0
          jne exit
          call Initialize
         exit:
       ENDM   
         
    ;----------------------------------------------------------------------
    .code
    main PROC
    
    ;----------------------------------------------------------------------
    ;   MENU    
        
        _mainprog: 
            call Clrscr
                    
            mov edx, offset menu
            call WriteString        
            call ReadDec            ;eax = user's choice       
            call crlf           
            
            cmp eax, 1           
            je _bin_dec   
            cmp eax, 2           
            je _dec_bin             
            cmp eax, 3           
            je _bin_hex   
            cmp eax, 4           
            je _hex_bin             
            cmp eax, 5           
            je _exit                
            jmp _wrong_number
            
    ;----------------------------------------------------------------------
    ;   BINARY TO DECIMAL
    
        _bin_dec:
            call BinaryString2Int                 
            mov edx, offset dec_msg_1
            call WriteString
            mov edx, offset binary_string 
            call WriteString
            mov edx, offset is
            call WriteString
            call WriteDec
            call _new_line       
    
            jmp _mainprog
    
    ;----------------------------------------------------------------------
    ;   DECIMAL TO BINARY
    
        _dec_bin:                 
            mov edx, offset dec_input_msg
            call WriteString
            call ReadDec
            cmp eax,255             ;check if value is 0 - 255 
            ja GreaterThan255
            
            mov edx, offset bin_msg_1
            call WriteString
            call WriteDec
            mov edx, offset is
            call WriteString
            mov ebx, 1             ; 1 - byte, 2 - word, 4 - dbl word
            call WriteBinB
            call _new_line 
                  
            jmp _mainprog
            
            GreaterThan255:
                call crlf 
                mov edx, offset dec_input_error
                call WriteString
                call _new_line       
       
                jmp _dec_bin
    
    ;----------------------------------------------------------------------
    ;   BINARY TO HEX
    
        _bin_hex:                
            call BinaryString2Int  
            mov edx, offset hex_msg_1
            call WriteString
            mov edx, offset binary_string
            call WriteString
            mov edx, offset is
            call WriteString
            call WriteHex
            call _new_line       
            
            jmp _mainprog
    
    ;----------------------------------------------------------------------
    ;   HEX TO BINARY
    
        _hex_bin:                 
            mov edx, offset hex_input_msg
            call WriteString
            call ReadHex        
            mov edx, offset bin_msg_1
            call WriteString       
            call WriteHex
            mov edx, offset is
            call WriteString
            mov ebx,4              ; 1 - byte, 2 - word, 4 - dbl word
            call WriteBinB
            call _new_line
            
            jmp _mainprog
            
    ;----------------------------------------------------------------------
    ;   NUMBER IS NOT ON THE MENU LIST
    
        _wrong_number:      
            mov edx, offset menu_error
            call WriteString
            call _new_line
    
            jmp _mainprog
    
    ;----------------------------------------------------------------------
    ;   NEW LINE
    
        _new_line:
            call crlf
            call crlf
            call WaitMsg            
            call crlf        
            ret
            
    ;----------------------------------------------------------------------
    ;   EXIT
    
        _exit:
            mov edx, offset exit_msg
            call WriteString
            call crlf
            call WaitMsg
            exit
            
    main ENDP
    
    BinaryString2Int Proc
    
    ;----------------------------------------------------------------------
    ;   INPUT - BINARY STRING
    
        _bin_string_input:
            mov edx, offset bin_input_msg    
            call WriteString
            mov edx, offset binary_string    
            mov ecx, sizeof binary_string     
            call ReadString  
    
    ;----------------------------------------------------------------------
    ;   BINARY STRING TO INT
    ;   Algorithm taken from -> https://stackoverflow.com/a/49548057/20889367
    
        mov edi, offset binary_string
        movzx   eax, byte ptr [edi]    ; start with the first digit
        sub     eax, '0'               ; convert from ASCII to number
        cmp     al, 1                  ; check that it's a decimal digit [0..1]
        jbe     _loop_entry            ; too low -> wraps to high value, fails unsigned compare check
    
        xor     eax,eax                ; else: bad first digit: return 0
        jmp conversionError ;ret
    
        ; rotate the loop so we can put the JCC at the bottom where it belongs
        ; but still check the digit before messing up our total
    
        _next_digit:                  
            ; lea     eax, [eax*4 + eax]   
            lea     eax, [eax*2 + ecx]    ; total = total*2 + digit
            ; imul eax, 2  / add eax, ecx
    
        _loop_entry:
            inc     edi
            movzx   ecx, byte ptr[edi]
            sub     ecx, '0'
            cmp     ecx, 1
            jbe     _next_digit  
            ret                            ; return with total in eax 
    
            conversionError:
                call crlf 
                mov edx, offset bin_string_error
                call WriteString
                call crlf  
                call crlf        
                jmp _bin_string_input
        ret
    BinaryString2Int Endp
    
    Initialize PROC private
    ;----------------------------------------------------------------------
    ;   Get the standard console handles for input and output,
    ;   and set a flag indicating that it has been done.
    ;   Updated 03/17/2003
    
        pushad
    
        INVOKE GetStdHandle, STD_INPUT_HANDLE
        mov [consoleInHandle],eax
    
        INVOKE GetStdHandle, STD_OUTPUT_HANDLE
        mov [consoleOutHandle],eax
    
        mov InitFlag,1
    
        popad
        ret
    Initialize ENDP
    END main