我有一组用于嵌入式应用程序(ARM 裸机)中的外设的 32 位寄存器,具有以下字节地址。
CTL 0x0;
STAT 0x4
TXR 0x8 <-- 不连续地址
RXR 0x20
DAT1 0x30 <-- 不连续地址
DAT2 0x40 <-- 不连续地址
等等
我想将所有这些寄存器分组到一个 C 结构中(它是一个打包结构)
struct my_peri {
uint32_t CTL;
uint32_t STAT;
uint32_t TXR;
uint32_t RXR;
uint32_t DAT1;
uint32_t DAT2;
};
struct my_peri* pPeri0 = (uint32_t*) (BASE_ADDRESS_OF_MY_PERI_0);
Run Code Online (Sandbox Code Playgroud)
现在如果我访问
pPeri->RXR; // This will point to (BASE_ADDRESS + 0x10)
// But the actual address i want to refer is (BASE_ADDRESS + 0x20)
Run Code Online (Sandbox Code Playgroud)
为了获得正确的地址,我在之间手动添加了一些元素
struct my_peri {
uint32_t CTL;
uint32_t STAT;
uint32_t …Run Code Online (Sandbox Code Playgroud) 我使用 linaro g++ for ARM arch64 编译一个简单的 cpp 文件:
int main()
{
char *helloMain = "main module (crm.c)";
long faculty, num = 12;
int stop,mainLoop = 1;
char word[80] = "";
}
Run Code Online (Sandbox Code Playgroud)
objdump生成elf文件后,我得到了它的asm代码:
0000000000001270 <main>:
int main()
{
1270: d101c3ff sub sp, sp, #0x70
char *helloMain = "main module (crm.c)";
1274: 90000020 adrp x0, 5000 <_malloc_trim_r+0x160>
1278: 9111c000 add x0, x0, #0x470
127c: f90003e0 str x0, [sp]
long faculty, num = 12;
1280: d2800180 movz x0, #0xc
1284: f90007e0 …Run Code Online (Sandbox Code Playgroud) 更新:numpy 错误。
不幸的是以下情况:
import numpy as np
a = np.zeros(4, dtype=np.dtype([('t', '<f8'), ('d', [('a', '<i4'), ('b', '<f8')], (100,))], align=True))
b = np.require(a, requirements=['ALIGNED'])
print([x.flags['ALIGNED'] for x in [a, b]])
Run Code Online (Sandbox Code Playgroud)
印刷[False, False]!
我该如何对齐a?
我想我理解堆栈对齐是4字节,例如,如果我只添加一个字符,他的地址将位于4字节的右侧(如果还有其他1或2字节变量,则稍早一点)
我仍然无法理解堆中的对齐方式,我认为有 4 字节或 8 字节对齐,但事情是这样的,当我分配 100 然后 20 字节时,第一个字节的末尾和开头之间有 4 个字节第二个,所以我猜测堆将使用 8 字节对齐。
通过连续分配 1 4 7 8 9 14 16 17 字节,我注意到 1、4、7、8、9 各占用 16 字节,14 16 17 各占用 24 字节,为什么呢?
我正在使用 C/C++ 并使用 malloc 进行分配(与 new 相同)。
谢谢。
我知道这个问题已经被问了一千次,我已经通读了每一个答案,但我仍然不明白。我的 RAM 模型可能存在一些基本错误,这使我无法理解任何答案。
我从互联网上获得了所有这些小信息,但我无法连接它们。
以下是我目前所知道的:以 IA-32 架构为例,其字边界为 32 位(边界 = CPU 可以从内存中读取的最大值?)。它将始终在其字边界内读取。
1)那么,无论我给它什么地址,它总是会读取 4 个字节?如果我在地址 x 有一个简单的字符怎么办。它会从那个地址读取 4 个字节,然后做一些奇怪的事情来只得到一个字节吗?
2)如果是这样,那么字符串(字符序列)n_chars * 4 字节大吗?我很确定它不是那样的,但是我应该如何解释“将始终阅读其单词边界”呢?
3)内存对齐似乎只与数据结构有关。为什么?内存的其余部分是否未对齐?我的意思是物理、虚拟、内核空间等?
4) 为什么我只能在可被 4 整除的地址中存储 32 位值?我的意思是我知道它最终只会读取 32 位,但为什么它不能从奇数地址读取 32 位?比如这里的限制是什么?
我只是很困惑请帮助我
我是 C++ 新手,所以我正在尝试一些 leetcode 问题。我目前正在尝试最小堆栈问题。我想我已经正确解决了它,除了我从 leetcode 得到以下运行时错误:
Line 24: Char 37: runtime error: member access within misaligned address 0xbebebebebebebebe for type 'struct ListNode', which requires 8 byte alignment (solution.cpp)
Run Code Online (Sandbox Code Playgroud)
这是我的 Visual Studio 代码,带有测试 - 错误源自 push() 中的以下行:
topStackNode->stackPrev = newNode;
Run Code Online (Sandbox Code Playgroud)
有谁知道什么会导致这种情况发生?我读了一点,一些有类似错误的人说这是因为 ListNode 没有初始化为 NULL,但我清楚地在我的结构中将所有 ListNode 初始化为 NULL。谢谢!
#include <vector>
#include <iostream>
using namespace std;
// design a stack that supports push, pop, top, and retrieving the minimum element in constant time
class MinStack {
struct ListNode {
ListNode* stackNext;
ListNode* …Run Code Online (Sandbox Code Playgroud) 正如标题所暗示的,问题是关于Linux 上 x86-64 中聚合类型的对齐。
在我们的讲座中,教授介绍了结构(及其元素)与附加幻灯片的对齐方式。因此,我会假设(根据维基百科和其他讲座材料)对于任何聚合类型,对齐是根据其最大成员。不幸的是,在以前的考试问题中似乎并非如此,它说:
“假设每个页表 [4kB,每个 PTE 64b] 都存储在内存中一个“自然对齐”的物理地址(即一个表大小的整数倍的地址),......”
为什么对于页表(它基本上是内存中的 8 字节值的数组),对齐规则不是根据最大的元素,而是根据整个表的大小?
我正在尝试重新实现 malloc 并且我需要了解对齐的目的。据我了解,如果内存对齐,代码将执行得更快,因为处理器不必采取额外的步骤来恢复被切割的内存位。我想我明白 64 位处理器读取 64 位 x 64 位内存。现在,让我们假设我有一个按顺序排列的结构(没有填充):一个字符、一个短字符、一个字符和一个整数。为什么短路会错位?我们拥有区块中的所有数据!为什么它必须在一个 2 的倍数的地址上。对于整数和其他类型,同样的问题?
我还有第二个问题:使用我之前提到的结构,处理器如何知道当它读取它的 64 位时前 8 位对应于一个字符,然后接下来的 16 位对应于一个短等等......?
目的:了解 C++17 引入std::aligned_alloc动态内存管理的动机。
问题:对于 C++ 中的内存分配,std::malloc由于在什么情况下使用 malloc 和/或 new?. 相反,new在低级代码中几乎总是鼓励使用表达式(例如参见注释)。
尽管有这种气馁,我想知道为什么 C++17 引入了std::aligned_alloc它看起来像std::malloc.
C ++ 17(及更高版本)中是否有任何内容new(或其他鼓励使用的等效实用程序,如果有)无法执行?
尝试:我只能找到以下讨论,这仍然与我的问题有很大关系:
我试图让自己熟悉 AES 指令,然后使用能够更有意识地利用这些技术的库。然而,我不经常用汇编编程,所以我对这门语言有一些信心,但我不认为自己是专家。我已经编写了大约 150 条装配线的清单,以尝试使用英特尔提供的文档来使用这些功能。然而,我并没有成功地向前迈出许多步骤。
当我使用该指令时,由于 main 中的分段错误,程序崩溃了movaps。我已经尝试使用 gdb 和 valgrind 进行调试,但似乎一切正常,但事实并非如此。以下是导致问题的行。
main:
start_f
printstr
movaps (string), %xmm15
==> movaps (key), %xmm0
call aes_encript
movaps %xmm15, string
printstr
end_f
Run Code Online (Sandbox Code Playgroud)
start_f并且end_f只是宏来启动和结束函数。我还提供了 .data 部分的代码,以显示应该没有问题:
.data
string:
.string "string"
.fill (128 - (.-string)), 1, 0
newline:
.byte 0x0a
key:
.fill 128, 1, 0
.text
.global _start
Run Code Online (Sandbox Code Playgroud)
至于错误,无论是通过静态反汇编还是在gdb中,我都无法获得任何有用的信息。Valgrind 也没有帮助,这是意料之中的,因为我根本不接触堆。我展示了 gdb 中主要反汇编的部分清单:
0x0000000000401022 <+0>: push %rbp
0x0000000000401023 <+1>: mov %rsp,%rbp
0x0000000000401026 <+4>: mov $0x402000,%rsi
0x000000000040102d <+11>: call …Run Code Online (Sandbox Code Playgroud)