为什么x86汇编允许将负整数放入无符号变量中?

3

当我在 Visual Studios 中运行此代码时,可以成功构建项目。

.data
   val1 DWORD -1

由于DWORD是无符号的,输入负值不应该导致错误吗?


3
你是怎么确信 DWORD 是无符号的?这份文档没有明确表明该类型的有无符号性。 - Codor
@Codor 这是我教授告诉我的。 - Hashim Amin
这可能是在C/C++中某些Windows头文件定义的DWORD类型的情况,但汇编甚至没有类型系统。我们可以说x86 CPU有数据类型吗? - Peter Cordes
1个回答

4

一切都只是一堆比特(bit)的模式。比如(使用NASM语法-dd代表“数据dword”),下面这些值都是相同的比特模式:

    dd '4321'               ;Interpreted as ASCII characters
    dd 0x31323334           ;Interpreted as an unsigned hexadecimal number
    dd 825373492            ;Interpreted as a signed decimal number

而这段代码也是完全相同的比特位模式,只不过被解释为(32位)指令:

    xor al,0x33
    xor dh,[ecx]

这段代码仍然是相同比特模式的,被解释为16位指令:

    xor al,0x33
    xor dh,[bx+di]

如果你想的话,可以将相同的位模式解释为32位浮点数(2.59315147e-9),或固定点数(例如12594.20001220703125),或二进制编码十进制数(4321),或颜色(RGBA中的“深灰带Alpha”),或作为声音的一部分,等等...
创建位模式的方式并不重要,重要的是如何使用位模式。例如,如果你执行 add dword eax,[foo], 然后执行 jb .somewhere,那么跳转指令可能表示无符号加法;但是,如果你执行 add dword eax,[foo], 然后执行 jl .somewhere,那么跳转指令可能表示有符号加法(尽管对于有符号和无符号加法的加法指令完全相同)。但是,如果你执行 fld dword [foo],则它被用作32位浮点值,或者...
现在,如果你看一下二进制补码的工作方式,你会发现(因为我太懒了,只考虑8位整数)它有两个范围:

00000000b to 01111111b = 0 to +127, regardless of signed or unsigned
10000000b to 11111111b = +128 to +255 if unsigned, or -128 to -1 if signed

换句话说,对于32位整数,0xFFFFFFFF(无符号)与-1(有符号)是相同的比特模式。由于比特模式相同,使用哪个版本并不重要(除了代码可读性方面)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接