Trouble with writing a very basic SPARC Assembly r

2019-05-30 05:38发布

问题:

I'm writing a small assembly routine called isOdd, which, as the name implies, returns if the passed integer is odd, by returning 1 from a % operation.

This is my code so far:

Function prototype: int isOdd( long num )

isOdd:
    save     %sp, -96, %sp  ! Save caller's window

    mov      %i0, %o0       ! Parameter num goes to %o0
    mov      2, %l0         ! 2 goes to local register
    call     .rem           ! Call modulus subroutine
    nop

    mov      %o0, %l0       ! moves the result of the subroutine 
                            ! to output register o0
    ret
    restore

However, I don't get good output; in fact, it seems like it is just returning whatever value I pass to num, instead of actually doing the modulus operation.

Google hasn't proved helpful for such a basic question. This is my first assembly code, so I'm pretty unfamiliar with the concept of "registers," and I think mixing them up is where my error may lie.

Thanks in advance for your help!

回答1:

There are a whole bunch of registers, which you can think of as being in blocks of 8. At any one time, three consecutive blocks of 8 registers are visible as the current register window, and are labelled as %o0-%o7, %l0-%l7, and %i0-%i7. (There is a fourth block of 8 registers, %g0-%g7, which are global rather than being a part of the windowing arrangement.)

When you save or restore, the window moves by two blocks of 8. The overlapping block allows for parameter and result passing. The registers which are named %o0-%o7 in the caller are the same ones that are named %i0-%i7 in the callee. (The two new blocks in the callee are %l0-%l7, which are private for local use within that window, and %o0-%o7 which the callee can use when it in turn wants to call another function.)

It's clearer with a picture:

:                      :
+----------------------+
| Block of 8 registers |      caller's window
+----------------------+  +----------------------+
| Block of 8 registers |  |      %i0 - %i7       |    ---------.
+----------------------+  +----------------------+             | save
| Block of 8 registers |  |      %l0 - %l7       |             v
+----------------------+  +----------------------+  +----------------------+
| Block of 8 registers |  |      %o0 - %o7       |  |      %i0 - %i7       |
+----------------------+  +----------------------+  +----------------------+
| Block of 8 registers |              ^             |      %l0 - %l7       |
+----------------------+      restore |             +----------------------+
| Block of 8 registers |              `---------    |      %o0 - %o7       |
+----------------------+                            +----------------------+
| Block of 8 registers |                                callee's window
+----------------------+
:                      :

Your caller places the num argument into %o0 (in its window), then calls you. You save to set up a new window, and so you see it in %i0 in your window.

.rem takes two parameters. You place these in your %o0 and %o1 (in your window), then call it. It will see them in its %i0 and %i1 (assuming it does a save to set up a new window). It puts the answer in its %i0, which is your %o0.

Similarly, you should put your result in your %i0; whoever called you will see it in their %o0.



回答2:

! modified based on comments 

isOdd:
  save     %sp, -96, %sp  ! Save caller's window
  mov      %i0, %o0       ! Parameter num goes to %o0
  mov      2, %o1         ! 2 goes to %o1
  call     .rem           ! Call modulus subroutine
  nop

  mov      %o0, %i0       ! moves the result of the subroutine 
                          ! to input register i0
  ret
  restore