你有很多问题。
首先,让我们假设一个简单的情况,比如 Arduino,它是软件和硬件的组合。
软件部分从您编写一些简单的 C++ 代码开始,例如:
byte ledPin = 13;
void setup(){
pinMode (ledPin, OUTPUT);
}
void loop(){
digitalWrite (ledPin, HIGH);
digitalWrite (ledPin, LOW);
}
接下来,您将编译代码。 Arduino IDE(集成开发环境)做了一些事情(在后台,比如添加一个 main() 来调用 setup()
函数一次,循环()函数重复)将 C++ 转换为汇编代码,它可能看起来像这样(不是上面的实际输出):
; Define pull-ups and set outputs high
; Define directions for port pins
ldi r16,(1<<PB7)|(1<<PB6)|(1<<PB1)|(1<<PB0)
ldi r17,(1<<DDB3)|(1<<DDB2)|(1<<DDB1)|(1<<DDB0)
out PORTB,r16
out DDRB,r17
; Insert nop for synchronization
nop
; Read port pins
in r16,PINB
汇编程序将代码转换为十六进制格式信息,程序员可以将其放入 Atmega328P 微控制器的 ROM 中。基本上,文件中的数据行,每行包含一行的起始地址,可能是 16 个字节的数据,以及一个校验和,以确保数据在处理时没有损坏:
000100005673495a6b4f5e205673495a6b4f5e24465
这不是真实数据。 0001000 可能是 ROM 中的起始地址,接下来的 32 个字符是要编程的 16 个字节的数据,最后 4 个可能是通过以某种方式操作数据创建的校验和。程序员接收数据,执行相同的操作,如果校验和正确,则将其刻录到内存中。
可以通过多种方式将十六进制代码放入 ROM - 程序员可以控制芯片并将代码直接放入内存,复位后芯片将运行代码;或者引导加载程序可以复位后从芯片上的 ROM 区域运行,它会通过串行线(Rx,Tx)与 PC 通信以接收数据,然后将其写入 ROM 的不同区域。如果引导加载代码没有检测到 PC 试图与其通信,它将跳转到代码开始的 ROM 地址并从那里运行。
8 位微控制器可能有一些 16 位寄存器,可用于捕获 ADC 转换的结果,或者将结果存储为两个 8 位字节,包含高位和低位数据。
堆栈可能是专用的硬件寄存器,也可能是 SRAM 的一个区域,用于保存诸如数学运算结果之类的东西。代码负责将内容放入堆栈并读回,您通常不会处理它的编程。对于 '328P,有 2048 字节的 SRAM,因此您只需要确保没有在代码中声明太多变量(如 byte ledPin = 13;),这些变量都用完了并且没有留下空间对于代码。通常,例如在 328Ps 中,这是由于尝试访问超出其限制的数组而引起的,因此要么返回无意义的结果,要么在写入超过数组末尾的内容覆盖其他内容时导致程序崩溃。 C++的灵活性很好,但稍不注意也会让你陷入困境。