这个函数改的深入理解程序设计 使用linux汇编语言里的例子。
相比书中的例子,主要改变为:
- 对底数为1。指数为1都进行特殊处理。
- 可以在64为平台编译通过,原书pushl %ebp 在64位平台编译不过,改为push %rbp。
- 原书使用exit系统调用查看结果,改为printf查看结果。
.section .data .section .text fmt: .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, @function power: 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) #符号位设置为-1 first_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_start power_1: mov $1, %eax power_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
时间: 2024-10-11 07:15:57