assembly language
[X86 어셈블리] FPU 프로그래밍 / 구의 부피 계산하기 / fmul, fmulp, fdiv, fdivp
leo_roh
2023. 8. 4. 17:38
구의 부피 공식
반지름이 r일 때 구의 부피 V는
V = (4/3) × π × r³
위의 간단한 공식을 8087 FPU 프로그래밍으로 구현해보자.
코드
ax 레지스터에 반지름 값을 넣고 스택에 push한다. 이 값을 인자로 하여 get_sphere_volume 프로시져가 구의 부피를 계산한다.
TITLE Sphere Volume
.DOSSEG
.8086
.8087
.MODEL TINY
.DATA
volume DD ?
int_four DW 4
int_three DW 3
.CODE
.STARTUP
mov ax, 3 ;r
push ax
call get_sphere_volume
add sp, 2
mov ah, 4Ch
xor al, al
int 21h
get_sphere_volume PROC
push bp
mov bp, sp
finit
fild WORD PTR [bp+4]
fild WORD PTR [bp+4]
fmul st, st
fmul ;fmulp st(1), st(0)
fild WORD PTR int_four
fmul
fild WORD PTR int_three
fdiv
fldpi
fmul
fstp volume
fwait
mov sp, bp
pop bp
ret
get_sphere_volume ENDP
END
get_sphere_volume 프로시져에서는 부동 소수 연산을 위해 8087을 사용한다. 8087 레지스터의 상태는 다음과 같이 바뀐다.
FMUL과 FMULP
FMUL은 두 레지스터를 피연산자로 명시한 경우에는 pop 동작을 수행하지 않지만 피연산자를 명시하지 않을 경우 pop 동작을 수행한다.
즉, FMUL은 FMULP st(1), st(0)으로 작동된다. 실제로 어셈블 후 확인해보면 FMULP st(1), st(0)로 어셈블된 것을 확인할 수 있다. 한편 두개의 레지스터를 피연산자로 명시하는 경우 첫번째 피연산자 레지스터에 곱한 결과가 저장되고 pop 동작은 없다. 어셈블 후 실제로 이진파일에 들어간 명령어도 FMUL이다. 아래의 그림에서 두번째 붉은 사각형에서 FMUL을 어셈블러가 FMULP st(1), st로 어셈블 한 것을 확인할 수 있다. 곱하기 외에 덧셈, 뺄셈, 나눗셈 또한 같은 방식으로 작동한다.