了解获取内存位置的两段代码

Understanding two pieces of code which fetch memory locations

我的任务是构建一个成功的引导加载程序,但会导致所有重要的问题,即它为何起作用。通过它,我被两行非常相似的代码难住了。

    //Get the application stack pointer (1st entry in the application vector table)
    appStack = (uint32_t) *((__IO uint32_t*) APPLICATION_ADDRESS);

    //Get the application entry address (2nd entry in the application entry table)
    appEntry = (pFunction) *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);

我已经定义了APPLICATION_ADDRESS。我已将 pFunction 定义为指向函数的指针。这是我的理解尝试:

(忽略 __IO 因为这只是意思 volatile

(__IO uint32_t*) APPLICATION_ADDRESS)APPLICATION_ADDRESS 转换为一个指针,returns 一个 32 位无符号整数。这意味着如果我们转到地址 APPLICATION_ADDRESS 将会有另一个内存位置的地址包含 uint32_t.

*((__IO uint32_t *) APPLICATION_ADDRESS) 中,我们使用解引用运算符来获取 APPLICATION_ADDRESS 指向的值。 APPLICATION_ADDRESS 指向另一个地址,该地址包含一个将被返回的值。 (uint32_t) 然后将此值转换为 uint32_t.

按照我的理解,转换是多余的,因为你已经说过变量保持在括号内 uint32_t

这与我对下一行的理解相矛盾。为什么我们最初没有将 APP_ADDRESS + 4 定义为括号内的 pFunction

最后我对括号排列的差异感到困惑。为什么取消引用运算符不包围整个 int_32(APPLICATION_ADDRESS +4) 像这样:

*((__IO uint32_t*) (APPLICATION_ADDRESS + 4))

或者这是用括号矫枉过正,只是不需要吗?

你有一些正确的假设和一些错误的假设。

您似乎在记忆中的固定位置存储了 2 个值:

APPLICATION_ADDRESS + 0  +----------------------+
                         |     Stack            |
                    + 4  +----------------------+
                         |     pFunction        |
                    + 8  +----------------------+

现在让我们看看您的假设:

(__IO uint32_t*) APPLICATION_ADDRESS) casts APPLICATION_ADDRESS to be a pointer which returns a 32-bit unsigned integer.

是的,正确。

This means if we go to address APPLICATION_ADDRESS there will be another address of a memory location holding a uint32_t.

接近但不正确。

在位置 APPLICATION_ADDRESS 你没有找到另一个整数地址,但在那里你找到了所述整数本身。

In *((__IO uint32_t *) APPLICATION_ADDRESS) we use the dereference operator to gain the value the APPLICATION_ADDRESS is pointing to.

是的。 好吧,有点迂腐,APPLICATION_ADDRESS 没有指向任何地方。它只是一个普通数字,而不是指针。这就是为什么您需要将所有类型转换为各种指针类型的原因。

The APPLICATION_ADDRESS points to another address which holds a value which will be returned. The (uint32_t) then casts this value to be uint32_t.

不,APPLICATION_ADDRESS 那个整数的地址。

Following my line of understanding renders the casting redundant as you have already said the variable held is uint32_t within the brackets.

正确。

This then contradicts my understanding of the next line. Why haven't we defined APP_ADDRESS + 4 to be a pFunction within the brackets initially?

从整数到指针的转换取决于实现。函数地址更多。如果内存内容定义为 32 位整数,则必须使用该类型读取它。然后,您可以根据需要进行任何转换。 这可能只会产生相同的值,也可能会有所不同。这取决于体系结构。

Finally I am confused with the difference in brackets arrangements. Why does the dereference operator not surround the whole int_32 and (APPLICATION_ADDRESS +4) like so:

*((__IO uint32_t*) (APPLICATION_ADDRESS + 4))

or is this overkill with brackets and it is just not required?

不需要外括号。 内括号很重要。如果没有方括号,转换将比添加具有更高的优先级。那么你不会将 4 个字节添加到地址,而是 4 个内存对象的大小,这里将是 16 个字节。