一个测试mxcsr 指令的汇编源码。
mxcsr 是多媒体指令集的一个。这个指令可以读一般指令读取不到的空间。
主程序 mxcsr.asm
; mxcsr.asm ; 浮点操作的SSE控制和状态寄存器----mxcsr,它是一个32位寄存器,只使用较低的16位。 ; ; mxcsr 指令的异常位 ; ; 0 IE 无效的操作错误 ; 1 DE 非规格化错误 ; 2 ZE 被零除错误 ; 3 OE 溢出错误 ; 4 UE 下溢错误 ; 5 PE 精度错误 ; 6 DAZ 非规格化浮点数置零 ; 7 IM 无效的操作掩码 ; 8 DM 非规格化操作掩码 ; 9 ZM 被零除掩码 ; 10 OM 溢出掩码 ; 11 UM 下溢掩码 ; 12 PM 精度掩码 ; 13 RC 舍入控制 ; 15 FZ 下溢则零 ; ; 0到5是检测浮点异常,7到12是掩码,字位置1时,跳入异常程序(书中没写明显同,异常程序由链表指针地址控制,如SEH) ; 13到14会引发SIMD浮点异常。使用2位控制4舍5入。 ; 00 四舍五入到最接近 ; 01 向下取整 ; 10 向上取整 ; 11 截断 ; 编译环境: ; ld64 print_mxcsr.c ; ld64 print_hex.c ; includelib libc.lib (libc.lib 是lcc64下的64位库) ; nasm -fwin64 01.asm ; lclnk64 01.obj print_hex.obj print_mxcsr.obj extern printf extern print_mxcsr extern print_hex section .data eleven dq 11.0 two dq 2.0 three dq 3.0 ten dq 10.0 zero dq 0.0 hex db "0x",0 fmt1 db 10,"Divide,default mxcsr:",10,0 fmt2 db 10,"Divide by zero, default mxcsr:",10,0 fmt4 db 10,"Divide, round up:",10,0 fmt5 db 10,"Divide,round dowm:",10,0 fmt6 db 10,"Divide,truncate:",10,0 f_div db "%.1f divided by %.1f is %.16f, in hex:",0 f_before db 10,"mxcsr before:",9,0 f_after db "mxcsr after:",9,0 ; mxcsr 值 default_mxcsr dd 00011111100000000b round_nearest dd 00011111100000000b round_down dd 00111111100000000b round_up dd 01011111100000000b truncate dd 01111111100000000b section .bss mxcsr_before resd 1 mxcsr_after resd 1 xmm resq 1 section .text global main main: push rbp mov rbp,rsp ; 除法 ; 默认 mxcsr mov rdi,fmt1 mov rsi,ten mov rdx,two mov ecx, [default_mxcsr] call apply_mxcsr ;-------------------------------- ; 除法(精度误差) ; 默认 mxcsr mov rdi,fmt1 mov rsi,ten mov rdx,three mov ecx,[default_mxcsr] call apply_mxcsr ; 除以零 ; 默认 mxcsr mov rdi,fmt2 mov rsi,ten mov rdx,zero mov ecx,[default_mxcsr] call apply_mxcsr ; 除法(精度误差) ; 向上取整 mov rdi,fmt4 mov rsi,ten mov rdx,three mov ecx,[round_up] call apply_mxcsr ; 除法(精度误差) ; 向上取整 mov rdi,fmt5 mov rsi,ten mov rdx,three mov ecx,[round_down] call apply_mxcsr ; 除法(精度误差) ; 截断 mov rdi,fmt6 mov rsi,eleven mov rdx,three mov ecx,[default_mxcsr] call apply_mxcsr ; 除法(精度误差) ; 向上取整 mov rdi,fmt4 mov rsi,eleven mov rdx,three mov ecx,[round_up] call apply_mxcsr ; 除法(精度误差) ; 向上取整 mov rdi,fmt5 mov rsi,eleven mov rdx,three mov ecx,[round_down] call apply_mxcsr ; 除法(精度误差) ; 截断 mov rdi,fmt6 mov rsi,eleven mov rdx,three mov ecx,[truncate] call apply_mxcsr leave ret ; 函数 ----------------------------- apply_mxcsr: push rbp mov rbp,rsp push rsi push rdx push rcx push rbp ; 另一个用于堆栈对齐 call printf pop rbp pop rcx pop rdx pop rsi mov [mxcsr_before],ecx ldmxcsr [mxcsr_before] movsd xmm2,[rsi] divsd xmm2,[rdx] stmxcsr [mxcsr_after] movsd [xmm],xmm2 mov rdi,f_div movsd xmm0,[rsi] movsd xmm1,[rdx] call printf call print_xmm ; 打印 mxcsr mov rdi,f_before call printf mov rdi,[mxcsr_before] call print_mxcsr mov rdi,f_after call printf mov rdi,[mxcsr_after] call print_mxcsr leave ret ; 函数 ----------------------------- print_xmm: push rbp mov rdi,hex call printf mov rcx,8 .loop: xor rdi,rdi mov dil,[xmm+rcx-1] push rcx call print_hex pop rcx loop .loop leave ret
函数:
print_hex.c
print_mxcsr.c
// print_hex.c #include <stdio.h> void print_hex(unsigned char n){ if (n < 16) printf("0"); printf("x",n); }
// print_mxcsr.c #include <stdio.h> void print_mxcsr (long int n){ long int s,c; for (c = 15; c >= 0; c--) { s = n >> c; // 每 8 位后的空间 if ((c+1) % 4 == 0) printf(" "); if (s & 1) printf("1"); else printf("0"); } printf("\n"); }