標籤:
這個函數改的深入理解程式設計 使用linux組合語言裡的例子。
相比書中的例子,主要改變為:
-
對底數為1。指數為1都進行特殊處理。
-
可以在64為平台編譯通過,原書pushl %ebp 在64位平台編譯不過,改為push %rbp。
-
原書使用exit系統調用查看結果,改為printf查看結果。
.section .data.section .textfmt: .ascii "%ld\n\0".global _start_start: push $24 #壓入第2個參數 push $2 #壓入第1個參數 call power #調用函數 add $16, %rsp #複位棧寄存器 movslq %eax, %rsi #把power函數的傳回值儲存到rsi寄存器中 mov $fmt, %rdi #把fmt 儲存到rdi寄存器中 #printf(%rdi, %rsi); xor %rax, %rax call printf add $16, %rsp mov $0, %rdi #printf(%rdi) call exit.type power, @functionpower: push %rbp #儲存基底位址暫存器 mov %rsp, %rbp #把棧指標寄存器的值儲存到基底位址暫存器中 movl 24(%rbp), %ecx #取出函數第2個參數 sub $8, %rsp #存放符號,第1個參數小於0 臨時變數存放-1 否則存發1 movq $1, -8(%rbp) #存發符號為的臨時變數 先設定為1 cmp $0, 16(%rbp) #和0比較 jge first_args_lg0 negl 16(%rbp) #發現第一個參數小於0 取負 x = -x 此時的x >= 0 movq $-1, -8(%rbp) #符號位設定為-1first_args_lg0: mov 16(%rbp), %ebx #取出函數第1個參數 cmp $0, %ecx #如果指數等於0 返回1. 任何數的0次方等於1 je power_1 cmp $1, %ebx #如果底數等於1 返回1. 任意多的1相乘還是1 je power_1 mov %ebx, %eax #存放最後的結果值 power_loop_start: cmp $1, %ecx #如果計算機等於1時,函數退出 jle power_end imul %ebx, %eax dec %ecx #對%eax裡的值減1 jmp power_loop_startpower_1: mov $1, %eaxpower_end: imul -8(%rbp), %eax #最終結果和符號位相乘 mov %rbp, %rsp pop %rbp ret
編譯:
gcc -c power.s -g && ld ./power.o -lc -dynamic-linker /lib64/ld-linux-x86-64.so.2 && ./a.out
彙編實現power函數