xxaznqboyxx
asked on
Assembly language: converting ASCII to Binary and Binary to ASCII
Hi,
I'm very new with Assembly Language. I am to write an assembly program that will implement a 16-bit calculator that add and subtract. I will need to check to see if the ASCII characters are valid.... (0-9). All inputs should be echoed to the output. If it is not a valid ASCII then the output will output a message "ERROR".
The operation will be off the form:
-2+4+10-33=
Once it reads in an equal then it will output the solution. I am completely lost as what to do. I've written a input and output routine which I don't even know if it is correct. Please help me with code examples, especially the converting and adding/subtracting.
/INPUT ROUTINE
CIF, SKI /Check input flag
BUN CIF /Flag=0, check again
INP /Flag=1, input
OUT /Print Character
STA CHR /Store Character
HLT
CHR, HEX 0001
/OUTPUT ROUTINE
LDA CHR /Load char in AC
COF, SKO /Check output flag
BUN COF /Flag=0, check again
OUT /Flag=1, output
HLT
CHR, HEX 0057 /Character is "W"
Thanks.
I'm very new with Assembly Language. I am to write an assembly program that will implement a 16-bit calculator that add and subtract. I will need to check to see if the ASCII characters are valid.... (0-9). All inputs should be echoed to the output. If it is not a valid ASCII then the output will output a message "ERROR".
The operation will be off the form:
-2+4+10-33=
Once it reads in an equal then it will output the solution. I am completely lost as what to do. I've written a input and output routine which I don't even know if it is correct. Please help me with code examples, especially the converting and adding/subtracting.
/INPUT ROUTINE
CIF, SKI /Check input flag
BUN CIF /Flag=0, check again
INP /Flag=1, input
OUT /Print Character
STA CHR /Store Character
HLT
CHR, HEX 0001
/OUTPUT ROUTINE
LDA CHR /Load char in AC
COF, SKO /Check output flag
BUN COF /Flag=0, check again
OUT /Flag=1, output
HLT
CHR, HEX 0057 /Character is "W"
Thanks.
ASKER
Hi Mark,
I changed the values that you left blank and tested it out. For some reason it kept branching to the error message. It is not recognizing the signs, +/- . Everytime it encounters the sign it will branch to the error routine. The routine looks right... you load the + sign which is the value 2B in hex, then complement it and add to the input and it should equal to zero and shall skip if it is zero. For some reason it does not skip. Can you see anything wrong?? I have an assembler here to run the code and test. You just need to compile and execute it. Then enter the value in the Input textfield. If you could give me your e-mail address I can mail it to you. Thanks again.
ORG 100
/c = read();
LOOP, SKI /check for character
BUN LOOP /loop while no character
INP /read
OUT /write
STA c /c = <input>
/if(c >= '0')
CZERO, LDA zero /AC = zero
CMA /AC = -AC
ADD c /AC = AC + c
INC /AC = AC + 1
SPA /if(AC > 0) skip
BUN CPLUS /goto CPLUS
BUN CNINE /goto CNINE
/if(c <= '9')
CNINE, LDA nine /AC = nine
INC /AC = AC + 1
CMA /AC = -AC
ADD c /AC = AC + c
SNA /if(AC < 0) skip
BUN CPLUS /goto CPLUS
BUN LDIGIT /goto LDIGIT
/if(c == '+')
CPLUS, LDA plus /AC = plus
CMA /AC = -AC
ADD c /AC = AC + c
SZA /if(AC == 0) skip
BUN CMINUS /goto CMINUS
BUN LPLUS /goto LPLUS
/if(c == '-')
CMINUS, LDA minus /AC = minus
CMA /AC = -AC
ADD c /AC = AC + c
SZA /if(AC == 0) skip
BUN ERROR /goto ERROR
/c = c - '0'
LDIGIT, LDA zero /AC = zero
CMA /AC = -AC
ADD c /AC = AC + c
STA c /c = AC
/counter = -10
LDA tentime
STA counter
/AC = cur * 10;
LDA cur /AC = cur
MUL, ADD cur /AC = AC + cur
ISZ counter /counter++; if(counter == 0) skip
BUN MUL /goto MUL
/cur = AC + c;
ADD c
STA cur
/dig = false;
LDA false
STA dig /dig = false
BUN CHECK /goto CHECK
/if(neg == false)
LPLUS, LDA neg /AC = neg
SZA /if(AC == false)
BUN NONEG /goto NONEG
/cur = cur;
LDA cur /AC = cur
STA cur /cur = AC
/if(neg == true)
LMINUS, LDA neg /AC = neg
SZA /if(AC == true) skip
BUN NONEG /goto NONEG
/cur = -cur;
LDA cur /AC = cur
CMA cur /AC = -AC
STA cur /cur = AC
/ans += cur;
NONEG, LDA cur /AC = cur
ADD ans /AC = AC + ans
STA ans /ans = AC
/cur = 0;
LDA true /AC = true
STA cur /cur = AC
/neg = true;
STA neg /neg = AC
/dig = true;
STA dig /dig = AC
BUN CHECK /goto CHECK
/write("INPUTERR");
ERROR, LDA letterI
OUT
LDA letterN
OUT
LDA letterP
OUT
LDA letterU
OUT
LDA letterT
OUT
LDA letterE
OUT
LDA letterR
OUT
LDA letterR
OUT
HLT
/while(c != '=')
CHECK, LDA equal /AC = equal
CMA /AC = -AC
ADD c /AC = AC + c
SZA /if(AC == 0) skip
BUN LOOP /goto LOOP
/write(ans);
LDA ans
OUT
/halt();
HLT
neg, DEC 1 /neg = false
dig, DEC 0 /dig = true
ans, DEC 0 /ans = 0
cur, DEC 0 /cur = 0
c, DEC 0 /c = 0
true, DEC 0 /true = 0
false, DEC 1 /false = 1
tentime, DEC -10 /tentime = -10
counter, HEX 0 /counter = 0
zero, HEX 30 /zero = '0'
nine, HEX 39 /nine = '9'
plus, HEX 2B /plus = '+'
minus, HEX 2D /minus = '-'
equal, HEX 3D /equal = '='
letterI, HEX 49 /letterI = I
letterN, HEX 4E /letterN = N
letterP, HEX 50 /letterP = P
letterU, HEX 55 /letterU = U
letterT, HEX 54 /letterT = T
letterE, HEX 45 /letterE = E
letterR, HEX 52 /letterR = R
END
I changed the values that you left blank and tested it out. For some reason it kept branching to the error message. It is not recognizing the signs, +/- . Everytime it encounters the sign it will branch to the error routine. The routine looks right... you load the + sign which is the value 2B in hex, then complement it and add to the input and it should equal to zero and shall skip if it is zero. For some reason it does not skip. Can you see anything wrong?? I have an assembler here to run the code and test. You just need to compile and execute it. Then enter the value in the Input textfield. If you could give me your e-mail address I can mail it to you. Thanks again.
ORG 100
/c = read();
LOOP, SKI /check for character
BUN LOOP /loop while no character
INP /read
OUT /write
STA c /c = <input>
/if(c >= '0')
CZERO, LDA zero /AC = zero
CMA /AC = -AC
ADD c /AC = AC + c
INC /AC = AC + 1
SPA /if(AC > 0) skip
BUN CPLUS /goto CPLUS
BUN CNINE /goto CNINE
/if(c <= '9')
CNINE, LDA nine /AC = nine
INC /AC = AC + 1
CMA /AC = -AC
ADD c /AC = AC + c
SNA /if(AC < 0) skip
BUN CPLUS /goto CPLUS
BUN LDIGIT /goto LDIGIT
/if(c == '+')
CPLUS, LDA plus /AC = plus
CMA /AC = -AC
ADD c /AC = AC + c
SZA /if(AC == 0) skip
BUN CMINUS /goto CMINUS
BUN LPLUS /goto LPLUS
/if(c == '-')
CMINUS, LDA minus /AC = minus
CMA /AC = -AC
ADD c /AC = AC + c
SZA /if(AC == 0) skip
BUN ERROR /goto ERROR
/c = c - '0'
LDIGIT, LDA zero /AC = zero
CMA /AC = -AC
ADD c /AC = AC + c
STA c /c = AC
/counter = -10
LDA tentime
STA counter
/AC = cur * 10;
LDA cur /AC = cur
MUL, ADD cur /AC = AC + cur
ISZ counter /counter++; if(counter == 0) skip
BUN MUL /goto MUL
/cur = AC + c;
ADD c
STA cur
/dig = false;
LDA false
STA dig /dig = false
BUN CHECK /goto CHECK
/if(neg == false)
LPLUS, LDA neg /AC = neg
SZA /if(AC == false)
BUN NONEG /goto NONEG
/cur = cur;
LDA cur /AC = cur
STA cur /cur = AC
/if(neg == true)
LMINUS, LDA neg /AC = neg
SZA /if(AC == true) skip
BUN NONEG /goto NONEG
/cur = -cur;
LDA cur /AC = cur
CMA cur /AC = -AC
STA cur /cur = AC
/ans += cur;
NONEG, LDA cur /AC = cur
ADD ans /AC = AC + ans
STA ans /ans = AC
/cur = 0;
LDA true /AC = true
STA cur /cur = AC
/neg = true;
STA neg /neg = AC
/dig = true;
STA dig /dig = AC
BUN CHECK /goto CHECK
/write("INPUTERR");
ERROR, LDA letterI
OUT
LDA letterN
OUT
LDA letterP
OUT
LDA letterU
OUT
LDA letterT
OUT
LDA letterE
OUT
LDA letterR
OUT
LDA letterR
OUT
HLT
/while(c != '=')
CHECK, LDA equal /AC = equal
CMA /AC = -AC
ADD c /AC = AC + c
SZA /if(AC == 0) skip
BUN LOOP /goto LOOP
/write(ans);
LDA ans
OUT
/halt();
HLT
neg, DEC 1 /neg = false
dig, DEC 0 /dig = true
ans, DEC 0 /ans = 0
cur, DEC 0 /cur = 0
c, DEC 0 /c = 0
true, DEC 0 /true = 0
false, DEC 1 /false = 1
tentime, DEC -10 /tentime = -10
counter, HEX 0 /counter = 0
zero, HEX 30 /zero = '0'
nine, HEX 39 /nine = '9'
plus, HEX 2B /plus = '+'
minus, HEX 2D /minus = '-'
equal, HEX 3D /equal = '='
letterI, HEX 49 /letterI = I
letterN, HEX 4E /letterN = N
letterP, HEX 50 /letterP = P
letterU, HEX 55 /letterU = U
letterT, HEX 54 /letterT = T
letterE, HEX 45 /letterE = E
letterR, HEX 52 /letterR = R
END
ASKER
Hi Mark,
For some reason it is not recognizing the +/- sign. Once I enter the +/- it branches to the ERROR routine. Do you know why? I mean the routine looks correct, for a plus, you would load the hex value 2B, then complement it and add it to the input. It should equal zero and skip the minus routine... I don't know why it's not working. I have an assembler for this basic computer if you need it, please give me your e-mail address. Thanks.
For some reason it is not recognizing the +/- sign. Once I enter the +/- it branches to the ERROR routine. Do you know why? I mean the routine looks correct, for a plus, you would load the hex value 2B, then complement it and add it to the input. It should equal zero and skip the minus routine... I don't know why it's not working. I have an assembler for this basic computer if you need it, please give me your e-mail address. Thanks.
You can adjust this:
CMINUS, LDA minus /AC = minus
CMA /AC = -AC
ADD c /AC = AC + c
SZA /if(AC == 0) skip
BUN ERROR /goto ERROR
to:
CMINUS, LDA minus /AC = minus
CMA /AC = -AC
ADD c /AC = AC + c
SZA /if(AC == 0) skip
BUN ERROR /goto ERROR
BUN LMINUS /goto LMINUS
Also check the value of - (0x2D), since it might be a different dash then you use on your command line.
Next, I forgot to mention, but it does not parse the unary - sign. So for example, 4+-2 is not valid, this also includes: -2+4... So, if you have to implement unary - also, then you should extend the program to remember if the digit is negative, if so, complement and add. It complicates the whole program a bit, so I left it out.
Mark
CMINUS, LDA minus /AC = minus
CMA /AC = -AC
ADD c /AC = AC + c
SZA /if(AC == 0) skip
BUN ERROR /goto ERROR
to:
CMINUS, LDA minus /AC = minus
CMA /AC = -AC
ADD c /AC = AC + c
SZA /if(AC == 0) skip
BUN ERROR /goto ERROR
BUN LMINUS /goto LMINUS
Also check the value of - (0x2D), since it might be a different dash then you use on your command line.
Next, I forgot to mention, but it does not parse the unary - sign. So for example, 4+-2 is not valid, this also includes: -2+4... So, if you have to implement unary - also, then you should extend the program to remember if the digit is negative, if so, complement and add. It complicates the whole program a bit, so I left it out.
Mark
If you want me to help debug, then it might help if you could post a link to the simulator software, or sth similar..
Mark
Mark
Ok, I wrote my own little simulator.. and i noticed it worked quite well.
Sometimes the jumps are not very smart, since they all jump to the CHECK label, but you can better jump to LOOP.. Also the case:
CMINUS, LDA minus /AC = minus
CMA /AC = -AC
ADD c /AC = AC + c
SZA /if(AC == 0) skip
BUN ERROR /goto ERROR
should be BUN CHECK.
The idea is to make it like:
LOOP : c = read();
CZERO : if(c>='0') goto CNINE else CPLUS
CNINE : if(c<='9') goto LDIGIT else CPLUS
CPLUS : if(c=='+') goto LPLUS else CMINUS
CMINUS: if(c=='-') goto LMINUS else CHECK
CHECK : if(c=='=') goto LOOP else ERROR
So you should adjust the jumps (BUNs).
Mark
Sometimes the jumps are not very smart, since they all jump to the CHECK label, but you can better jump to LOOP.. Also the case:
CMINUS, LDA minus /AC = minus
CMA /AC = -AC
ADD c /AC = AC + c
SZA /if(AC == 0) skip
BUN ERROR /goto ERROR
should be BUN CHECK.
The idea is to make it like:
LOOP : c = read();
CZERO : if(c>='0') goto CNINE else CPLUS
CNINE : if(c<='9') goto LDIGIT else CPLUS
CPLUS : if(c=='+') goto LPLUS else CMINUS
CMINUS: if(c=='-') goto LMINUS else CHECK
CHECK : if(c=='=') goto LOOP else ERROR
So you should adjust the jumps (BUNs).
Mark
I'm not sure how the IN/OUT works, but i guess you should convert the answer back to ASCII....
Mark
Mark
I made a mistake in the JUMPs (AGAIN!)
LOOP : c = read();
: if(c=='=') goto LANS else CZERO
CZERO : if(c>='0') goto CNINE else CPLUS
CNINE : if(c<='9') goto LDIGIT else CPLUS
CPLUS : if(c=='+') goto LPLUS else CMINUS
CMINUS: if(c=='-') goto LMINUS else ERROR
LDIGIT: goto LOOP
LPLUS : goto LOOP
LMINUS: goto LOOP
LANS: write(ans);
That should be correct.
Mark
LOOP : c = read();
: if(c=='=') goto LANS else CZERO
CZERO : if(c>='0') goto CNINE else CPLUS
CNINE : if(c<='9') goto LDIGIT else CPLUS
CPLUS : if(c=='+') goto LPLUS else CMINUS
CMINUS: if(c=='-') goto LMINUS else ERROR
LDIGIT: goto LOOP
LPLUS : goto LOOP
LMINUS: goto LOOP
LANS: write(ans);
That should be correct.
Mark
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thanks Mark, I can see your algorithm. I am trying to implement it on my assembler now. I will let you know the results.
http://calab.kaist.ac.kr/~hyoon/courses/cs311/cs311_2006/Ch6.ppt
So let's see.. this sounds like homework.. anyway.. my idea would be:
Make a loop until we come along a '='
Read a digit or '+' or '-'
Write read character
Compute number and/or answer
So in pseudo code:
dig = true;
ans = 0;
cur = 0;
neg = false;
do
{
c = read();
if(c >= '0' && c <= '9')
{
cur = cur*10 + (c - '0');
dig = false;
}
else if(c == '+' && !dig)
{
if(negate) cur = -cur;
ans += cur
cur = 0;
neg = false;
dig = true;
}
else if(c == '-' && !dig)
{
if(neg)
{
cur = -cur;
neg = false;
}
ans += cur;
cur = 0;
neg = true;
dig = true;
}
else
{
write("ERROR");
}
}
while(c != '=')
write(ans);
Now translating this to your assembly code.. I did most of the work and i did not run a test (i have no idea how), but it's getting late and you can do the rest yourself, i think not so difficult. ENJOY!
ORG 100
/c = read();
LOOP, SKI /check for character
BUN LOOP /loop while no character
INP /read
OUT /write
STA c /c = <input>
/if(c >= '0')
CZERO, LDA zero /AC = zero
CMA /AC = -AC
ADD c /AC = AC + c
INC /AC = AC + 1
SPA /if(AC > 0) skip
BUN CPLUS /goto CPLUS
BUN CNINE /goto CNINE
/if(c <= '9')
CNINE, LDA nine /AC = nine
INC /AC = AC + 1
CMA /AC = -AC
ADD c /AC = AC + c
SNA /if(AC < 0) skip
BUN CPLUS /goto CPLUS
BUN LDIGIT /goto LDIGIT
/if(c == '+')
CPLUS, LDA plus /AC = plus
CMA /AC = -AC
ADD c /AC = AC + c
SZA /if(AC == 0) skip
BUN CMINUS /goto CMINUS
BUN LPLUS /goto LPLUS
/if(c == '-')
CMINUS, LDA minus /AC = minus
CMA /AC = -AC
ADD c /AC = AC + c
SZA /if(AC == 0) skip
BUN ERROR /goto ERROR
/c = c - '0'
LDIGIT, LDA zero /AC = zero
CMA /AC = -AC
ADD c /AC = AC + c
STA c /c = AC
/counter = -10
LDA tentime
STA counter
/AC = cur * 10;
LDA cur /AC = cur
MUL, ADD cur /AC = AC + cur
ISZ counter /counter++; if(counter == 0) skip
BUN MUL /goto MUL
/cur = AC + c;
ADD c
STA cur
/dig = false;
LDA false
STA dig /dig = false
BUN CHECK /goto CHECK
/pretty much similar to the minus case.
LPLUS, ...
BUN CHECK /goto CHECK
/if(neg == true)
LMINUS, LDA neg /AC = neg
SZA /if(AC == true) skip
BUN NONEG /goto NONEG
/cur = -cur;
LDA cur /AC = cur
CMA cur /AC = -AC
STA cur /cur = AC
/ans += cur;
NONEG, LDA cur /AC = cur
ADD ans /AC = AC + ans
STA ans /ans = AC
/cur = 0;
LDA true /AC = true
STA cur /cur = AC
/neg = true;
STA neg /neg = AC
/dig = true;
STA dig /dig = AC
BUN CHECK /goto CHECK
/write("ERROR");
ERROR, ...
/while(c != '=')
CHECK, LDA equal /AC = equal
CMA /AC = -AC
ADD c /AC = AC + c
SZA /if(AC == 0) skip
BUN LOOP /goto LOOP
/write(ans);
...
/halt();
HLT
neg, DEC 1 /neg = false
dig, DEC 0 /dig = true
ans, DEC 0 /ans = 0
cur, DEC 0 /cur = 0
c, DEC 0 /c = 0
true DEC 0 /true = 0
false DEC 1 /false = 1
tentime, DEC -10 /tentime = -10
counter, HEX 0 /counter = 0
zero, HEX 30 /zero = '0'
nine, HEX 39 /nine = '9'
plus, HEX 2B /plus = '+'
minus, HEX 2D /minus = '-'
equal, HEX 3D /equal = '='
END
I hope it works, at least it's close to a working version.
Mark