Stuck on 7.5 project, stage I.

classic Classic list List threaded Threaded
20 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Stuck on 7.5 project, stage I.

jmoyles
Been chewing through the book on my own and having a blast until I got to Chapter 7.  I'm completely stuck on the 7.5 project.  Not the coding aspect of it, but how to go about even the simplest part of executing on the project.

The previous chapter (6 - assembler) had a ton of examples of input and output, which it made it possible for me to see if I had strayed to far from spec, or didn't understand a concept.

The 7.5 project, as near as I can tell, has no output examples.  Lots of illustrations of pointer movement in specific scenarios, but no input this = output .asm that.

I've hammered out something that will do the SimpleAdd.vm, but it generates 37 lines of ASM code to accomplish the task, and I'm betting I'm not doing it optimally.  My add/sub asm code is 13 asm lines long - again, I don't think I'm on the right track.

The test files are great, but aren't terribly helpful about *why* something isn't working, just that it isn't.

I'm completely lost at this point, and have no idea how to proceed.

Is there any chance that we could get the SimpleAdd.asm posted as a solution to help us newbies along in figuring out the basic structure of vm->asm output logic?
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Stuck on 7.5 project, stage I.

jmoyles
Got some excellent email replies on this one, so I'd thought I share some things I've learned for the 7.5 stage I part of the project.  

Since it appears that posting code is frowned upon, I'll post general lessons I learned.

[1] It makes things easier if your push comes back with D=value pushed, and A as the pointer to stack where the D value is.  If this is always true, then any operation after push() has a lot less to do.

[2] It makes things easier if your pop leaves the popped value in D and A as the pointer to the stack where the D value was.  Again, if this is always true, any operation after pop() has a lot less to do.

[3] You don't have to do cleanup on the stack - old data in the stack is irrelevant, only the pointer and the values below the pointer matter.

[4] on some of the commands, you'll have to use label/jump label commands.  Keep in mind that everything compiles down to one .asm, so you'll need a way to create unique labels for each occurrence of these commands in your output file.

[5] Look at pong.asm and other .asm's for hints on how to proceed.




Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Stuck on 7.5 project, stage I.

jmoyles
In reply to this post by jmoyles
Here is where I am at for optimization of the various operations - am I close, or am I still missing something?

push constant #: 6 commands (leaving D=# and A=memory location)
pop to D: 3 commands (leaving D=# and A=memory location)
add, and sub: pop to d + 2 commands
eq, lt, gt: pop to d + 10 commands, 2 labels, 2 label symbols
and, not: 3 commands
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Stuck on 7.5 project, stage I.

ybakos
I also strongly recommend you use a visual diagram, drawn in ink, representing the computer's registers and important memory segments. If you consider an implementation, you should be able to walk yourself through what data needs to move where (and therefore what asm instructions you need to generate). Pencil in numeric values, re-draw where the SP is pointing to, etc.

For one-track-minded people like me, leveraging abstraction is key.

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Stuck on 7.5 project, stage I.

johns4ta
I am experiencing the same problem as jmoyles. I understand how to parse the files, but I don't know what to do at all it comes to the CodeWriter module. Is there any way that I can recieve the same assistance that jmoyles recieved to get me started on the right track?
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Stuck on 7.5 project, stage I.

David Rysdam
In reply to this post by jmoyles
Same problem here. For instance, should the add/sub/etc operations be using the R13-15 registers or can they use LCL? I think LCL is verboten because that's local *to the function* but that's not what add/sub/etc are. Or are they? Is LCL going to be set somewhere "safe" before add is called?

It seems like they should be able to use LCL, because that would make the push/pop generating functions nice and general. But then again, Stage I doesn't do memory access, so then LCL is out again.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Stuck on 7.5 project, stage I.

cadet1620
Administrator
It is important to understand what a stack frame is. Jump forward to Chapter 8 and look at figures 8.3 and 8.4. ARG and LCL point in to the stack frame for the active VM function so that the function can reference its arguments and local variables. This is what push argument #, pop local #, et.al. are about.

The only temporary storage your generated code can use is R13-R15.

You can actually do the simple 2-argument math functions without temporary storage. At some point in your generated code you have
   D=M
where you load the argument from the top of stack. With a small adjustment, the A-register can point to the other argument/result.

--Mark

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Stuck on 7.5 project, stage I.

David Rysdam
OK, so this is what I thought. It's just that the operands like add/etc will need to push and pop from the stack also, so it would have been nice to use the same functions for those. I can probably wrap up a general push/pop so that I can use it "bare" or from the Official Ways of "pop local" etc.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Stuck on 7.5 project, stage I.

cadet1620
Administrator
Stack operators like add are a place where it hurts you to use general purpose writePush and writePop routines.  Add can be done in 5 hack instructions; it will be huge if you write pushes and pops!

--Mark
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Stuck on 7.5 project, stage I.

David Rysdam
FIVE?!

OK, now that's a challenge.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Stuck on 7.5 project, stage I.

David Rysdam
Oh. Got it. Pretty clever.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Stuck on 7.5 project, stage I.

yoav
In reply to this post by cadet1620
Hi,

When you say 'add' can be done with 5 Hack instructions, do these include the stack pointer update at the end or just the net operation?

Do you make any assumption on the last vm instruction preceding the add?

Thanks
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Stuck on 7.5 project, stage I.

yoav
In reply to this post by jmoyles
Hi,

Could you elaborate on why having "A as the pointer to stack where the D value is" as opposed to A having the address to the stack segment location?

YM
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Stuck on 7.5 project, stage I.

cadet1620
Administrator
In reply to this post by yoav
YM wrote
Hi,

When you say 'add' can be done with 5 Hack instructions, do these include the stack pointer update at the end or just the net operation?

Do you make any assumption on the last vm instruction preceding the add?

Thanks
Five instructions is the entire operation including SP update. No assumptions about previous VM instruction.

Don't spend much time trying to achieve this small of code. If your generated code is 10 or even 15 instructions, that's OK for now. Optimization can be a huge time waster early in a project. As you work on the project, you learn more about the what you are doing and gain insights that can be used at a later time if/when you need to do optimization.

--Mark
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Stuck on 7.5 project, stage I.

yoav
Thanks. I got it down to 5 before seeing your reply.

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Stuck on 7.5 project, stage I.

cadet1620
Administrator
YM wrote
Thanks. I got it down to 5 before seeing your reply.
Become a registered user and you can get email sent to you when people reply to your posts.

--Mark
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Stuck on 7.5 project, stage I.

peterxu422
In reply to this post by jmoyles
jmoyles wrote
Got some excellent email replies on this one, so I'd thought I share some things I've learned for the 7.5 stage I part of the project.  

Since it appears that posting code is frowned upon, I'll post general lessons I learned.

[1] It makes things easier if your push comes back with D=value pushed, and A as the pointer to stack where the D value is.  If this is always true, then any operation after push() has a lot less to do.

[2] It makes things easier if your pop leaves the popped value in D and A as the pointer to the stack where the D value was.  Again, if this is always true, any operation after pop() has a lot less to do.

....
I encountered some issues in Project 08 by following this convention. By following your suggestion, you would write all of your arithmetic commands assuming two things: 1) D contains the value at the top of the stack, 2) A is the address pointing to it. It's true that if you follow your convention for pop and push, it will save you a few asm lines for add, subtract, etc. But once you make those assumptions for one of your arithmetic commands, you'll have to assume those for the rest of your commands, including some non-arithmetic ones.

The problem arises when you have a vm command preceding an arithmetic command where you can't ensure that D will be the value at the top of the stack and A is the address pointing to it. For example, goto, if-goto, call, and return you run into issues. The last asm commands you'd write for these would be setting A an address and then jumping to it. Then assumption 2) is invalid for any subsequent arithmetic commands.

This caused a long troublesome debugging issue for me during Project 08. Were you able to find another way around this while maintaining your convention?
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Stuck on 7.5 project, stage I.

ronaldmaas
Just came across this thread.
I've completed project 7 and 8, and now looking to improve areas of my code generator.

I can't seem to get my head round the 5 statements needed for the add operation.

I can visualise it like this:

SP=SP-1
RAM[SP] = RAM[SP] + RAM[SP-1]

Not sure how I can get this in 5 statements. I think I'm nearly there though :).

Any pointers (no pun intended) would be welcome.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Stuck on 7.5 project, stage I.

cadet1620
Administrator
SP=SP-1
RAM[SP] = RAM[SP] + RAM[SP-1]
SP=SP-1
RAM[SP-1] = RAM[SP-1] + RAM[SP]


Before       After
      x             x+y
      y        SP:
SP:

Multiple destinations are your friend. You can decrement SP and point to y with two instructions:
    @SP
    AM=M-1
No further need to do anything with SP. The remaining 3 instructions just use A, D and M.

--Mark
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Stuck on 7.5 project, stage I.

ronaldmaas
Ah ok, didn't realise that you could manipulate M in this way as well. It almost has a dual role, a before part and a after part.

So add, sub, or and and can all be implemented in the same way (sub with a minor adjustment).

Thanks,
Loading...