Listing 1. Assembly Language that Detects and Uses MMX Technology

 1:  ; File name: mmx_brightening.asm (requires NASM 0.97)
 2:
 3:  bits 32                         ; 32 bit protected mode programming.
 4:  section .text                   ; Start code segment.
 5:
 6:  ;-----------------------------------------------------------------------
 7:  ; C prototype:  int cpuid_support(void);
 8:  ; Returns 1 if the current x86 processor supports the CPUID instruction,
 9:  ; otherwise returns 0.
10:          global cpuid_support    ; Export cpuid_support label.
11:          align   16
12:  cpuid_support:
13:          ;;; Try to modify bit 21 in EFLAGS register.
14:          pushf                   ; Push EFLAGS register into the stack.
15:          pop     ecx             ; Pop stack. ECX has a copy of EFLAGS.
16:          mov     edx, ecx        ; Put another copy of EFLAGS in EDX.
17:          xor     ecx, 0x00200000 ; Complement bit 21 of ECX.
18:          push    ecx             ; Push ECX into the stack.
19:          popf                    ; Pop stack. EFLAGS should have a copy of ECX.
20:
21:          ;;; Check if bit 21 was successfully changed in EFLAGS register.
22:          xor     eax, eax        ; EAX = 0, default return value (failure).
23:          pushf                   ; Push EFLAGS register again into the stack.
24:          pop     ecx             ; Pop stack. ECX has a copy of new EFLAGS.
25:          cmp     ecx, edx        ; Are ECX and EDX the same?
26:          je      .no_CPUID_Support ; Jump if they are (there's no CPUID support).
27:          mov     eax, 1          ; EAX = 1, means success.
28:  .no_CPUID_Support:
29:          ret                     ; End routine, EAX has return value.
30:
31:  ;-------------------------------------------------------------------------
32:  ; C prototype:  int mmx_support(void);
33:  ; Returns 1 if the current x86 processor supports MMX technology, otherwise
34:  ; returns 0.
35:          global mmx_support      ; Export mmx_support label.
36:          align   16
37:  mmx_support:
38:          call    cpuid_support   ; Check if it's OK to use CPUID.
39:          test    eax, eax        ; Is EAX = 0?
40:          jz      .no_MMX_Support ; Jump if it is (there's no CPUID support).
41:
42:          ; Get CPU feature information.
43:          mov     eax, 1
44:          cpuid
45:          xor     eax, eax        ; EAX = 0, default return value (failure).
46:          test    edx, 0x00800000 ; Is bit 23 set?
47:          jz      .no_MMX_Support ; Jump if it isn't (there's no MMX support).
48:          mov     eax, 1          ; EAX = 1, means success.
49:  .no_MMX_Support:
50:          ret                     ; End routine, EAX has return value.
51:
52:  ;-------------------------------------------------------------------------
53:  ; C prototype:  void brightening(
54:  ;                           unsigned char *   BK_vector,
55:  ;                           unsigned char *   bitmap,
56:  ;                           size_t            iterations
57:  ;                           );
58:  ; Image brightening algorithm using MMX technology.
59:          global brightening      ; Export brightening label.
60:          align   16
61:  brightening:
62:          push    ebp             ; Must preserve original EBP register.
63:          mov     ebp, esp        ; Initialize EBP in order to access parameters.
64:
65:          mov     eax, [ebp+8]    ; EAX = pointer to the brightening constant vector.
66:          movq    mm0, [eax]      ; Load in MM0 the brightening constant vector.
67:
68:          mov     edx, [ebp+12]   ; EDX = pointer to first element of bitmap array.
69:          mov     ecx, [ebp+16]   ; ECX = number of iterations.
70:          xor     eax, eax        ; EAX = 0. EAX is an index to the bitmap array.
71:
72:          align   16
73:  .repeat
74:          movq    mm1, [edx+eax*8]; Load MM1 with next 8 bytes.
75:          paddusb mm1, mm0        ; Add into MM1 8 bytes with unsigned saturation.
76:          movq    [edx+eax*8], mm1; Copy back to memory the result.
77:          inc     eax             ; EAX = EAX + 1.
78:          dec     ecx             ; ECX = ECX - 1.
79:          jnz     .repeat         ; Repeat while ECX != 0.
80:
81:          emms                    ; Empty MMX state.
82:
83:          pop     ebp             ; Restore original EBP register.
84:          ret                     ; End routine.