"i32" 类型的值在 WebAssembly 中是如何求值的?
How the value of type "i32" is evaluated in WebAssembly?
根据规范中的文本如下:
Note that the value types i32 and i64 are not inherently signed or unsigned. The interpretation of these types is determined by individual operators.
既然不知道传递的i32类型参数的符号,那么i32.add如何对这两个参数进行加法运算呢?如果我们将这个函数导出到 JavaScript,结果应该如何评估?例如,0xffffffff 可以计算为具有不同符号的不同数字(4294967295 或 -1)。
(module
(func (export "addTwo") (param i32 i32) (result i32)
local.get 0
local.get 1
i32.add))
WebAssembly 要求将 -a + b
写成 b - a
。
使用 WebAssembly Explorer,这个:
int add(int a, int b) { return a + b; }
编译为:
(i32.add(get_local )(get_local [=11=]))
同时(注意负数 -a
):
int add(int a, int b) { return -a + b; }
编译成这个(注意 sub
tract 而不是 add
):
(i32.sub(get_local [=13=])(get_local ))
加号无所谓。如果您有一些位 X
,那么它们可以被解释为有符号值 S_X
或无符号值 U_X
。重要的是两者之间的差异是 0
或 2^32
,因为二进制补码的工作原理。
例如,如果X全为1,则S_X == -1
和U_X == 2^32 - 1
。请注意差异是 2^32
。如果X全为0那么两个值都是0,差就是0.
所以你可以写 S_X = U_X + D_X
其中 D_X
是差值,要么是 0 要么是 2^32
。 X
到 Y
的有符号加法是
S_X + S_Y = U_X + D_X + U_Y + D_Y = U_X + U_Y
最后一步是重要的一步:我们可以忽略 D_*
值,因为它们是 2^32
的倍数,我们假设我们环绕 - 即更高的位超过 32 个被忽略。
并非所有操作都如此。例如,出于这个原因,除法有两个操作,有符号和无符号。但是加减乘法等等,不用在意符号。
根据规范中的文本如下:
Note that the value types i32 and i64 are not inherently signed or unsigned. The interpretation of these types is determined by individual operators.
既然不知道传递的i32类型参数的符号,那么i32.add如何对这两个参数进行加法运算呢?如果我们将这个函数导出到 JavaScript,结果应该如何评估?例如,0xffffffff 可以计算为具有不同符号的不同数字(4294967295 或 -1)。
(module
(func (export "addTwo") (param i32 i32) (result i32)
local.get 0
local.get 1
i32.add))
WebAssembly 要求将 -a + b
写成 b - a
。
使用 WebAssembly Explorer,这个:
int add(int a, int b) { return a + b; }
编译为:
(i32.add(get_local )(get_local [=11=]))
同时(注意负数 -a
):
int add(int a, int b) { return -a + b; }
编译成这个(注意 sub
tract 而不是 add
):
(i32.sub(get_local [=13=])(get_local ))
加号无所谓。如果您有一些位 X
,那么它们可以被解释为有符号值 S_X
或无符号值 U_X
。重要的是两者之间的差异是 0
或 2^32
,因为二进制补码的工作原理。
例如,如果X全为1,则S_X == -1
和U_X == 2^32 - 1
。请注意差异是 2^32
。如果X全为0那么两个值都是0,差就是0.
所以你可以写 S_X = U_X + D_X
其中 D_X
是差值,要么是 0 要么是 2^32
。 X
到 Y
的有符号加法是
S_X + S_Y = U_X + D_X + U_Y + D_Y = U_X + U_Y
最后一步是重要的一步:我们可以忽略 D_*
值,因为它们是 2^32
的倍数,我们假设我们环绕 - 即更高的位超过 32 个被忽略。
并非所有操作都如此。例如,出于这个原因,除法有两个操作,有符号和无符号。但是加减乘法等等,不用在意符号。