selph
selph
发布于 2022-01-22 / 306 阅读
0
0

《xchg rax,rax》片段分析0x15--32位转64位

前言

本次是该系列的的第0x15篇,本篇介绍了一种将32位有符号数扩展成64位的方法


实验环境:

  • Windows10 + VS2022 + masm

0x15

代码片段链接:xorpd | xchg rax,rax 0x15

mov      rdx,0xffffffff80000000
add      rax,rdx
xor      rax,rdx

代码分析

指令依然没啥陌生的,这里使用了一个固定数字:0xffffffff80000000,这个64位数的前33位都是1,后31位都是0,用来与rax进行相加操作

此处rax里装入的输入应该是32位有符号数,这样这个固定数字的设置才显得合理

32位有符号数的最高位是符号位,如果是正数,符号位是0,再次异或这个固定数的时候,前面33位就会都变回0

如果是负数,符号位是1,经过相加后,由于进位以至于前33位的1都变成了0,最终的进位溢出,再次异或的时候,前33位又会变回1

假定输入为:0x80000001,那么接下来的问题就是,0xffffffff80000001和0x80000001表示的值是否相同呢?

测试代码1:

int main(int argv)
{
	int a = 0x80000001;
	long long b = 0xFFFFFFFF80000001;
	printf("32: %d %x\r\n", a, a);
	printf("64: %lld %llx", b, b);

	return 0;
}

输出结果:

32: -2147483647 80000001
64: -2147483647 ffffffff80000001

结论是,是一样的,所以本篇的主要内容是有符号数32位扩展成64位

测试代码2:

.code
main proc
    mov eax, 080000001h 
    ;输入小于等于31位,输出为输入本身
    ;第32位有值,则结果为负的输入本身
    ;结果会扩展到64位

    mov      rdx,0ffffffff80000000h ;前33位都是1
    add      rax,rdx    ;rax = rax + rdx 如果符号位是1(负数),则高32位会因为进位而清零,低31位数据位不变
    xor      rax,rdx    ;rax = rax ^ rdx = (rax + rdx)^rdx 如果是正数,前33位会因为异或变回0,否则会因为异或再次出现

	ret

main ENDP
END

评论