Hey,
I am writing an assembly program that take a decimal and converts it to base 7. It is not a requirement for it to be displayed back to the user in the correct order. The order can be backwards. So far I have this code...I am not sure where I am going wrong with it. Any ideas would be AWESOME!


TITLE MASM Template                        (main.asm)


INCLUDE Irvine32.inc
.data

base7 BYTE "Base 7 (In reverse order) is ",0


.code
main PROC

call readdec

mov edx,OFFSET base7
call WriteString



mov bl, 7
begin1:
div bl


cmp ah,0
je theend
mov ax,ah
call writedec
mov ax,al
jmp begin1

theend:
mov ax,ah
call writedec

call crlf

    exit
main ENDP

END main


I understand what I need to do...I need to divide, check if the remainder is 0, print out the remainder, and then move the quotient into eax to start the process over again.

What I'm having trouble with is understading how to mov the registars to eax so that they can be displayed back to the user using the "call writedec" function. I am also new to the syntax of things, so bear with me in stupid little mistakes.

Thanks in advance everyone!

-Mallard
Posted on 2011-09-28 19:57:29 by msmallard
What I'm having trouble with is understading how to mov the registars to eax so that they can be displayed back to the user using the "call writedec" function.
Don't be afraid to use other registers such as esi edi ebp, AFAIK irvine32 library functions preserve all registers. If that is not enough there is always STACK. PUSH and POP - LIFO.

	call readdec
mov edx,OFFSET base7
call WriteString
mov ebx,eax
mov ecx,7
do:
mov eax,ebx
xor edx,edx; requirement for div, high dword of EDX:EAX = 0
div ecx
mov ebx,eax
mov eax,edx
call writedec
call crlf
or ebx,ebx
jnz do

	call readdec
mov edx,OFFSET base7
call WriteString
mov ecx,7
do:
xor edx,edx
div ecx
push edx; preserving edx not needed, but we'll do it anyway
push eax
mov eax,edx
call writedec
call crlf
pop eax
pop edx;
or eax,eax
jnz do



Posted on 2011-09-29 10:25:03 by drizz
You've got some "fairly serious" errors in your code, as posted:

...
mov ax,ah
...
mov ax,al
...
mov ax,ah

These instructions don't exist! I think you'll find that your assembler burps up an error message when you try it. Changing "mov" to "movzx" would work, but may not be the way you want to do it. Study the code Drizz posted!

"div" is kind of a "funny" instruction, in that the two operands are not the same size...

div bl

divides a 16-bit number (ax) by an 8-bit number (bl), and puts the quotient in al and the remainder in ah.

div ebx

divides the 64-bit number edx:eax (edx times 4G + eax) by ebx, and puts the quotient in eax and the remainder in edx.

If ah or edx are not zero before the "div", you'll get unexpected results. If the result won't fit into the destination (which would happen if ah >= bl or edx >= ebx) it causes a CPU exception. This used to be reported as "division by zero error" (What? I didn't divide by zero!). In Linux, it's reported as "floating point error" (What? I didn't use any floating point!). This is a common beginner error, and can be very confusing!

Note that Drizz does:

xor edx, edx

just before the "div". That's why!

You've got the general idea right... pretty near...

I understand what I need to do...I need to divide, check if the remainder is 0, print out the remainder, and then move the quotient into eax to start the process over again.

Actually, you don't care if the remainder is zero or not - you want to print it either way. When the quotient is zero, you're done.

Good start... carry on!

Best,
Frank

Posted on 2011-09-29 14:02:13 by fbkotler
Hey guys...So I got base 7 to work with both of you helping me. Your hints helped alot!!!



Here's the finished product


; There is some more stuff above this but this is the main block where the magic happens :D

call crlf

mov edx,OFFSET base7
call WriteString


mov bl, 7
mov eax,var


start123:
div bl

mov cl,al ; quotient
mov ch,ah ; remainder

cmp al,0
je done123
mov eax, 0
mov al,ch
call WriteDec
mov al,cl
jmp start123

done123:
mov eax,0
mov al,ch
call WriteDec
mov al,cl
call WriteDec

call crlf


    exit
main ENDP

END main



Thanks guys!!! I am enjoying assembly code much much more than any other language I've encountered. It's quite enjoyable!

P.S. This program prints it backwards. This presents my next little project :D

-Mallard
Posted on 2011-09-30 12:34:47 by msmallard
I'm not sure this is quite "right". After you exit the loop, you print the last remainder, which is correct, and then you print the quotient. Do you want to do that? If you enter 7, and convert it to base 7, it should print "10", right? ("01", since they're reversed) Don't you get "010"? Does no harm, I guess. You can save one (slow) "div" by comparing the quotient to the base (instead of zero), and exiting the loop - in that case, you'd want to print the quotient.

"irvine32.inc" is for Windows, of course, but there's a "port" of it to Linux, which I've downloaded but haven't tried. Maybe I will... I could be wrong about the extra digit.

In any case, to reverse the output, note that Drizz says that the stack is a "LIFO" (last in, first out) structure. This can be useful! Push 'em as you get 'em, and then pop 'em off and print 'em... There are other ways to do it, but that's an "easy" way.

Best,
Frank


Posted on 2011-10-01 08:03:04 by fbkotler