//----------------------------------------------------------------- // gcd.s // // This is an assembly language implementation for a function // that can be called from a high-level language to calculate // the Greatest Common Divisor for a pair of 64-bit integers. // // ARGUMENT TRANSMISSION CONVENTIONS // // For the Linux x86_64 platform, these two integer arguments // will get passed to this function in registers RDI and RSI, // and the function's value must be returned in register RAX. // // programmer: ALLAN CRUSE // written on: 04 MAY 2009 //----------------------------------------------------------------- # equates for stackframe offsets .equ p, -8 .equ q, -16 .equ r, -24 .global gcd # make entry-point visible .section .text #------------------------------------------------------------------ gcd: # function's prototype: extern long gcd( long x, long y ); # EXPECTS: %rdi = x # %rsi = y # RETURNS: %rax = gcd( x, y ) push %rbp # save caller stack-frame mov %rsp, %rbp # setup local stack-frame sub $24, %rsp # allocate local storage push %rdx # preserve caller's RDX # assignment: p = abs( x ); mov %rdi, %rax # copy x to accumulator cqo # replicate its sign-bit xor %rdx, %rax # maybe flip all bits sub %rdx, %rax # maybe then add one mov %rax, p(%rbp) # saving abs(x) as p # assignment: q = abs( y ); mov %rsi, %rax # copy y to accumulator cqo # replicate its sign-bit xor %rdx, %rax # maybe flip all bits sub %rdx, %rax # maybe then add one mov %rax, q(%rbp) # saving abs(y) as q # loop: while ( q != 0 ) again: cmpq $0, q(%rbp) # is q equal to zero? je finis # yes, exit from loop # assignment: r = p % q; mov p(%rbp), %rax # setup value of p xor %rdx, %rdx # as a double-quad divq q(%rbp) # to divide p by q mov %rdx, r(%rbp) # remainder into r # assignment: p = q; mov q(%rbp), %rax # fetch value of q mov %rax, p(%rbp) # store value as p # assignment: q = r; mov r(%rbp), %rax # fetch value of r mov %rax, q(%rbp) # store value as q jmp again # reenter our loop finis: mov p(%rbp), %rax # return value in RAX pop %rdx # restore saved register mov %rbp, %rsp # discard local storage pop %rbp # recover former frame ret # return control to caller #------------------------------------------------------------------ .end