标签: low-level

callstack究竟是如何工作的?

我试图更深入地了解编程语言的低级操作是如何工作的,尤其是它们如何与OS/CPU交互.我可能已经在Stack Overflow上的每个堆栈/堆相关线程中阅读了每个答案,并且它们都很棒.但还有一件事我还没有完全理解.

在伪代码中考虑这个函数,这往往是有效的Rust代码;-)

fn foo() {
    let a = 1;
    let b = 2;
    let c = 3;
    let d = 4;

    // line X

    doSomething(a, b);
    doAnotherThing(c, d);
}
Run Code Online (Sandbox Code Playgroud)

这就是我假设堆栈在X行上的样子:

Stack

a +-------------+
  | 1           | 
b +-------------+     
  | 2           |  
c +-------------+
  | 3           | 
d +-------------+     
  | 4           | 
  +-------------+ 
Run Code Online (Sandbox Code Playgroud)

现在,我读到的关于堆栈如何工作的一切都是它严格遵守LIFO规则(后进先出).就像.NET,Java或任何其他编程语言中的堆栈数据类型一样.

但如果是这样,那么在X行之后会发生什么?显然,接下来我们需要的是使用ab,但这意味着操作系统/ CPU(?)必须弹出dc首先回到ab.但是它会在脚下射击,因为它需要c并且d在下一行.

所以,我想知道幕后究竟发生了什么?

另一个相关问题.考虑我们传递对其他函数的引用,如下所示:

fn foo() {
    let …
Run Code Online (Sandbox Code Playgroud)

cpu assembly callstack calling-convention low-level

99
推荐指数
5
解决办法
2万
查看次数

如何在C++类内存结构中创建"spacer"?

问题

低级裸机嵌入式上下文中,我想在内存中创建一个空格,在C++结构中并且没有任何名称,以禁止用户访问这样的内存位置.

现在,我已经通过设置一个丑陋的uint32_t :96;位域来实现它,它将方便地取代三个单词,但它会从GCC发出警告(Bitfield太大而不适合uint32_t),这是非常合理的.

虽然它工作正常,但是当你想要分发一个包含数百个警告的库时它不是很干净......

我该怎么做呢?

为什么首先出现问题?

我正在研究的项目包括定义整个微控制器线路(STMicroelectronics STM32)的不同外设的存储器结构.为此,结果是一个类,它包含几个结构的并集,这些结构定义了所有寄存器,具体取决于目标微控制器.

一个非常简单的外设的一个简单示例如下:通用输入/输出(GPIO)

union
{

    struct
    {
        GPIO_MAP0_MODER;
        GPIO_MAP0_OTYPER;
        GPIO_MAP0_OSPEEDR;
        GPIO_MAP0_PUPDR;
        GPIO_MAP0_IDR;
        GPIO_MAP0_ODR;
        GPIO_MAP0_BSRR;
        GPIO_MAP0_LCKR;
        GPIO_MAP0_AFR;
        GPIO_MAP0_BRR;
        GPIO_MAP0_ASCR;
    };
    struct
    {
        GPIO_MAP1_CRL;
        GPIO_MAP1_CRH;
        GPIO_MAP1_IDR;
        GPIO_MAP1_ODR;
        GPIO_MAP1_BSRR;
        GPIO_MAP1_BRR;
        GPIO_MAP1_LCKR;
        uint32_t :32;
        GPIO_MAP1_AFRL;
        GPIO_MAP1_AFRH;
        uint32_t :64;
    };
    struct
    {
        uint32_t :192;
        GPIO_MAP2_BSRRL;
        GPIO_MAP2_BSRRH;
        uint32_t :160;
    };
};
Run Code Online (Sandbox Code Playgroud)

所有GPIO_MAPx_YYY都是宏,定义为uint32_t :32或寄存器类型(专用结构).

在这里,您可以看到uint32_t :192;哪个效果很好,但它会触发警告.

到目前为止我考虑过的事情:

我可能已经用几个替换它uint32_t :32;(这里有6个),但我有一些极端情况,我有uint32_t :1344;(42)(其中).所以我宁愿不在8k其他行上添加大约100行,即使结构生成是脚本化的.

确切的警告信息是这样的:( width of 'sool::ll::GPIO::<anonymous union>::<anonymous struct>::<anonymous>' …

c c++ memory-management bare-metal low-level

93
推荐指数
6
解决办法
5632
查看次数

为什么要在汇编中编程?

我对那里的所有核心低级黑客都有疑问.我在博客中遇到了这句话.我并不认为这些来源很重要(如果你真的在意,那就是Haack),因为它似乎是一个常见的陈述.

例如,许多现代3D游戏都有他们用C++和Assembly编写的高性能核心引擎.

就程序集而言 - 是用汇编编写的代码,因为你不希望编译器发出额外的指令或使用过多的字节,或者你使用的是更好的算法,你无法在C中表达(或者没有表达编译器把它们搞砸了)?

我完全明白了解低级别的东西很重要.我只想在你理解它之后理解为什么程序在汇编.

c performance assembly low-level

85
推荐指数
11
解决办法
6万
查看次数

哪个更快:x << 1或x << 10?

我不想优化任何东西,我发誓,我只想出于好奇而问这个问题.我知道,在大多数硬件有位移(例如的组件的命令shl,shr),它是一个命令.但是,你转移了多少比特(纳秒级,或CPU技巧)是否重要?换句话说,在任何CPU上是否更快?

x << 1;
Run Code Online (Sandbox Code Playgroud)

x << 10;
Run Code Online (Sandbox Code Playgroud)

请不要因为这个问题而恨我.:)

c c++ cpu performance low-level

82
推荐指数
8
解决办法
7018
查看次数

为什么bit endianness是bitfields中的一个问题?

任何使用位域的可移植代码似乎都区分了小端和大端平台.有关此类代码的示例,请参阅linux内核中struct iphdr声明.我无法理解为什么位字节序是一个问题.

据我所知,bitfields纯粹是编译器构造,用于促进位级操作.

例如,考虑以下位域:

struct ParsedInt {
    unsigned int f1:1;
    unsigned int f2:3;
    unsigned int f3:4;
};
uint8_t i;
struct ParsedInt *d = &i;
只是一种简洁易懂的说法d->f2.

但是,无论架构如何,位操作都是明确定义的并且可以正常工作.那么,bitfields怎么不便携?

c portability cross-platform low-level bit-fields

54
推荐指数
4
解决办法
3万
查看次数

要学习汇编 - 我应该从32位还是64位开始?

我真的很想学习装配.我非常擅长c/c ++,但希望更好地了解较低级别的内容.

我意识到之前已经提出了与装配相关的问题,但我只是在寻找一些特定于我的情况的方向:

我正在运行Windows 7,我对如何开始使用汇编感到困惑.我是否必须从x64开始,因为我正在运行Windows 7?有些人说"先从32位开始" - 我该如何做呢?我的操作系统与我为'32'或'64'位写入汇编的能力有什么关系.事实上,'n位'汇编意味着什么,其中n是一个数字?


编辑:

以下是一些帮助我开始组装的链接; 刚刚入门的其他人可能会发现它们很有帮助.随着我继续组装之旅,我将继续更新此列表:)

注意:正如我一直在学习的那样,我决定专注于使用masm32进行编程.因此,以下大多数资源都集中于此.

x86 assembly x86-64 low-level

52
推荐指数
2
解决办法
3万
查看次数

操作系统如何"制造"?

创建操作系统似乎是一个庞大的项目.怎么会有人开始?

例如,当我将Ubuntu弹出到我的驱动器中时,我的计算机如何才能运行它? (我想,这是我真正想知道的.)

或者,从另一个角度来看,磁盘上可能存在的字节数最少,仍然可以作为操作系统"运行"?

(我很抱歉,如果这是模糊的.我只是不知道这个主题,所以我不能非常具体.我假装知道关于计算机如何工作的相当数量,但我对这个主题完全无能为力. )

operating-system osdev low-level

46
推荐指数
5
解决办法
2万
查看次数

为什么矢量化一般比循环更快?

为什么,在硬件执行操作的最低级别和所涉及的一般底层操作(即:运行代码时所有编程语言的实际实现的一般性),矢量化通常比循环更快?

当使用矢量化时,计算机在循环时做了什么(我说的是计算机执行的实际计算,而不是程序员编写的计算),或者它有什么不同的做法?

我一直无法说服自己为什么差异应该如此重要.我可能会说服矢量化代码在某处削减一些循环开销,但计算机仍然必须执行相同数量的操作,不是吗?例如,如果我们将大小为N的向量乘以标量,我们将使用N次乘法执行任一方式,不是吗?

language-agnostic performance vectorization low-level

46
推荐指数
3
解决办法
9057
查看次数

使用位移除以10?

是否有可能通过使用纯位加法,减法除以10的无符号整数,也许繁衍?使用资源非常有限且速度慢的处理器.

math bit low-level integer-division micro-optimization

41
推荐指数
4
解决办法
5万
查看次数

为什么Linux不通过TSS使用硬件上下文切换?

我读了以下声明:

x86架构包括称为任务状态段(TSS)的特定段类型,用于存储硬件上下文.尽管Linux不使用硬件上下文切换,但它仍然被迫为系统中的每个不同CPU设置TSS.

我想知道:

  • 为什么Linux不使用硬件支持进行上下文切换?
  • 硬件方法不是比软件方法快得多吗?
  • 是否有任何操作系统可以利用硬件上下文切换?Windows使用它吗?

最后一如既往,感谢您的耐心和回复.

- - - - - -添加 - - - - - - -

http://wiki.osdev.org/Context_Switching得到了一些解释.

像我这样迷茫的人可以看看它.8 ^)

linux x86 low-level linux-kernel

39
推荐指数
3
解决办法
1万
查看次数