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

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

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

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

分享给朋友:

相关文章

介绍一个改编过的纸牌游戏WinSol。

介绍一个改编过的纸牌游戏WinSol。

这个游戏是VC++ 6.0 SP6 编写的。原作者是个日本人。但是他也是翻版。源代码是linux下的aisleriot纸牌游戏。经过拼装,加上windows SDK。改编而成。虽然这是VC++ 6.0...

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

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

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

关于 Cannot enable. Maybe the USB cable is bad? 这个问题。

关于 Cannot enable. Maybe the USB cable is bad? 这个问题。

经常摆弄电脑,那USB接口也是插进,拔出多少次。有一天发生了这个问题,什么问题呢?见图:只要是linux 新内核,都会出现这个问题,虚拟机USB功能,DOSBOX等USB功能不可识别。在网上查看了一些...

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

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

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

linux 下的《仙剑奇侠传》

linux 下的《仙剑奇侠传》

以前的DOS游戏《仙剑奇侠传》是炙制人口的一个很容易上手的游戏。这个游戏流行了很多年。很多人在玩过多年以后,重温旧梦,回味游戏之中的情感。这个游戏再版了很多次了。现在linux 下也可以直接玩这个游戏...

谈谈引导程序的想法。

谈谈引导程序的想法。

当个人电脑一出现就有了磁盘系统,不管是软盘,光盘,硬盘,计算机要应用操作系统就要引导,引导程序一段代码。这引导代码很小,在第一个磁盘的扇区上,平时没什么人注意它。这段代码损坏一个字节,都会造成计算机瘫...