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.
Copyright © 1994 - 2019 Linux Journal. All rights reserved.