section .data
number_1 dd 25
number_2 dd 36
A dq 2
msg_square_root db "The square root is: ", 0
msg_square_root_len equ $ - msg_square_root
newline db 0x0A
section .bss
buf resb 20 ; 用于存储 ASCII 码的缓冲区
digit resb 1 ; 存储当前数字位的 ASCII 码
section .text
global _start
_start:
push qword [number_1] ;将number_1压入栈
call single_root
mov rax, 1 ; 'write' 系统调用号
mov rdi, 1 ; 标准输出描述符
mov rsi, newline ; 字符串地址
mov rdx, 1 ; 字符串长度(字节数)
syscall
push qword [number_2] ;将number_2压入栈
call single_root
mov rax, 60
xor rdi, rdi
syscall
single_root:
push rbp ; 保存调用者的基址指针
mov rbp, rsp ; 设置当前的基址指针
sub rsp, 8 ; 为局部变量分配空间
push r9 ;保存用于计算的寄存器r9
push r10 ;保存用于计算的寄存器r10
push r13 ;保存用于计算的寄存器r13
push r15 ;保存用于计算的寄存器r15
mov r9d, [rbp+16] ;把第一个数存储到r9中
mov r10d, [rbp+16] ;把第一个数存储到r10中
shr r9, 1 ; initial guess for sqrt(D) is D/2, quicker search
call single_root_iteration
ret
single_root_iteration:
mov rax, r10
mov r15, r9
xor rdx, rdx
idiv r9
add rax, r9
mov r13, [A]
xor rdx, rdx
idiv r13
mov r9, rax ;quotient in rax gives to r9
neg rax
add rax, r15
cmp rax, 0
jg single_root_iteration
mov [rbp-8], r9
call print_any_digits_numbers
pop r9 ; restore r9
pop r10 ; restore r10
pop r13 ; restore r13
pop r15 ; restorer 15
mov rsp, rbp ; restore stack pointer. It's equal to removing local variables from the stack
pop rbp ; restore RBP
ret
print_any_digits_numbers:
mov rax, [rbp-8]
mov r10, 0 ; 数位计数器和缓冲区偏移量,同时指向空闲单元
mov rbx, 10 ; 除数
conv_loop_start:
cqo ; 将 RAX 扩展为 RDX:RAX 以进行除法运算
idiv rbx ; RAX = RDX:RAX / RBX,商存储在 RAX 中,余数存储在 RDX 中
add dl, '0' ; 将余数转换为 ASCII 码
mov [buf + r10], dl ; 存储到缓冲区
inc r10
cmp rax, 0 ; 检查商是否为 0
jnz conv_loop_start ; 如果不为 0,则继续循环
mov rcx, r10 ; 将位数存储在 RCX 中
mov rax, 1
mov rdi, 1
mov rsi, msg_square_root
mov rdx, msg_square_root_len
syscall
print_loop_start:
dec r10 ; 到最后一个处理的数位
mov al, [buf + r10] ; 将 [buf+r8] 移动到 AL 寄存器
mov [digit], al ; 将 AL 存储到 digit 变量(用于打印)
mov rax, 1 ; 'write' 系统调用号
mov rdi, 1 ; 标准输出描述符
mov rsi, digit ; 字符串地址
mov rdx, 1 ; 字符串长度(字节数)
syscall
cmp r10, 0 ; 检查是否到达第一位
jnz print_loop_start ; 如果不是第一位,则继续循环
ret