RUST编译结果的疑惑?

非常简单的测试代码:

fn main(){

    let _a = true;
    let _b = false;
    let _s:u32 = 17;
    let _c = true;
    let _d = false;
    
    //println!("{:p}", &s);
    //println!("{:p}", &c);
    //println!("{:p}", &d);

}

  (可以直接在play.rust-lang.org上查看编译结果,比较方便,免得记那么多rustc的编译指令了。)编译后:

playground::main: # @playground::main
# %bb.0:
    subq    $12, %rsp
    movb    $1, 2(%rsp)
    movb    $0, 3(%rsp)
    movl    $17, 4(%rsp)
    movb    $1, 10(%rsp)
    movb    $0, 11(%rsp)
    addq    $12, %rsp
    retq
                                        # -- End function

subq - 移动栈顶,为局部变量腾位置

mov* - 给栈帧赋值

这里可以看出,几个bool没什么大问题。(虽然也不知道第一个为什么要放到  2(%rsp)里,而不是直接放到栈顶呢??? )

在 let _s:i32之后的 let c = true;就显得很奇怪了。明明可以直接 moveb $1, 8(%rsp),为什么要多空出两个字节呢? 赋值给  10(%rsp)? 多出来的这两个字节有什么特别的用处吗?

当然,这些不影响整个临时栈的使用, 反正最后又add 12 rsp了,直接把栈顶还原了,即便是浪费,但不影响结果。

---------------------------

之所以好奇这个问题的原因,本来是在测试打印变量地址,好简单查看和计算变量实际占用空间大小的问题,结果发现减出来的结果不太对,就看了下汇编代码,才发现这个奇怪的现象的,如果用 u8 u16,好像依然是紧凑布局的,但是u64就空出来更多的字节了。

如果真想测试大小,在mem还有ptr的模块里,好像有几个专门的方法,如果就是想自己去计算查看,并且看具体地址,可以在struct里定义各种类型的变量,然后在去获取地址

当然,为了防止优化, 可以标记一下属性 repr(C) 或者 repr(packed),好取消RUST编译优化和设置内存布局的紧凑模式. 

(如果同时需要,就写成  #[repr(C,packed)] 就行了)

posted @ 2022-05-07 12:53  姜大伟  阅读(115)  评论(0编辑  收藏  举报