当前位置:首页 > 我的程序 > 正文内容

一个测试mxcsr 指令的汇编源码。

Peirre2年前 (2023-06-13)我的程序358

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");
}

1.jpg

分享给朋友:

相关文章

下载:经典游戏音效开发SDK(fmod),专业的游戏音频开发包,个人非商业使用完全免费。

fmod 简  介这个版本是最完美的一个版本,之后的都添加了其它的应用模块。这个版本响应速度快,占用内存少,功能完善。而且是最后一个个人非商业化使用完全免费版本。使用效果非常好,很多游戏就用...

快速傅里叶易语言算法。

雷达滤波需要快速傅里叶公式计算波形。    工程中待处理的信号,通常具有非周期性,故我们需要对离散傅里叶变换进行研究。离散公式:【x(n)是采样的时域信号,X(k)是对于...

发布一个雷达显示程序,仅测试,有问题请交流。

发布一个雷达显示程序,仅测试,有问题请交流。

下载地址:雷达显示程序.rar这个雷达显示程序用来显示雷达数据的。使用易语言编写。数据部分还没完善。欢迎提意见。...

Radasm 编辑器配置VC2010下的Opencv 环境。

Radasm 编辑器配置VC2010下的Opencv 环境。

Opencv 下载地址:https://opencv.org/releases.html备用下载地址1:https://blog.csdn.net/yanzi1225627/article/detai...

linux mint 20 下编译最新内核所添加的文件。

linux mint 20 下编译最新内核所添加的文件。

linux mint 20 下编译最新内核文件所需要的两个文件包。sudo apt-get install libncurses5-devsudo apt-get install libssl-dev...

USB设备的插入机制与USB驱动故障。

USB设备的插入机制与USB驱动故障。

USB主机检测设备,首先在USB集线器的每个端口的D+,D-上,分别接了一个15K欧姆的下拉电阻到地。集线器端口为空时,被这两个电阻拉低了电平。在USB设备端,D+或者D- 上接了上拉1.5K电阻。全...