Solved

Assembly language:  converting ASCII to Binary and Binary to ASCII

Posted on 2006-12-01
12
791 Views
Last Modified: 2010-05-18
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
Comment
Question by:xxaznqboyxx
  • 7
  • 3
12 Comments
 
LVL 10

Expert Comment

by:ADSLMark
ID: 18057726
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 '-'
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
0
 

Author Comment

by:xxaznqboyxx
ID: 18058718
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
0
 

Author Comment

by:xxaznqboyxx
ID: 18058725
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
 
LVL 10

Expert Comment

by:ADSLMark
ID: 18059016
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
 
LVL 10

Expert Comment

by:ADSLMark
ID: 18059050
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
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 10

Expert Comment

by:ADSLMark
ID: 18059205
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
 
LVL 10

Expert Comment

by:ADSLMark
ID: 18059207
I'm not sure how the IN/OUT works, but i guess you should convert the answer back to ASCII....
Mark
0
 
LVL 10

Expert Comment

by:ADSLMark
ID: 18059216
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
 
LVL 10

Accepted Solution

by:
ADSLMark earned 125 total points
ID: 18059239
Allright, i made some adjustments, this should be a working version for add/sub. No unary - operator possible, sorry.

        :ORG 100  :
LOP     :INP      :read
        :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
        :ADD c    :
        :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 Comment

by:xxaznqboyxx
ID: 18060782
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

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

Learn to move / copy / export exchange contacts to iPhone without using any software. Also see the issues in configuration of exchange with iPhone to migrate contacts.
A Short Story about the Best File Recovery Software – Acronis True Image 2017
Illustrator's Shape Builder tool will let you combine shapes visually and interactively. This video shows the Mac version, but the tool works the same way in Windows. To follow along with this video, you can draw your own shapes or download the file…
When you create an app prototype with Adobe XD, you can insert system screens -- sharing or Control Center, for example -- with just a few clicks. This video shows you how. You can take the full course on Experts Exchange at http://bit.ly/XDcourse.

706 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now