• Status: Solved
• Priority: Medium
• Security: Public
• Views: 864

# 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.
0
xxaznqboyxx
• 7
• 3
1 Solution

Commented:
I am completely unfamiliar with Basic Computer Assembly, but i guess i know where you got your example ;-)

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 '-'
Compute number and/or answer

So in pseudo code:

dig = true;
ans = 0;
cur = 0;
neg = false;

do
{
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

LOOP,    SKI          /check for character
BUN LOOP     /loop while no character
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;
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
0

Author Commented:
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

LOOP,    SKI          /check for character
BUN LOOP     /loop while no character
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;
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
0

Author Commented:
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.
0

Commented:
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
0

Commented:
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
0

Commented:
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
0

Commented:
I'm not sure how the IN/OUT works, but i guess you should convert the answer back to ASCII....
Mark
0

Commented:
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
0

Commented:
Allright, i made some adjustments, this should be a working version for add/sub. No unary - operator possible, sorry.

:ORG 100  :
:OUT      :write
:STA c    :c = <input>
:LDA equ  :AC = equ
:CMA      :AC = -AC
:ADD c    :AC = AC + c
:SZA      :if(AC == 0) skip
:BUN CZR  :goto CZR
:BUN ANS  :goto ANS
CZR     :LDA zro  :AC = zro
:CMA      :AC = -AC
:ADD c    :AC = AC + c
:INC      :AC = AC + 1
:SPA      :if(AC > 0) skip
:BUN CPL  :goto CPL
:BUN CNN  :goto CNN
CNN     :LDA nin  :AC = nin
:INC      :AC = AC + 1
:CMA      :AC = -AC
:ADD c    :AC = AC + c
:SNA      :if(AC < 0) skip
:BUN CPL  :goto CPL
:BUN LDI  :goto LDI
CPL     :LDA plu  :AC = plu
:CMA      :AC = -AC
:ADD c    :AC = AC + c
:SZA      :if(AC == 0) skip
:BUN CMI  :goto CMI
:BUN LPL  :goto LPL
CMI     :LDA min  :AC = min
:CMA      :AC = -AC
:ADD c    :AC = AC + c
:SZA      :if(AC == 0) skip
:BUN ERR  :goto ERR
:BUN LMI  :goto LMI
LDI     :LDA zro  :AC = zro
:CMA      :AC = -AC
:ADD c    :AC = AC + c
:STA c    :c = AC
:LDA tt   :
:STA cnt  :
:LDA cur  :AC = cur
MUL     :ADD cur  :AC = AC + cur
:ISZ cnt  :cnt++; if(cnt == 0) skip
:BUN MUL  :goto MUL
:STA cur  :
:LDA fal  :
:STA dig  :dig = fal
:BUN LOP  :goto LOP
LPL     :LDA neg  :AC = neg
:SZA      :if(AC == tru) skip
:BUN NNP  :goto NNP
:LDA cur  :AC = cur
:CMA cur  :AC = -AC
:STA cur  :cur = AC
NNP     :LDA cur  :AC = cur
:ADD ans  :AC = AC + ans
:STA ans  :ans = AC
:LDA tru  :AC = tru
:STA cur  :cur = AC
:STA dig  :dig = AC
:LDA fal  :AC = fal
:STA neg  :neg = AC
:BUN LOP  :goto LOP
LMI     :LDA neg  :AC = neg
:SZA      :if(AC == tru) skip
:BUN NNM  :goto NNM
:LDA cur  :AC = cur
:CMA cur  :AC = -AC
:STA cur  :cur = AC
NNM     :LDA cur  :AC = cur
:ADD ans  :AC = AC + ans
:STA ans  :ans = AC
:LDA tru  :AC = tru
:STA cur  :cur = AC
:STA neg  :neg = AC
:STA dig  :dig = AC
:BUN LOP  :goto LOP
ERR     :LDA lE   :
:OUT      :
:LDA lR   :
:OUT      :
:LDA lR   :
:OUT      :
:LDA lO   :
:OUT      :
:LDA lR   :
:OUT      :
:HLT      :
ANS     :LDA neg  :AC = neg
:SZA      :if(AC == tru) skip
:BUN NAN  :goto NAN
:LDA cur  :AC = cur
:CMA cur  :AC = -AC
:STA cur  :cur = AC
NAN     :LDA cur  :AC = cur
:ADD ans  :AC = AC + ans
:HLT      :answer is in AC
neg     :DEC 1    :neg = fal
dig     :DEC 0    :dig = tru
ans     :DEC 0    :ans = 0
cur     :DEC 0    :cur = 0
c       :DEC 0    :c = 0
tru     :DEC 0    :tru = 0
fal     :DEC 1    :fal = 1
tt      :DEC -9   :tt = -9
cnt     :DEC 0    :cnt = 0
zro     :DEC 48   :zro = '0'
nin     :DEC 57   :nin = '9'
plu     :DEC 43   :plu = '+'
min     :DEC 45   :min = '-'
equ     :DEC 61   :equ = '='
lE      :DEC 69   :lE = E
lR      :DEC 82   :lR = R
lO      :DEC 79   :lO = O
:END      :

Also the answer is now in AC at the end, not printed, since it should still do string2int.
Mark
0

Author Commented:
Thanks Mark, I can see your algorithm.  I am trying to implement it on my assembler now.  I will let you know the results.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

## Featured Post

• 7
• 3
Tackle projects and never again get stuck behind a technical roadblock.