从阵列0初始化奇怪的组装 [英] Strange assembly from array 0-initialization

查看:162
本文介绍了从阵列0初始化奇怪的组装的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对这个问题<一个启发href=\"http://stackoverflow.com/questions/453432/difference-in-initalizing-and-zeroing-an-array-in-c-c\">Difference在initalizing并在C调零数组/ C ++?,我决定以实际研究大会,于我而言,一个优化的发行版本的Windows Mobile专业版(ARM处理器,从Microsoft优化编译器)。我发现,有些令人吃惊,我不知道是否有人能在我的关于它的问题提供一些线索。

Inspired by the question Difference in initalizing and zeroing an array in c/c++ ?, I decided to actually examine the assembly of, in my case, an optimized release build for Windows Mobile Professional (ARM processor, from the Microsoft Optimizing Compiler). What I found was somewhat surprising, and I wonder if someone can shed some light on my questions concerning it.

这两个例子进行检查:

byte a[10] = { 0 };

byte b[10];
memset(b, 0, sizeof(b));

它们在相同的功能使用,所以堆栈看起来像这样:

They are used in the same function, so the stack looks like this:

[ ] // padding byte to reach DWORD boundary
[ ] // padding byte to reach DWORD boundary
[ ] // b[9] (last element of b)
[ ]
[ ]
[ ]
[ ]
[ ]
[ ]
[ ]
[ ]
[ ] // b[0] = sp + 12 (stack pointer + 12 bytes)
[ ] // padding byte to reach DWORD boundary
[ ] // padding byte to reach DWORD boundary
[ ] // a[9] (last element of a)
[ ]
[ ]
[ ]
[ ]
[ ]
[ ]
[ ]
[ ]
[ ] // a[0] = sp (stack pointer, at bottom)

有我的评语生成的程序集:

The generated assembly with my comments:

; byte a[10] = { 0 };

01: mov   r3, #0        // r3 = 0
02: mov   r2, #9        // 3rd arg to memset: 9 bytes, note that sizeof(a) = 10
03: mov   r1, #0        // 2nd arg to memset: 0-initializer
04: add   r0, sp, #1    // 1st arg to memset: &a[1] = a + 1, since only 9 bytes will be set
05: strb  r3, [sp]      // a[0] = r3 = 0, sets the first element of a
06: bl    memset        // continue in memset

; byte b[10];
; memset(b, 0, sizeof(b));

07: mov   r2, #0xA      // 3rd arg to memset: 10 bytes, sizeof(b)
08: mov   r1, #0        // 2nd arg to memset: 0-initializer
09: add   r0, sp, #0xC  // 1st arg to memset: sp + 12 bytes (the 10 elements
                        // of a + 2 padding bytes for alignment) = &b[0]
10: bl    memset        // continue in memset

现在,有两件事情让我困惑:

Now, there are two things that confuses me:


  1. 什么是线02和05点?为什么不干脆放弃和放大器;一个[0]和10个字节memset的

  2. 为什么不的填充字节0初始化?是,只有在结构填充?

编辑:我太好奇,想不考结构情况:

I was too curious to not test the struct case:

struct Padded
{
    DWORD x;
    byte y;
};

0初始化它汇编:

The assembler for 0-initializing it:

; Padded p1 = { 0 };

01: mov   r3, #0
02: str   r3, [sp]
03: mov   r3, #0
04: str   r3, [sp, #4]

; Padded p2;
; memset(&p2, 0, sizeof(p2));

05: mov   r3, #0
06: str   r3, [sp]
07: andcs r4, r0, #0xFF
08: str   r3, [sp, #4]

在这里,我们一行04看到填充确实会发生,因为 STR (而不是 STRB )是用过的。对吧?

Here we see in line 04 that a padding indeed occur, since str (as opposed to strb) is used. Right?

推荐答案

原因线2和5是因为你在数组初始化指定的0。编译器将初始化所有的常量然后垫了用memset休息。如果你把两个零在你的初始化,你会看到它STRW(字而不是字节),那么memset的8个字节。

The reason for lines 2 and 5 is because you specified a 0 in the array initializer. The compiler will initialize all constants then pad out the rest using memset. If you were to put two zeros in your initializer, you'd see it strw (word instead of byte) then memset 8 bytes.

至于填料,它仅用于对准的存储器存取 - 的数据不应在正常情况下被使用,所以memsetting它是浪费

As for the padding, it's only used to align memory accesses -- the data shouldn't be used under normal circumstances, so memsetting it is wasteful.

编辑:为了记录在案,我可能是错的上述STRW假设。我的经验,ARM 99%是通过逆转GCC / LLVM对iPhone产生code,所以我的假设可能不结转到MSVC。

For the record, I may be wrong about the strw assumption above. 99% of my ARM experience is reversing code generated by GCC/LLVM on the iPhone, so my assumption may not carry over to MSVC.

这篇关于从阵列0初始化奇怪的组装的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆