ARM中装配的GCD功能无法正常工作

时间:2016-11-19 08:44:33

标签: assembly raspberry-pi arm raspbian raspberry-pi3

我对汇编语言很陌生,我正在编制一个计算GCD的程序,但我遇到了麻烦。输入两个数字时,它不会返回正确的答案。有什么建议?我认为问题出在 gcd 函数中,但我不确定。

.text
.global main


     // Usage of the function: gcd(x,y), with the gcd returned in R0.
     // Parameters: Register R0 must contain x, and register R1 must contain y.
gcd:
     bal mod
     cmp r0, #0
     bne gcd
     // end of gcd function

     // Utility modulus function for you to use in your gcd function:
     // Usage: mod(x,y), returns the modulus of x and y in register R0.
     // Parameters: Register R0 must contain x, and register R1 must contain y.
mod:    push {LR}
    mov R3, R1
    mov R1, #0
    mov R2, #1
    //Shift the denominator left until greater than numerator, then shift back 
_shift_left:
        //R3<<=1; //Denominator shift left
    mov r3, r3, asl #1
        //R2<<=1; //Division shift left
    mov r2, r2, asl #1
        //if(R0>R3)goto _shift_left;//Shift Left until Decrement/Division Greater than Numerator
    cmp r0, r3 // compare r0 to r3
    bgt _shift_left // branch if greater than to _shift_left label
        //R3>>=1; //Shift Denominator right
    mov r3, r3, asr #1
        //R2>>=1; //Shift Division right
    mov r2, r2, asr #1
        //Loop and keep subtracting off the shifted Denominator 
_subtract: //if(R0<R3)goto _done;
    cmp r0, r3 // compare r0 to r3
    blt _done // branch if less than to _done
        //R1+=R2; //Increment division by the increment
    adds r1, r2
        //R0-=R3; //Subtract shifted Denominator with remainder of Numerator
    subs r0, r3 //Shift right until denominator is less than numerator
_shift_right:
        //if(R2==1) goto _subtract;
    cmp r2, #1 // compare r2 to #1
    beq _subtract // branch if equal to _subtract
        //if(R3<=R0)goto _subtract;
    cmp r3, r0 // compare r3 to r0
    ble _subtract // branch if less than or equal to _subtract
        //R2>>=1; //Shift Increment left
    mov r2, r2, asr #1
        //R3>>=1; //Shift Denominator left
    mov r3, r3, asr #1
        //goto _shift_right; //Shift Denominator until less than Numerator
    bal _shift_right
        //goto _subtract; //Keep Looping until the division is complete
    bal _subtract
_done:  pop {PC}
// end of mod function

main:
    push {LR}
    ldr R0, =welcome
    bl printf

    ldr R0, =prompt_a
    bl printf

    ldr R0, =scan_pat
    ldr R1, =a
    bl scanf

    ldr r0, =prompt_b
    bl printf

    ldr r0, =scan_pat
    ldr r1, =b
    bl scanf

    ldr r0, =a
    ldr r0, [r0]
    ldr r1, =b
    ldr r1, [r1]
    bl gcd
    ldr r1, =gcd_result
    str r0, [r1]

    ldr r0, =gcd_msg
    ldr r1, =a
    ldr r1, [r1]
    ldr r2, =b
    ldr r2, [r2]
    ldr r3, =gcd_result
    ldr r3, [r3]
    bl printf

    mov r0, #0
    pop {PC}
// end of main function

.data
welcome: .asciz "Welcome to the GCD Program!\n"
prompt_a: .asciz "Enter a value for A: "
prompt_b: .asciz "Enter a value for B: "
gcd_msg: .asciz "gcd(%d,%d) = %d\n"
scan_pat: .asciz "%d"

a: .word 0
b: .word 0
gcd_result: .word 0

1 个答案:

答案 0 :(得分:1)

下面是一个ARMv7 GCD宏。您应该能够将其编写为函数并忽略.macro指令等。我正在使用GCC指令。

我有一段时间没有对代码进行测试,因此它可能包含一些错误,在某些情况下可能效率不高;尽管如此,它应该对你有帮助。

        1:                                                                                                                                                              

        cmp     r1, r2          // r1 - r2 set cpsr                                                                                                                     
        subgt   r1, r1, r2      // sub if r1 > r2 and put result in r1                                                                                                  
        mov r0, r1                                                                                                                                                      
        sublt   r2, r2, r1      // else sub if r2 < r1 and put result in r2                                                                                             

        bne 1b