1

We recently started to learn about assembly code and we have homework on the topic. We have been studying the ARM and have to code in Raspberry Pi. One of my homework questions read like this:

Write assembly functions that implement the following C functions:

int32_t shiftS32(int32_t x, int32_p) // return x*2^p for p = -31..31

This is my answer to the question:

.global shiftS32  
.text  

shiftS32:  

PUSH {R0}   
CMP R0, #0   
BMI ENDA 
PUSH {R1}  
CMP R1, #0    

BMI END1   
POP {R1}  
MOV R0, R0, LSL R1  

BX LR

END1:
POP {R1}
SUB R1, #0
NEG R1, R1
MOV R0, R0, LSR R1 

BX LR

ENDA: 
PUSH {R1}
CMP R1, #0

BMI END 
POP {R1}
MOV R0, R0, LSL R1

BX LR

END:
POP {R1}
SUB R1, #0
NEG R1, R1
MOV R0, R0, ASR R1 

BX LR

This code works but I think I am overdoing this. Is there a way to do this same thing but in fewer lines?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847

1 Answers1

1

Yes, that's a bit too much code.

You want to employ this trick for implementing signed integer division in terms of shifts while still maintaining the rounding semantics of n / 2 (towards 0), unlike shifts which round towards -infinity.

You probably want to use conditional execution.

Your code may be as short as this:

shiftS32:
        cmp     r1, #0
        asrlt   r2, r0, #31
        addlt   r3, r1, #32
        lslge   r0, r0, r1
        rsblt   r1, r1, #0
        addlt   r0, r0, r2, lsr r3
        asrlt   r0, r0, r1
        bx      lr

And a bit of test here.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Alexey Frunze
  • 61,140
  • 12
  • 83
  • 180
  • Thank you so much for your reply. Your method certainly looks really clean but the thing is we have not been taught all those terms. That's why I had to resort to the crude method. – TheSorcerer4 Mar 01 '19 at 07:29
  • @SugamBanskota You can throw in a conditional branch, it's trivial. – Alexey Frunze Mar 01 '19 at 08:34
  • The OP doesn't appear to want rounding that matches integer division, given the assignment they're probably intended to use `ASR` for negative counts, not division or a complicated emulation. The mathematical problem statement is in terms of multiplication by a fractional value; if they were using FP they'd get round-to-nearest(-even) by default. – Peter Cordes Mar 02 '19 at 06:09
  • @PeterCordes In that case it should be more than trivial to devise a nearly perfect solution without using any "advanced" techniques or instructions. – Alexey Frunze Mar 02 '19 at 10:26
  • @AlexeyFrunze: Yeah, exactly. Like subtract from zero (into a new register) and set flags, and use that for predicated right/left shifts. I think you could use that same trick to save the CMP instruction, at the cost of a register. – Peter Cordes Mar 02 '19 at 15:19