Today I will show you how to use the MMX instructions.
SSE stands for Streaming SIMD Extensions and uses 128-bit registers:
XMM0 XMM1 XMM2 XMM3 XMM4 XMM5 XMM6 XMM7
The capabilities of the XMM registers are:
- 2 64-bit floating points (double precision)
- 2 64-bit integers
- 4 32-bit floating points (single-precision)
- 4 32-bit integers
- 8 16-bit integers
- 16 8-bit characters (bytes)
I will use two operations with these registers:
DIVSD — Divide Scalar Double-Precision Floating-Point Value
Divides the low double-precision floating-point value in the first source operand by the low double-precision floating-point value in the second source operand, and stores the double-precision floating-point result in the destination operand. The second source operand can be an XMM register or a 64-bit memory location. The first source and destination are XMM registers.
MULSD — Multiply Scalar Double-Precision Floating-Point Value
Multiplies the low double-precision floating-point value in the second source operand by the low double-precision floating-point value in the first source operand, and stores the double-precision floating-point result in the destination operand. The second source operand can be an XMM register or a 64-bit memory location. The first source operand and the destination operands are XMM registers.
First source code for DIVSD:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | format ELF64 public main extrn printf section '.data' writeable formt db 'Result = %f',0ah,0 section '.code' executable main: sub rsp,8 ;align the stack add r14,11 cvtsi2sd xmm0,r14 ;convert count to double add r13,5 cvtsi2sd xmm8,r13 ;convert count to double divsd xmm8,xmm0 ;divide is here movq xmm0,xmm8 mov rdi,formt mov rax,11 call printf add rsp,8 ret |
First source code for MULSD:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | format ELF64 public main extrn printf section '.data' writeable formt db 'Result = %f',0ah,0 section '.code' executable main: sub rsp,8 ;align the stack add r14,11 cvtsi2sd xmm0,r14 ;convert count to double add r13,5 cvtsi2sd xmm8,r13 ;convert count to double mulsd xmm8, xmm0 ;multiply scalar double-precision floating-point value movq xmm0,xmm8 mov rdi,formt mov rax,11 call printf add rsp,8 ret |
The examples start with some base code in order to show the result.
First is the align the stack.
You can see I load registers r14 and r13 with these numbers 11 and 5.
I put the values from registers r14 and r13 into xmm0 and xmm8.
I process the operations divsd and mulsd.
Because I used xmm8 to get the result needs to use movq operation, else the result is the first number load into xmm0.
In the last part from mov rdi,formt is used to show the result.
Use fasm tool like this:
1 2 3 4 | [mythcat@desk fasm]$ ./fasm.x64 test_004.fasm flat assembler version 1.73.24 (16384 kilobytes memory, x64) 1 passes, 824 bytes. [mythcat@desk fasm]$ gcc -m64 test_005.o -o test_004 |
The result is this:
1 2 3 4 | [mythcat@desk fasm]$ ./test_004 Result = 0.454545 [mythcat@desk fasm]$ ./test_005 Result = 55.000000 |