WebAssembly中如何评估类型“ i32”的值?

问题描述

根据以下规范文字

请注意,值类型i32和i64本身不是带符号的或无符号的。这些类型的解释由各个操作员决定。

由于我们不知道i32类型的传递参数的签名,因此i32.add如何对这两个参数执行加法运算?而且,如果我们将此函数导出到JavaScript,应该如何评估结果?例如,可以将0xffffffff评估为具有不同符号(4294967295或-1)的不同数字。

(module
  (func (export "addTwo") (param i32 i32) (result i32)
    local.get 0
    local.get 1
    i32.add))

解决方法

该符号与添加无关紧要。如果您有一些位git branch -D branch_name,则可以将它们解释为带符号的值X或无符号的值S_X。重要的是,由于两者的补码是如何工作的,因此两者之间的区别要么是U_X要么是0

例如,如果X为全1,则2^32S_X == -1。请注意,差异为U_X == 2^32 - 1。如果X均为0,则两个值均为0,且差值为0。

因此,您可以写2^32,其中S_X = U_X + D_X是差值,为0或D_X。然后将2^32签名添加到X

Y

最后一步很重要:我们可以忽略S_X + S_Y = U_X + D_X + U_Y + D_Y = U_X + U_Y的值,因为它们是D_*的倍数,并且我们假设我们回绕了-即高于32的位只是被忽略了。

对于所有操作,不是是真的。例如,由于这个原因,除法有两个操作,有符号的和无符号的。但是加法,减法,乘法等并不关心符号。

,

WebAssembly要求将-a + b编写为b - a

使用WebAssembly Explorer

int add(int a,int b) { return a + b; }

编译为此:

(i32.add(get_local $1)(get_local $0))

与此同时(请注意否定的-a

int add(int a,int b) { return -a + b; }

编译为此(注意,用sub段而不是add):

(i32.sub(get_local $0)(get_local $1))