1.实时系统概念
2.编译连接
3.AT&T汇编指令学习(GCC)
4.内存对齐
5.Big-Endian大端模式和Little-Endian小端模式
6.过程调用
后台是各种面向硬件的程序,如中断,定时器,gpio等。
前台是:
main()
{
while(1)
{
;
}
}
循环中不断调用各种函数实现功能。
指处理时不可分割的代码,一旦这部分代码运行就不可以打断、
为了确保代码能正常运行,进入临界段代码钱需要关中断,执行完后再开中断。
一个任务也就是一个线程,是一个简单的程序。
任务间通信最简单的办法是使用数据共享结构。
任务间通信途径:1)全局变量;2)发消息给另一个任务。
任务切换(context switch)
不可剥夺型内核,允许使用不可重入函数。
可剥夺型内核,,最高优先级的任务一就绪,总能得到CPU的使用权。,不能直接使用不可重入函数。
处理共享数据时保证互斥,最简单的办法是关中断和开中断。
一种约定机制。
就好像一把钥匙。任务要运行下去需要获得信号量,且信号量没有被占用。
两个任务相互等待对方释放资源。
一个中断或者任务触发另一个任务。
一种内存共享方式。
特定的周期性中断,如同系统的心脏。
包含代码和数据
可被用来链接成执行文件或者共享目标文件
linux(.o) windows(.obj)
包含可以执行的程序
系统可以直接执行的文件
linux (ELF文件,无后缀) windows (.exe)
包含代码和数据
跟可重定位文件和共享目标文件链接,产生新的目标文件
动态连接器将共享目标文件与可执行文件结合,作为进程映像的一部分来运行
linux(.so) windows (.DLL)
Linux(core dump)
file header
目标文件头
code section
程序指令(.code /.text)
存放程序代码程序
data section
程序数据(.data /.bss)
.data段 初始化的全局和局部静态变量
.bss段 未初始化的全局和局部静态变量
.bss(block started by symbol)符号预留块,没有内容不占据空间
othe section
还有可能包含的其他段,例 bank data .ect
程序指令和数据分开存放的优点?3点。
操作码命令格式:
源/目的操作数顺序:
Intel语法格式中命令表示格式为:”opcode dest, src”; “操作码 目标, 源”
AT&T语法格式表示为:”opcode src, dest”; “操作码 源, 目标”
操作数长度标识:
在AT&T语法中,通过在指令后添加后缀来指明该指令运算对象的尺寸.
后缀 ‘b’ 指明运算对象是一个字节(byte)
后缀 ‘w’ 指明运算对象是一个字(word)
后缀 ‘l’ 指明运算对象是一个双字(long)
Intel语法中指令’mov’在AT&T语法必须根据运算对象的实际情况写成:’movb’,’movw’或’movl’。
注:若在AT&T中省略这些后缀,GAS将通过使用的寄存器大小来猜测指令的操作数长度.
SECTION:[BASE + INDEX*SCALE + DISP];
段:[基地址+变址*比例因子+偏移量] SECTION:DISP(BASE, INDEX, SCALE);
段:偏移量(基地址,变址,比例因子) asm("statements");
asm ( "statements" : output_regs : input_regs : clobbered_regs);
条件码寄存器(单个bit):
cf(进位标志),zf(零标志),sf(符号标志),of(溢出标志)…
访问条件码指令:cmp,test,set…
t = a + b;
cf: (unsigned) t < (unsigned) a;//无符号溢出
zf: t == 0;//零
sf: t < 0;//负数
of: (a < 0 == b < 0) && (t < 0 != a < 0)//有符号溢出
内存对齐的规则
许多实际的计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据的首地址的值是某个数k(通常它为4或8)的倍数,这就是所谓的内存对齐,而这个k则被称为该数据类型的对齐模数(alignment modulus)。当一种类型S的对齐模数与另一种类型T的对齐模数的比值是大于1的整数,我们就称类型S的对齐要求比T强(严格),而称T比S弱(宽松)。这种强制的要求一来简化了处理器与内存之间传输系统的设计,二来可以提升读取数据的速度。
比如这么一种处理器,它每次读写内存的时候都从某个8倍数的地址开始,一次读出或写入8个字节的数据,假如软件能保证double类型的数据都从8倍数地址开始,那么读或写一个double类型数据就只需要一次内存操作。否则,我们就可能需要两次内存操作才能完成这个动作,因为数据或许恰好横跨在两个符合对齐要求的8字节内存块上。某些处理器在数据不满足对齐要求的情况下可能会出错.
但是Intel的IA32架构的处理器则不管数据是否对齐都能正确工作。不过Intel奉劝大家,如果想提升性能,那么所有的程序数据都应该尽可能地对齐。
定义
- Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。
- Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。
- 网络字节序:TCP/IP各层协议将字节序定义为Big-Endian,因此TCP/IP协议中使用的字节序通常称之为网络字节序.
- 高/低字节定义:在十进制中我们都说靠左边的是高位,靠右边的是低位,在其他进制也是如此。就拿 0x12345678来说,从高位到低位的字节依次是0x12、0x34、0x56和0x78.
例子分析:
unsigned int value = 0x12345678
1.Big-Endian: 低地址存放高位
|
||
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
2.Little-Endian: 低地址存放低位
|
||
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
在Little-endian模式CPU内存中的存放方式(假设从地址0x4000开始存放)
内存地址 | 0x4000 | 0x4001 | 0x4002 | 0x4003 |
---|---|---|---|---|
存放内容 | 0x78 | 0x56 | 0x34 | 0x12 |
在Big- endian模式CPU内存中的存放方式则为
内存地址 | 0x4000 | 0x4001 | 0x4002 | 0x4003 |
---|---|---|---|---|
存放内容 | 0x12 | 0x34 | 0x56 | 0x78 |
注意:通常我们说的主机序(Host Order)就是遵循Little-Endian规则。所以当两台主机之间要通过TCP/IP协议进行通信的时候就需要调用相应的函数进行主机序 (Little-Endian)和网络序(Big-Endian)的转换。
检查CPU是大端还是小端:
int checkCPU(void)
{
union
{
int a;
char b;
}c;
c.a = 1;
return (c.b == 1);
}
说明:
返回值在相对%ebp偏移量为4的位置;
第一个参数放在相对于%ebp偏移量为8的位置;
支持过程调用和返回的指令:
一个过程调用的整个汇编流程示意: