Welcome to Dream.In.Code
Become an Expert!

Join 137,390 Programmers for FREE! Get instant access to thousands of experts, tutorials, code snippets, and more! There are 2,133 people online right now. Registration is fast and FREE... Join Now!




Assembly Language

 
Reply to this topicStart new topic

Assembly Language, Counting Coins?

Wilbur
8 Oct, 2008 - 09:07 AM
Post #1

New D.I.C Head
*

Joined: 26 Sep, 2008
Posts: 17

Ok. So I am trying to write an assembly program that will ask the user to input a number of pennies, nickels, dimes, and quarters. Then, it will calculate the total number of coins, dollars it adds up to, and cents left over. Here is what i have so far...

CODE

.586
.MODEL FLAT

INCLUDE io.h        ; header file for input/output

.STACK 4096

.DATA
pennies DWORD   ?
nickels DWORD   ?
dimes DWORD   ?
quarters DWORD   ?
numberOfCoins DWORD ?
total DWORD ?
prompt1 BYTE    "How many pennies do you have?", 0
prompt2 BYTE    "How many nickels do you have?", 0
prompt3 BYTE    "How many dimes do you have?", 0
prompt4 BYTE    "How many quarters do you have?", 0
string  BYTE       40 DUP (?)
resultLbl BYTE    "Coin Information", 0
sum     BYTE      11 DUP (?), 0

.CODE
_MainProc PROC
        input     prompt1, string, 40; read ASCII characters
        atod      string    ; convert to integer
        mov      pennies, eax; store in memory

        input     prompt2, string, 40; repeat for second number
        atod      string
        mov      nickels, ebx
        
        input     prompt3, string, 40; read ASCII characters
        atod      string    ; convert to integer
        mov      dimes, ecx; store in memory

        input     prompt4, string, 40; repeat for second number
        atod      string
        mov      quarters, edx
        
        mov     eax, pennies; pennies to EAX
        mov    numberOfCoins, eax; numberOfCoins = number of pennies
        mov    total, eax; total = pennies
        
        mov     ebx, nickels; nickels to EBX
        add      numberOfCoins, ebx; add numberOfNickels to numberOfCoins
        mul      numberOfNickels, 5; multiply numberOfNickels by 5
        add      total, ebx; total = total + 5*numberOfNickels
        
                        
        mov    ecx, dimes; dimes to ECX
        add     numberOfCoins, ecx; add numberOfDimes to numberOfCoins
        mul     numberOfDimes, 10; total = total + 10*numberOfDimes
        add     total, ecx
                                         
        mov      edx, quarters; quarters to EDX
        add       numberOfCoins, edx; add  numberOfQuarters to numberOfCoins
        mul       numberOfQuarters, 25; total = total + 25*numberofQuarters
        add       total, edx                                
        
        dtoa    sum, eax; convert to ASCII characters
        output  resultLbl, sum; output label and sum

        mov     eax, 0    ; exit with return code 0
        ret
_MainProc ENDP
END                        ; end of source code



I know the mul command doesn't have the right syntax, but I have no idea how to write that command. Also, I am currently using 4 different registers. Is there a way to use just the EAX register?

Thanks in advance!

This post has been edited by Wilbur: 8 Oct, 2008 - 09:10 AM
User is offlineProfile CardPM
+Quote Post

TheFlipside
RE: Assembly Language
9 Oct, 2008 - 04:27 AM
Post #2

New D.I.C Head
*

Joined: 9 Aug, 2007
Posts: 9


My Contributions
Ok, first let me check if I understand it well...
You want to know if you can just use the EAX for the MUL opcode to multiply things?

Well to answer this question: Yes and there is no other way then using EAX.
MUL will put the final result of the operation in EAX, that is how the opcode is defined.

But I must confess that I don't understand your code...
First you declare the variables which is ok, but then you use in the main code several times the next command:
CODE

input     prompt1, string, 40; read ASCII characters


And then you use different registers which suddenly appear to have the address (i suppose) as their value...
(first EAX, then EBX etc.)

A function always returns its result in the same register (probably EAX) or on the stack. To read from stack use:

CODE

POP EAX


this loads the first value from the stack into register EAX.

If this sounds all unfamiliar please read some tuts on the basics of assembler. When this is your first assembler project, then you are on the good way!

Please let me know what the exact problems and I will try to help you.
(I don't think it is usefull that I give you the correct code already, I assuming that you are trying to understand and learn, which means:
Usus Magister Est Optimus - Experience is the best teacher)


User is offlineProfile CardPM
+Quote Post

David W
RE: Assembly Language
9 Oct, 2008 - 06:37 AM
Post #3

D.I.C Regular
Group Icon

Joined: 20 Sep, 2008
Posts: 315



Thanked: 16 times
Dream Kudos: 275
My Contributions
QUOTE
If this sounds all unfamiliar please read some tuts on the basics of assembler. When this is your first assembler project, then you are on the good way!

Please let me know what the exact problems and I will try to help you.
(I don't think it is usefull that I give you the correct code already, I assuming that you are trying to understand and learn, which means:
Usus Magister Est Optimus - Experience is the best teacher)


Try HLA ... a much more user friendly assember ... and here is an 'intro' course for it: ( at these links )

http://developers-heaven.net/forum/index.php/topic,46.0.html

http://docs.google.com/View?docID=d674v6b_...atest&pli=1


Here is a little demo HLA program ...

CODE
program add_nums;


#include( "stdlib.hhf" )


// declare three integer variables in the static memory space

static
    num1:   int32:=    23;       // initialize num1 to 23
    num2:   int32:=    77;       // initialize num2 to 77
    sum:    int32;                // sum is not initialized here


begin add_nums;

    stdout.put( "The sum of ", num1, " and ", num2, " is " );
                            
                    // eax is a 32 bit register in the microprocessor
    mov( num1, eax );    // move the (value of the) integer num1 into eax
    add( num2, eax );    // add the (value of the) integer num2 to (what's in) eax

    mov( eax, sum );    // move the 32 bit value now in the eax register into the
                    // 32 bit static memory that we reserved as 'sum'

    stdout.put( sum )

    //  output a newline character(s)
    stdout.newln();        

    // Also ... nl will output a newline character(s)
    stdout.put( nl "Enter an integer " );
    stdin.get( num1 );

    stdout.put( nl "Enter a second integer " );
    stdin.get( num2 );
    
    stdout.put( nl "The sum of ", num1, " and ", num2, " is " );

    mov( num1, eax );    
    add( num2, eax );    
    mov( eax, sum );    

    stdout.put( sum, nl nl "The end." nl nl );
    
end add_nums;




User is offlineProfile CardPM
+Quote Post

Wilbur
RE: Assembly Language
9 Oct, 2008 - 08:17 AM
Post #4

New D.I.C Head
*

Joined: 26 Sep, 2008
Posts: 17

QUOTE(TheFlipside @ 9 Oct, 2008 - 05:27 AM) *
Please let me know what the exact problems and I will try to help you.
(I don't think it is usefull that I give you the correct code already, I assuming that you are trying to understand and learn, which means:
Usus Magister Est Optimus - Experience is the best teacher)

Thanks Flip. I definitely agree with you. As frustrating as writing good code can be, it is just something you have to mostly figure out on your own. Unless you struggle enough with it first, you will never learn anything. I will work on it some more this afternoon and repost tonight. I really appreciate your help!
~ Wilbur

This post has been edited by Wilbur: 9 Oct, 2008 - 08:18 AM
User is offlineProfile CardPM
+Quote Post

David W
RE: Assembly Language
10 Oct, 2008 - 03:30 AM
Post #5

D.I.C Regular
Group Icon

Joined: 20 Sep, 2008
Posts: 315



Thanked: 16 times
Dream Kudos: 275
My Contributions
Writing good code should be fun ... not frustrating.

Hey try HLA ... eh ?

See this HLA code I just put together to show you how HLA can make your work ... fun biggrin.gif

CODE
program ChangeReturned;

#include( "stdlib.hhf" )

?@nodisplay := true;

procedure getCents; @returns( "eax" );
begin getCents;
    try
        stdout.puts( nl "Enter the number of cents to convert: " );
        stdin.flushInput();
        stdin.getu32(); // returns uns32 value input in eax
    anyexception
        mov( 0, eax ); // return ZERO if 'bad data' entered for 'cents' ...
        stdout.puts( "Must enter a number in the range 0...(2^32 -1)." nl );
    endtry;
    
end getCents;

procedure computeCoins( denomination: uns32; var amountLeft: uns32 ); @returns( "eax" );
begin computeCoins;
    push( ebx );
    push( edx );
    
    mov( amountLeft, ebx ); // ebx holds the address of the value
    mov( (type uns32 [ebx]), eax ); // eax now holds the VALUE of amountLeft //*1*//

    // 'DIV' divides the 64 bit value in EDX:EAX by the operand
    // leaving the quotient in EAX and the remainder in EDX.
    // 'div' is used below ...
    
    // Firstly, finish initializing the  'edx:eax' 64 bit 'register' ...
    mov( 0, edx );
    
    // int number = amountLeft / denomination;
    div( denomination, edx:eax ); // Note that eax was set at //*1*// above
    // mov( eax, number ); //Note: eax now holds the quotient i.e. the 'return value'
    
    // and 'update' ... amountLeft = amountLeft % denomination;
    mov( edx, (type uns32 [ebx]) ); // amountLeft value returned by ref
    
    pop( edx );
    pop( ebx );
    // return number
    // mov( number, eax ); // eax already holds the 'number'
end computeCoins;

procedure again; @returns( "al" );
begin again;
    stdout.puts( nl nl "More (y/n) ? " );
    stdin.flushInput();
    stdin.getc();
    if( !( al == 'n' || al =='N') ) then
        mov( true, al );
    else
        mov( false, al );
    endif;
end again;

procedure computeAndDisplay( cents: uns32 );
begin computeAndDisplay;

    stdout.puts( nl stdio.tab "loonies      : " );
    stdout.putu32( computeCoins(100, cents) );
    
    stdout.puts( nl stdio.tab "half-dollars : " );
    stdout.putu32(  computeCoins(50, cents) );
    
    stdout.puts( nl stdio.tab "quarters     : " );
    stdout.putu32(  computeCoins(25, cents) );    
    
    stdout.puts( nl stdio.tab "dimes        : " );
    stdout.putu32(  computeCoins(10, cents) );
    
    stdout.puts( nl stdio.tab "nickles      : " );
    stdout.putu32(  computeCoins( 5, cents) );
    
    stdout.puts( nl stdio.tab "pennies      : " );
    stdout.putu32(  cents );
    
end computeAndDisplay;



begin ChangeReturned;

    stdout.puts
    (
        "This program is intended to take 1-99 or more cents "
        "and tell you how many" nl nl
        stdio.tab "loonies      :" nl
        stdio.tab "half-dollars :" nl
        stdio.tab "quarters     :" nl
        stdio.tab "dimes        :" nl
        stdio.tab "nickles      :" nl
        stdio.tab "pennies      :" nl
    );
    repeat
        computeAndDisplay( getCents() );
    until( !again() );
    
end ChangeReturned;


This post has been edited by David W: 10 Oct, 2008 - 01:52 PM
User is offlineProfile CardPM
+Quote Post

Wilbur
RE: Assembly Language
14 Oct, 2008 - 10:13 AM
Post #6

New D.I.C Head
*

Joined: 26 Sep, 2008
Posts: 17

That does make a lot more sense. However, I need it written in 80x86 assembly language and I really don't understand how the mul operator is supposed to be used. I have worked with this program over the weekend and just have no idea where to go next. Any ideas/help would be greatly appreciated! This is my new code, although not much as changed other than changing all the registers to EAX.

CODE

; Purpose: Counting coins problem

.586
.MODEL FLAT

INCLUDE io.h          ; header file for input/output

.STACK 4096

.DATA
pennies DWORD   ?
nickels DWORD   ?
dimes DWORD   ?
quarters DWORD   ?
numberOfCoins DWORD ?
total DWORD ?
prompt1 BYTE    "How many pennies do you have?", 0
prompt2 BYTE    "How many nickels do you have?", 0
prompt3 BYTE    "How many dimes do you have?", 0
prompt4 BYTE    "How many quarters do you have?", 0
string  BYTE    40 DUP (?)
resultLbl BYTE  "Coin Information", 0
sum     BYTE    11 DUP (?), 0

.CODE
_MainProc PROC
        input   prompt1, string, 40; read ASCII characters
        atod    string            ; convert to integer
        mov     pennies, eax    ; store in memory

        input   prompt2, string, 40; repeat for second number
        atod    string
        mov     nickels, eax
        
        input   prompt3, string, 40; read ASCII characters
        atod    string            ; convert to integer
        mov     dimes, eax        ; store in memory

        input   prompt4, string, 40; repeat for second number
        atod    string
        mov     quarters, eax
        
        
        
                mov         eax, pennies    ; pennies to EAX
                mov        numberOfCoins, eax; numberOfCoins = number of pennies
                mov        total, eax        ; total = pennies
            
                mov        eax, nickels    ; nickels to EAX
        add        numberOfCoins, eax; add numberOfNickels to numberOfCoins
        mul        5            ; multiply numberOfNickels by 5
        add        total, eax        ; total = total + 5*numberOfNickels
                                
        mov        eax, dimes        ; dimes to EAX
        add        numberOfCoins, eax; add numberOfDimes to numberOfCoins
        mul        10            ; total = total + 10*numberOfDimes
        add        total, eax
                                        
        mov        eax, quarters              ; quarters to EAX
        add        numberOfCoins, eax          ; add  numberOfQuarters to numberOfCoins
        mul        25                      ; total = total + 25*numberofQuarters
        add        total, eax                            
        
              dtoa    sum, eax        ; convert to ASCII characters
              output  resultLbl, sum                ; output label and sum

              mov     eax, 0            ; exit with return code 0
              ret
_MainProc ENDP
END                                ; end of source code


This post has been edited by Wilbur: 14 Oct, 2008 - 10:16 AM
User is offlineProfile CardPM
+Quote Post

Wilbur
RE: Assembly Language
14 Oct, 2008 - 10:34 AM
Post #7

New D.I.C Head
*

Joined: 26 Sep, 2008
Posts: 17

The problem itself is not a difficult concept for me...it is all about the implementation of it in assembly language. Here is the code for this program written in C++. I was able to write this in about 5 minutes.

CODE

#include <iostream>
using namespace std;

int main()
{
    int pennies = 0;
    int nickels = 0;
    int dimes = 0;
    int quarters = 0;
    int dollars = 0;
    int totalCents = 0;
    int cents;
    
    cout <<"Enter # of pennies: ";
    cin >> pennies;
    cout <<"Enter # of nickels: ";
    cin >> nickels;
    cout <<"Enter # of dimes: ";
    cin >> dimes;
    cout <<"Enter # of quarters: ";
    cin >> quarters;
    
    totalCents = pennies + ( nickels * 5 ) + ( dimes * 10 )
            + ( quarters * 25);
    
    dollars = totalCents / 100;
    cents = totalCents % 100;
            
    
    cout << "Total cents: " << totalCents << endl;
    cout << "Dollars    : " << dollars << endl;
    cout << "Cents        : " << cents << endl;
    
    return 0;
}


I really just don't understand how to do this kind of thing in assembly.
User is offlineProfile CardPM
+Quote Post

David W
RE: Assembly Language
14 Oct, 2008 - 12:49 PM
Post #8

D.I.C Regular
Group Icon

Joined: 20 Sep, 2008
Posts: 315



Thanked: 16 times
Dream Kudos: 275
My Contributions
QUOTE
I really just don't understand how to do this kind of thing in assembly.


Did you take a look at the HLA code I sent you ... The idea of HLA is to use the High level coding where time is not so critical or to more quickly prototype your scheme ... and get it working and tested ... (And Randy also designed HLA to leverage your knowledge of other languages like C/C++ to fast track your way into Assembly Programming.)

Then if you need to speed some sections up a little, (actually the high level code is all now rewritten in fairly optimized low level code) ... you may be able to shave some time off, by taking each of the HLA structures that you used in HLA and re-coding each, as you wish, in low level. This is a good game plan to attack any program of much size at all. HLA was designed firstly to teach good coding style. Randy Hyde is a real pro at what he does ... The newest versions of HLA are now written in a previous version of HLA.

Shalom,

David

P.S.

This is where most of the real work gets done ...
(I use eax, ebx, and edx; ... eax returns the number of each denomination,
ebx holds a pointer, I need edx:eax to hold 64 bits when I divide a 32 bit number into it ... the quotient is left in eax ... the remainder in edx)

CODE

procedure computeCoins( denomination: uns32; var amountLeft: uns32 ); @returns( "eax" );
begin computeCoins;
    push( ebx );
    push( edx );
    
    mov( amountLeft, ebx ); // ebx holds the address of the value
    mov( (type uns32 [ebx]), eax ); // eax now holds the VALUE of amountLeft //*1*//

    // 'DIV' divides the 64 bit value in EDX:EAX by the operand
    // leaving the quotient in EAX and the remainder in EDX.
    // 'div' is used below ...
    
    // Firstly, finish initializing the  'edx:eax' 64 bit 'register' ...
    mov( 0, edx );
    
    // int number = amountLeft / denomination;
    div( denomination, edx:eax ); // Note that eax was set at //*1*// above
    // mov( eax, number ); //Note: eax now holds the quotient i.e. the 'return value'
    
    // and 'update' ... amountLeft = amountLeft % denomination;
    mov( edx, (type uns32 [ebx]) ); // amountLeft value returned by ref
    
    pop( edx );
    pop( ebx );
    // return number
    // mov( number, eax ); // eax already holds the 'number'
end computeCoins;


I pass in two values each time ... and two new values returned each time

The denomination, to divide by, was passed in by value, (the default in HLA)
The amount left was passed in and returned by reference ( a 'var' in HLA)
I also returned, via eax, the number of coins for that denomination

That is a BLOCK of code that keeps getting repeated. I can make it a macro, or a procedure, as I wish, in HLA. ( I choose a procedure to allow returning a value in eax, that I hand to a print function each time it is called. That print function first calls for that returned value of eax.)

Or ... I could just write the block and manage all the iterations myself ... but that may be a really bad design choice most of the time.

HLA was designed, among other things, to teach you how your procedures are actually implemented in low level code ... smile.gif ... so you can do it yourself and you will then know ... if it's really appropriate.

This post has been edited by David W: 14 Oct, 2008 - 01:40 PM
User is offlineProfile CardPM
+Quote Post

Wilbur
RE: Assembly Language
15 Oct, 2008 - 01:35 PM
Post #9

New D.I.C Head
*

Joined: 26 Sep, 2008
Posts: 17

This code will output the number of cents, but only for the quarters.

Example input: pennies = 1. nickels = 1. dimes = 1. quarter = 1.
Example output: 25

Could someone please help me fix this? It is supposed to add up all the cents.

CODE


.MODEL FLAT

INCLUDE io.h        ; header file for input/output

.STACK 4096

.DATA
pennies DWORD   ?
nickels DWORD   ?
nickel DWORD 5
dimes DWORD   ?
dime DWORD 10
quarters DWORD   ?
quarter DWORD 25
numberOfCoins DWORD ?
total DWORD ?
prompt1 BYTE    "How many pennies do you have?", 0
prompt2 BYTE    "How many nickels do you have?", 0
prompt3 BYTE    "How many dimes do you have?", 0
prompt4 BYTE    "How many quarters do you have?", 0
string  BYTE    40 DUP (?)
resultLbl BYTE  "Coin Information", 0
sum     BYTE    11 DUP (?), 0

.CODE
_MainProc PROC
        input   prompt1, string, 40; read ASCII characters
        atod    string    ; convert to integer
        mov     pennies, eax; store in memory

        input   prompt2, string, 40; repeat for second number
        atod    string
        mov     nickels, eax
        
        input   prompt3, string, 40; read ASCII characters
        atod    string    ; convert to integer
        mov     dimes, eax; store in memory

        input   prompt4, string, 40; repeat for second number
        atod    string
        mov     quarters, eax
        
        
        
        mov     eax, pennies; pennies to EAX
        mov        numberOfCoins, eax; numberOfCoins = number of pennies
        mov        total, eax; total = pennies
        
        mov        eax, nickels; nickels to EAX
        add        numberOfCoins, eax; add numberOfNickels to numberOfCoins
        mul        nickel    ; multiply numberOfNickels by 5
        add        total, eax; total = total + 5*numberOfNickels
                            
        mov        eax, dimes; dimes to EAX
        add        numberOfCoins, eax; add numberOfDimes to numberOfCoins
        mul        dime    ; total = total + 10*numberOfDimes
        add        total, eax
                                    
        mov        eax, quarters; quarters to EAX
        add        numberOfCoins, eax; add  numberOfQuarters to numberOfCoins
        mul        quarter; total = total + 25*numberofQuarters
        add        total, eax                            
        
        dtoa    sum, eax                    ; convert to ASCII characters
        output  resultLbl, sum            ; output label and sum

        mov     eax, 0    ; exit with return code 0
        ret
_MainProc ENDP
END                        ; end of source code


This post has been edited by Wilbur: 15 Oct, 2008 - 06:24 PM
User is offlineProfile CardPM
+Quote Post

Fast ReplyReply to this topicStart new topic
Time is now: 12/5/08 02:28AM

Live Help!

Tutorials

Programming

Web Development

Reference Sheets

Code Snippets

DIC Chatroom

Bye Bye Ads

Monthly Drawing

Thumb Drive

Top Contributors

Top 10 Kudos This Month