; convert: converts numbers between bases ; compile: nasm -f elf -l convert.lst convert.asm ; link: gcc -o convert convert.o ; run: ./convert ; ; Programmer: Spencer Shimko extern printf section .bss decsave: resd 2 ; stores dec->bin conversion binsave: resd 1 section .data ; preset constants, writeable dec1: db '1','2','3','.','3','7','5',0 bin1: dd 01010110111101B ; 10101101.11101 section .text ; instructions, code segment global main ; for gcc standard linking main: ; label push ebp ; save ebp mov ebp,esp ; ebp is callers stack push ebx push edi ; save registers ;parse and convert integer portion of dec->bin mov eax,0 ; accumulate value here mov al,[dec1] ; get first ASCII digit sub al,48 ; convert ASCII digit to binary mov edi,1 ; subscript initialization h1loop: mov ebx,0 ; clear register (upper part) mov bl,[dec1+edi] ; get next ASCII digit cmp bl,'.' ; compare to decimal point je h1fin ; exit loop on decimal point sub bl,48 ; convert ASCII digit to binary imul eax,10 ; * base (ignore edx) add eax,ebx ; increment accumulator inc edi ; increment subscript jmp h1loop h1fin: mov [decsave],eax ; save decimal portion section .data ten: dd 10 global h7loop ; for debugging loop "break h7loop" section .text mov ecx,edi ; move array index into count add ecx,3 ; loop iteration count initialization mov eax,0 ; accumulate value here mov al,[dec1+ecx] ; get last ASCII digit sub al,48 ; convert ASCII digit to binary shl eax,16 ; move binary point dec ecx h7loop: mov edx,0 ; must clear upper dividend idiv dword [ten] ; quotient in eax mov ebx,0 ; clear register (upper part) mov bl,[dec1+ecx] ; get previous ASCII digit cmp bl, '.' ; if we're back at the dec je h7fin ; jmp to finish loop sub bl,48 ; convert ASCII digit to binary shl ebx,16 ; move binary point 16-bits add eax,ebx ; increment accumulator loop h7loop h7fin: mov edx,0 ; must clear upper dividend idiv dword [ten] ; final divide mov [decsave+16],eax ; save fractional portion ; print the bits in decsave: section .bss abits: resb 17 ; 16 characters plus newline & zero terminator section .data fmts: db "%s",0 section .text ; shift decimal portion into abits as ascii mov eax,[decsave] ; restore eax to dec. portion mov ecx,8 ; for printing 1st 8 bits h8loop: mov edx,0 ; clear edx ready for a bit shld edx,eax,1 ; top bit of eax into edx add edx,48 ; make it ASCII mov [abits+ecx-1],dl ; store character ror eax,1 ; next bit into top of eax loop h8loop ; decrement ecx, jump non zero mov byte [abits+7],'.' ; end of dec. portion string mov byte [abits+8],0 ; end of "C" string push dword abits ; string to print push dword fmts ; "%s" call printf add esp,8 mov eax,[decsave+16] ; increment to fractional portion mov ecx,16 ; for printing 3 bits as required in the directions h9loop: mov edx,0 ; clear edx ready for a bit shld edx,eax,1 ; top bit of eax into edx add edx,48 ; make it ASCII mov [abits+ecx-1],dl ; store character ror eax,1 ; next bit into top of eax loop h9loop ; decrement ecx, jump non zero mov byte [abits+3],10 ; end of "C" string at 3 places mov byte [abits+4],0 ; end of "C" string push dword abits ; string to print push dword fmts ; "%s" call printf add esp,8 section .data fmtd: db "%d.",0 fmtd2: db "%d",10,0 section .text ; convert bin->dec ;convert binary integer portion mov eax, 0 ; clear accumulator mov edx, 0 ; clear for bin storage mov edx, [bin1] shld ax, dx, 11 ; shift binary value into eax mov dword [binsave], eax ; end of "C" string push dword [binsave] ; string to print push dword fmtd ; "%d." call printf add esp,8 ; convert binary fractional portion mov ebx, 0 mov edx, [bin1] shl edx, 11 shld bx, dx, 5 ; shift fractional portion into bl mov edx, 0 ; accumulator mov al, 1 ; quotient shl bx, 3 ; place 5 digits at end of bl mov ch, 0 ; our count h10loop: cmp ch, 4 ; check to see that we've done all 5 digits je h10fin ; finished mov cl, 2 ; base to convert from1 mov bh, 0 ; clear bh imul cl ; multiply to get divisor in (1/32, 1/16,1/8,etc) shl bx, 1 ; place single digit in bh cmp bh, 1 ; if if fractional digit is a 1 accumlate value jne h10loop push ecx ; store ecx (loop counter and base) push eax ; store eax (divisor) mov al, 1 ; dividen pop ecx ; restore divisor for use push ecx ; save it again for eax push edx ; idiv will destroy edx mov edx, 0 ; set quotient break1: idiv cl ; i had to do a little finagling to get over the eax/edx limitation ; it isnt optimized at all but doesnt have to be for this project pop edx ; restore edx add dx, ax pop eax ; restore eax pop ecx ; restore ecx inc ch jmp h10loop h10fin: push dword edx ; string to print push dword fmtd2 ; call printf add esp,8 ; return using c-style pops to return stack to correct position ; and registers to correct content pop edi pop ebx mov esp,ebp ; restore callers stack frame pop ebp mov eax,0 ret ; return