Author Topic: Decimal To Binary  (Read 16432 times)

Offline RagingGrim

  • Jr. Member
  • *
  • Posts: 28
Decimal To Binary
« on: December 28, 2014, 06:03:20 AM »
So I'm just toying around with binary so I have a few new tricks to teach when school starts again next year ( gotta hate physics classes! ) but anyway I got this working which prints out a decimal number's binary in reverse ( the quotients ) ; So now I got a program that turns 10 into 0101 ( 1010 would be correct ) ; How do I reverse these bits? Should I be storing them as a specific datatype? I wrote the same function in delphi ages ago and I handled the sequence as a string which made reversing it that much easier but then again I don't want to do that this time.

Code: [Select]
BITS 32
extern __cprintf
extern __getch
extern _ExitProcess
global main

section .data
CharFormat db "%",0
State_One db "1",0
State_Zero db "0",0
StateMsg db 0ah,"Quotient %i",0ah,"Remainder %i",0ah,0
IntFormat db 0ah,"Result : %i",0ah,0
DoneMsg db 0ah,"Done",0ah,0
ANumber dd 10
Answer dd 0

section .text
main:
mov EAX , 1500
mov dword [Answer]  ,1500
;Save Initial Value
;DIV performs unsigned integer division. The explicit operand provided is the divisor; the dividend and destination operands are implicit, in the following way:

;For DIV r/m8, AX is divided by the given operand; the quotient is stored in AL and the remainder in AH.
;For DIV r/m16, DX:AX is divided by the given operand; the quotient is stored in AX and the remainder in DX.
;For DIV r/m32, EDX:EAX is divided by the given operand; the quotient is stored in EAX and the remainder in EDX.
aLoop:
mov EDX , 0
mov EAX , dword [Answer]
mov ECX , 2

DIV ECX
mov dword [Answer] , EAX
push EDX
push dword [Answer]
push StateMsg
CMP EAX,0
JE Done
call __cprintf
call __getch
JMP aLoop


Done:
push 1
push EAX
push StateMsg
call __cprintf
call __getch

Is there some sort of an array I can use? Suggestions?

Thanks! ( working with nasm on Win64 )

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Decimal To Binary
« Reply #1 on: December 28, 2014, 07:10:59 AM »
Well, this is for dos and not really suitable for 32-bit code... but I happened to have it on hand... :)
Code: [Select]
; prints the value of ax as decimal, hex, and binary ascii
; nasm -f bin -o showax.com showax.asm

org 100h

section .text
    mov ax, 12345

    call ax2dec
    call newline
    call ax2hex
    call newline
    call ax2bin

    mov ah, 4Ch
    int 21h
;--------------

;--------------
ax2dec:
    push ax
    push bx
    push cx
    push dx

    mov bx, 10          ; divide by ten
    xor cx, cx          ; zero our counter
.push_digit:
    xor dx, dx          ; clear dx for the div
    div bx              ; dx:ax/bx -> ax quotient, dx remainder
    push dx             ; save remainder
    inc cx              ; bump digit counter
    or ax, ax           ; is quotient zero?
    jnz .push_digit     ; no, do more

    mov ah, 2           ; print character subfunction
.pop_digit:
    pop dx              ; get remainder back
    add dl, '0'         ; convert to ascii character
    int 21h             ; print it
    loop .pop_digit     ; cx times

    pop dx
    pop cx
    pop bx
    pop ax
    ret
;-------------------

;-------------------
ax2hex:
    push cx
    push dx

    mov cx, 4           ; four digits to show

.top
    rol ax, 4           ; rotate one digit into position
    mov dl, al          ; make a copy to process
    and dl, 0Fh         ; mask off a single (hex) digit
    cmp dl, 9           ; is it in the 'A' to 'F' range?
    jbe .dec_dig        ; no, skip it
    add dl, 7           ; adjust
.dec_dig:
    add dl, 30h         ; convert to character

    push ax
    mov ah, 2           ; print the character
    int 21h
    pop ax

    loop .top

    pop dx
    pop cx
    ret
;--------------------------

;--------------------------
ax2bin:
    push cx
    push dx
    mov cx, 16
.top
    rcl ax, 1     ; rotate and set/clear carry
    mov dl, '0'
    adc dl, 0     ; make it '1' if carry set

    push ax
    mov ah, 2     ; print it
    int 21h
    pop ax

    loop .top

    pop dx
    pop cx
    ret
;----------------------------

;----------------------------
newline:
    push ax
    push dx

    mov ah, 2       ; print character in dl
    mov dl, 13      ; carriage return
    int 21h
    mov dl, 10      ; and linefeed
    int 21h

    pop dx
    pop ax
    ret
;----------------------------

Besides giving us the remainders in the wrong order, "div" is dog slow. For dividing by two, or powers of two, a shift or rotate might be more appropriate. As you can see, I rotate a bit into the carry flag and then use "adc" to bump the character '0' up to '1' if necessary. (I only use dl 'cause that's what dos wants to print) This won't fit into your "framework" very well, but might give you some ideas...

I'll try to get back to you on this. (I'll get back to you on the private message Real Soon Now, too. Sorry for the delay - just haven't been "in the mood" to write much lately - sorry.)

Later,
Frank





Offline RagingGrim

  • Jr. Member
  • *
  • Posts: 28
Re: Decimal To Binary
« Reply #2 on: December 28, 2014, 08:12:01 AM »
No problem! I considered using shifts but I wasn't sure about the math behind it and what happens to what, while I wait I'll take look at what happens and look take a deeper look into the operations ( including rotate which I have never heard of but I suppose it's like a shift XD )

I did as I said I would and i've been playing around with the rotate operations ; I get what they do although I'm a bit lost .

Code: [Select]
mov eax,0b1010
ror eax,1

so rotate 1010 right with one would result in 0101 which is 5 and mighty fine!

However if I use ror eax,2 I get a negative value . The videos I watched mentioned a few things amongst which now seems the most striking is that the rotate operations don't work on the result if you rotate 2 times for example. I actually have no idea what's meant by that but I'll continue twiddling and reading.

Maybe I had the wrong idea but if you had a binary value of 11101 and rotated it in any direction with the amount of elements ( if I can put it like that eg. 5 ) you would have reversed the sequence? If I try this on 1010 I get a decimal value of  -1610612736 which in binary is -1100000000000000000000000000000 (__cprintf handles the conversion from binary to int so I suppose it might be something wront there as well ). Somehow that doesn't seem right. For one I'm not sure what a signed ( negative specifically ) integer looks like in binary. I suppose a 0/1 would be used to represent positive and negative . I should probably look into that.

I am aware of what the carry flag is ( well not it's exact definition but I understand why it's there ) although I don't see why I'd use this here. If i rotate left with four the binary value 1010 I get a result of 160 in decimal which is equal to 10100000. It seems like those four zeros just get paddded in :/
Thanks Again!
« Last Edit: December 28, 2014, 05:15:41 PM by RagingGrim »

Offline Gunner

  • Jr. Member
  • *
  • Posts: 74
  • Country: us
    • Gunners Software
Re: Decimal To Binary
« Reply #3 on: December 30, 2014, 03:12:40 AM »

Offline RagingGrim

  • Jr. Member
  • *
  • Posts: 28
Re: Decimal To Binary
« Reply #4 on: December 30, 2014, 06:37:20 PM »
That's an interesting way to do it :O

I was curious about a few things. For one when I call DIV for example isn't that number converted to binary anyway ( seeing as how computers work with binary ) . The other is that by using shifts on the integers you the program converts the integer to a binary value and shifts the binary value ( I guess this is the same as the first question ) .

Am I wasting my time doing this ? Or is there something I don't understand properly? ^^

Offline HD1920.1

  • Jr. Member
  • *
  • Posts: 40
Re: Decimal To Binary
« Reply #5 on: January 01, 2015, 06:25:47 AM »
Code: [Select]
mov eax,0b1010
ror eax,1
Rotate does only work when the last bit is zero. Use shift, that works in any cases and stores the reminder of the division into the carry flag.

Offline RagingGrim

  • Jr. Member
  • *
  • Posts: 28
Re: Decimal To Binary
« Reply #6 on: January 01, 2015, 08:23:25 AM »
I couldn't find anything regarding rotate only working when the last bit is zero but I'll continue looking at that.

As for shift storing the remainder in the carry flag ; A shift would divide or multiply depending on the correction you shift to ? It also seems more apparent that shift actually shifts rather than multiply and divide - I guess my point is that the division/multiplication is a result of the shift rather than an operation performed on the bits.

« Last Edit: January 01, 2015, 08:59:06 AM by RagingGrim »