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!
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
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)
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 )
// 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 " );
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
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
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;
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
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;
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 ... ... 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
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