I'm currently working on a school assignment using a theoretical CPU with a very limited instruction set. The available instructions are as follows: Code: add // add registers addi // add immediate sub lui // load upper immediate and andi or ori xor xori nor sll // shift left logical srl // shift right logical sra // shift right arithmetic lw // load word lh // load half word lb // load byte sw // store word sh sb beq // branch on equal bne // branch on not equal blt // branch on less than ble // branch on less than or equal j // jump jal // jump and link jr // jump register Registers are named as r0, r1, ..., r31. One part of the assignment is to write a very simple program for this CPU in assembly language, "such as 1+1=2". I'm an extreme beginner at assembly language and would therefore like to ask for some tips. For example, would the below program work to calculate 1+1? (comments ignored): addi r1, r0, 1 // add 1 to zero register, store in r1 addi r2, r0, 1 // add 1 to zero register, store in r2 add r3, r2, r1 // add r1 and r2, store in r3 sb r3 0(r1) // store contents of r3 to memory address 1 (r1 = 1 and dpl = 0) I may be completely off track with this so please tell me if it looks weird. Also, if you have any ideas about slightly more complex programs (that use a branching instruction, for example) I'd greatly appreciate your suggestions.
You need to know more than just the keyword to write programs. For example, what does addi a,b,c mean, is it a+b=c, or a=b+c, or b=a+c, or (accumulator)=a+b+c, or *a=*b+*c, or something else? Are there any details about the CPU posted anywhere; are you using a theoretical one of your own design or a design you got from somewhere?
Thanks for the reply. I've added descriptions and syntax below. rs = source register, rt = target register, rd = destination register. Code: add // rd <-- rs + rt // R-type addi // rt <-- rs + imm // I-type sub // rd <-- rs - rt // R-type lui // rt <-- imm <<16 (shift) // I-type and // rd <-- rs AND rt (bitwise) // R-type andi // rt <-- rs AND imm // I-type or // rd <-- rs OR rt // R-type ori // rd <-- rs OR imm // I-type xor // rd <-- rs XOR rt // R-type xori // rt <-- rs OR imm // I-type nor // rd <-- rs NOR rt // R-type sll // rd <-- rs llshift aux[10, 6] // R-type srl // rd <-- rs lrshift aux[10, 6] // R-type sra // rd <-- rs arshift aux[10, 6] // R-type lw // rt <-- mem(rs + dpl) // I-type lh lb sw // mem(rs + dpl) <-- rt // I-type sh sb beq // if rs == rt then PC = PC + dpl // I-type bne // if rs !== rt then PC = PC + dpl // I-type blt // if rs < rt then PC = PC + dpl // I-type ble // if rs <= rt then PC = PC + dpl // I-type j // PC <-- addr // A-type jal // r31 <-- PC + 4; PC <-- addr // A-type jr // PC <-- rs // R-type -- SYNTAX -- R-type: <op> rd, rs, rt I-type: <op> rt, rs, imm A-type: <op> <addr> Registers are named as r0, r1, ..., r31. One part of the assignment is to write a very simple program for this CPU in assembly language, "such as 1+1=2". I'm an extreme beginner at assembly language and would therefore like to ask for some tips. For example, would the below program work to calculate 1+1? (comments ignored): Code: addi r1, r0, 1 // add 1 to zero register, store in r1 addi r2, r0, 1 // add 1 to zero register, store in r2 add r3, r2, r1 // add r1 and r2, store in r3 sb r3 0(r1) // store contents of r3 to memory address 1 (r1 = 1 and dpl = 0) I haven't been able to find more details about the CPU design online. It is presented in a textbook for the class I'm taking. I'm currently doing an exchange year in Japan so the textbook is in Japanese and even though I can understand it fairly well it does make things slightly harder. :goofy:
I would say probably not, because it depends on the initial value of r0. If r0 starts off as zero, what do you think the result will be? If you're not sure, take it a step at a time. What is the result of addi r1,r0,1? Then when you've worked that out, what is the result of addi r2,r0,1? And so on. That's how you solve problems like this.
Since r0, the zero register, has a constant value 0, my reasoning is that Code: addi r1, r0, 1 will add together 0 + 1 (r0 and imm 1) and store the result (=1) in r1. Is this incorrect?
Why are you asking if this is incorrect? What exactly don't you understand about Code: addi // rt <-- rs + imm // I-type Also what happens if you run the program; does it do what you expect? I'm puzzled about why you want to know in advance what will happen. Experimentation is key to learning and you will develop the skills to perform a dry run in your head only in conjunction with much experimentation. What's the worst that can happen if you just try it and see what happens? If it doesn't do what you expect then you can start to figure out why.
Thanks for the feedback. Perhaps I've explained my problem poorly. This instruction set and its syntax is, afaik, not supported by an actual CPU. It is merely a hypothetical one introduced for this particular assignment. However, one may assume that it accepts the instructions and syntax mentioned above. I'm only interested in knowing whether my suggested program is a reasonable approach for a program that performs some simple operations, such as 1+1=2. Had it been a high-level programming language, I might have created two variables say x and y, assign x = 1 and let y = x + x, but since I have no previous experience in assembly language I'm not sure how to appropriately represent such operations. If I wanted to be able to compile and test the program I would need to design the actual CPU, right? Is this doable with only the information given in this thread? Does this make things any clearer or have I just proven my ignorance? :freak:
OK, fair point, I had missed the fact that this CPU doesn't actually exist. So you have no choice but to dry run it in your head. I'm reluctant just to say "yes" or "no" because it's in discovering the answer for yourself that you will learn. But maybe nobody's actually bothered to explain how to dry run a program, so here's how I would do it. We'll assume that r0 starts off at zero: Initiali register values: r0=0; r1=?; r2=?; r3=? (? means unknown value) Let's look at the first instruction: addi r1, r0, 1 // add 1 to zero register, store in r1 If this works correctly, the new values of the registers above will be: r0=0; r1=1; r2=?; r3=? After addi r2, r0, 1 // add 1 to zero register, store in r2 the registers should contain r0=0; r1=1; r2=1; r3=? After add r3, r2, r1 // add r1 and r2, store in r3 the registers should contain r0=0; r1=1; r2=1; r3=2 sb r3 0(r1) // store contents of r3 to memory address 1 (r1 = 1 and dpl = 0) Memory location 1 should now contain the value 2. (note "should". That comes from many years of experience with computers and finding it's always a good idea to hedge your bets. Feel free to replace this with "will" if you see fit.)
Thanks, I feel I've somewhat got the hang of it now. :pleased: Also, your advice has made me want to try to do more than just a "dry run", so I might start looking into some actual CPU design after this. Thanks again!