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

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

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

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

分享给朋友:

相关文章

阿里云后台的一个身份证信息查询工具。

阿里云后台的一个身份证信息查询工具。

注:此软件时效性已过,只在此陈列,没有什么意义。工具主图形界面有时会欠费,查不了时,请付1分钱给阿里云。下载地址:个人身份证阿里云查询.rar...

关于ch341驱动,联动3D打印机USB串口通讯.

关于ch341驱动,联动3D打印机USB串口通讯.

手上有个3D打印机,搬家的原因,好久没用.天气热了,打印温度很适合,正好可以使用.又过了一年.发现linux 版本内核已经升级,和原来的系统不一样了. 按照3D打印机的说明,和寻找它的程序,原来的方法...

linux 下的 opengl SDK。

linux 下的 opengl SDK。

opengl 图形库是开放式图形库,最近出了一个freeglut3 我们下载它:sudo apt-get install freeglut3sudo apt-get install freeglut3...

关于DOSBOX的简单说明。

关于DOSBOX的简单说明。

linux 下的共享软件DOSBOX 在有些版本的linux 中不能使用鼠标。网上说明要换声卡地址和中断,连接鼠标端口才可以使用。 曾经设置过,可以使用参数不记得。有个解决方法。这是软件问题。 先卸载...

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

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

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

刚刚上手的一个汇编程序nasm。

刚刚上手的一个汇编程序nasm。

今天使用了masm32软件,总有使不上劲的感觉。因为intel 指令集很多都没有,自己想测试一下,一边翻资料,一边使用。windows 编程好用,但是指令不全,心里总是感觉差一点。又不是编大程序,只是...