当前位置: 首页 > article >正文

嵌入式知识点总结 ARM体系与架构 专题提升(四)-编程

 针对于嵌入式软件杂乱的知识点总结起来,提供给读者学习复习对下述内容的强化。

目录

1.嵌人式编程中,什么是大端?什么是小端 ?

2.如何判断计算机处理器是大端,还是小端 ?

3.如何进行大小端的转换 ?

4.如何对绝对地址0x100000赋值?


1.嵌人式编程中,什么是大端?什么是小端 ?

在嵌入式编程中,大端和小端是字节序(Byte Order)的概念,用于描述多字节数据在内存中的存储方式。

大端存储是指将数据的高字节存储在低地址,低字节存储在高地址的一种方式。

假设有一个32位整数 0x12345678,在内存中的存储方式如下(地址从小到大):

地址数据(字节值)
0x000x12
0x010x34
0x020x56
0x030x78

特点:数据从高字节到低字节依次存储。

小端存储是指将数据的低字节存储在低地址,高字节存储在高地址的一种方式。

同样的32位整数 0x12345678,在内存中的存储方式如下(地址从小到大):

地址数据(字节值)
0x000x78
0x010x56
0x020x34
0x030x12

特点:数据从低字节到高字节依次存储。

大端

通常用于网络传输(网络字节序)。

更符合人类阅读习惯(从高位到低位)。

小端

大多数嵌入式设备和PC(如Intel、ARM)采用小端存储。

存储和访问数据时效率更高(低地址直接存储低字节)。

2.如何判断计算机处理器是大端,还是小端 ?

#include <stdio.h>

int main() {
    unsigned int x = 0x12345678;  // 一个32位整数
    unsigned char *ptr = (unsigned char *)&x; // 取x的地址并转为字节指针

    if (*ptr == 0x78) {
        printf("Little-Endian (小端模式)\n");
    } else if (*ptr == 0x12) {
        printf("Big-Endian (大端模式)\n");
    } else {
        printf("Unknown Byte Order\n");
    }

    return 0;
}

如果输出Little-Endian (小端模式),说明低字节存储在低地址(小端)。

如果输出Big-Endian (大端模式),说明高字节存储在低地址(大端)。

补充:*ptr存的起始地址嘛

3.如何进行大小端的转换 ?

大小端的转换是指在内存中交换数据的字节顺序,将大端存储格式转换为小端存储格式,或反之。这通常用于跨平台数据通信、存储格式兼容性处理等场景。

通过按位操作手动调整字节顺序。

#include <stdio.h>

unsigned int swap_endian(unsigned int x) {
    return ((x & 0xFF000000) >> 24) | // 高8位 -> 低8位
           ((x & 0x00FF0000) >> 8)  | // 次高8位 -> 次低8位
           ((x & 0x0000FF00) << 8)  | // 次低8位 -> 次高8位
           ((x & 0x000000FF) << 24);  // 低8位 -> 高8位
}

int main() {
    unsigned int x = 0x12345678;
    unsigned int y = swap_endian(x);
    printf("Original: 0x%x\n", x);
    printf("Converted: 0x%x\n", y);
    return 0;
}
Original: 0x12345678
Converted: 0x78563412

4.如何对绝对地址0x100000赋值?

通过将绝对地址类型转换为指针并进行解引用,可以对该地址赋值。

#include <stdio.h>

int main() {
    unsigned int *addr = (unsigned int *)0x100000; // 将绝对地址0x100000转为指针
    *addr = 0x12345678;                            // 向地址写入值
    printf("Value at 0x100000: 0x%x\n", *addr);    // 打印地址中的值
    return 0;
}

地址合法性

需要确保 0x100000 是有效的内存地址。

该地址可能位于特定设备寄存器区域(如外设地址)或已映射的内存区域。

使用无效地址会导致段错误 (Segmentation Fault) 或异常。

访问权限

确保程序有权访问该地址,某些地址可能需要特定的权限(如特权模式下的访问)。

编译器优化

某些编译器可能会优化掉对特定地址的操作。如果是硬件相关的地址访问,建议将指针声明为 volatile,以防止编译器优化。

volatile unsigned int *addr = (unsigned int *)0x100000;

操作系统影响

在裸机(无操作系统)开发环境中,直接访问绝对地址通常是可行的。

在操作系统(如 Linux)中,用户态程序无法直接访问绝对物理地址,需通过内核驱动或内存映射接口(如 mmap)实现。

如果是在 Linux 用户态下操作绝对地址,可以使用 mmap 进行内存映射。

#include <fcntl.h>
#include <sys/mman.h>
#include <stdio.h>
#include <unistd.h>

#define PHYS_ADDR 0x100000  // 物理地址
#define MAP_SIZE  0x1000    // 映射大小

int main() {
    int fd = open("/dev/mem", O_RDWR | O_SYNC); // 打开物理内存设备
    if (fd < 0) {
        perror("open /dev/mem failed");
        return -1;
    }

    void *mapped_addr = mmap(NULL, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, PHYS_ADDR);
    if (mapped_addr == MAP_FAILED) {
        perror("mmap failed");
        close(fd);
        return -1;
    }

    volatile unsigned int *addr = (unsigned int *)mapped_addr;
    *addr = 0x12345678; // 写入值
    printf("Value at 0x100000: 0x%x\n", *addr);

    munmap(mapped_addr, MAP_SIZE); // 解除映射
    close(fd);
    return 0;
}

在裸机开发中,直接使用指针操作即可对绝对地址赋值。

在操作系统中,需要通过内核支持(如 /dev/memmmap)访问物理地址。

对硬件地址操作时,请确保地址的合法性和访问权限,并根据需要使用 volatile 关键字防止优化。


http://www.kler.cn/a/517500.html

相关文章:

  • 科普篇 | “机架、塔式、刀片”三类服务器对比
  • vulnhub靶场【kioptrix-3】靶机
  • 在Linux系统上安装.NET
  • 【Pytest】结构介绍
  • TangoFlux 本地部署实用教程:开启无限音频创意脑洞
  • 【工程篇】01:GPU可用测试代码
  • 【Java】阿里云OSS上传、删除文件
  • git基础使用命令
  • YOLOv10-1.1部分代码阅读笔记-val.py
  • 《罗宾逊-旅途VR》Build2108907官方学习版
  • Oracle 机器宕机之后启动数据库
  • 大数据,Hadoop,HDFS的简单介绍
  • 从根源分析,调试,定位和解决MacOS ld: unsupported tapi file type ‘!tapi-tbd‘ in YAML file
  • Leecode刷题C语言之购买水果需要的最小金币数
  • 【实践】Python实现气象数据分析与可视化
  • Ubuntu 安装 QGIS LTR 3.34
  • SVN客户端使用手册
  • 逐笔成交逐笔委托Level2高频数据下载和分析:20250124
  • 计算机视觉算法实战——图像生成
  • Cloudpods是一个开源的Golang实现的云原生的融合多云/混合云的云平台,也就是一个“云上之云”。
  • 【python】subprocess.Popen执行adb shell指令进入linux系统后连续使用指令,出现cmd窗口阻塞问题
  • 总结与展望,龙蜥社区第 30 次运营委员会会议线上召开
  • 探究 Facebook 隐私安全发展方向,未来走向何方?
  • 深度学习算法:从基础到实践
  • RV1126画面质量三:QP调节
  • 实现GD32F470作为高速USB主机与USB鼠标通信的功能