C和汇编的一些基础知识

来源:互联网 发布:黄播软件 编辑:程序博客网 时间:2024/06/04 23:28

问:

void copy_2th_to_sdram(void) 

    unsigned int *pdwSrc  =
(unsigned int *)2048;  
    unsigned int *pdwDest =
(unsigned int *)0x30004000;  
     
    while (pdwSrc < (unsigned int *)4096) 
    { 
        *pdwDest = *pdwSrc; 
        pdwDest++; 
        pdwSrc++; 
    } 
}
想问下为什么0x30004000前面还要加(unsigned int *),0x30004000已经代表地址了啊;
还有汇编程序里像
.text 
.global _start

.align 4
这样子的为什么加个点,.align 4 又是什么意思呢?

 

 

答:  

.text 部分是处理器开始执行代码的地方.
.global关键字用来让一个符号对链接器可见,可以供其他链接对象模块使用。.global _start 让 _start 符号成为可见的标识符,这样链接器就知道跳转到程序中的什么地方并开始执行。
0x30004000只是个立即数。前面加(unsigned int *),表示把它强转成指针,另外表示它指向的是unsigned int类型的数据。
 
楼上说得对0x30004000只能是数,强制转换的目的是把它转换成相应形式的指针,如果不这么作有些编译器会出警告,而有些编译器会认为是个错误。

align 4
应该是四字节对齐的意思,也就是说这段数据的起始地址是4的整数倍,如0x00000018,0x00000020,如果不做这样的修饰,编译器可能会为了节省内存而使用连续空间的形式接着前边数据的地址,导致下边的数据地址是0x00000011

 

 

问:

再问个问题,在ARM环境下,
unsigned long virtuladdr;
unsigned long *mmu_tlb_base = (unsigned long *)0x30000000;
virtuladdr = 0xA0000000;
(virtuladdr >> 20))  = 0xA00

(mmu_tlb_base + (virtuladdr >> 20))  = 0x30000000 +0xA00 *4 :之所以乘4,是由于mmu_tlb_base 是unsigned int指针
0x30000000 +0xA00 *4  = 0x30002800
(mmu_tlb_base  + 1)的实际结果是mmu_tlb_base 的地址值加上4

我想问下为什么要乘以4,在同样的环境下,改为unsigned int 类型指针时,是不是要乘以2,
unsigned char类型指针时,是不是要乘以1???

答:

unsigned long *mmu_tlb_base = (unsigned long *)0x30000000;
如果执行mmu_tlb_base=mmu_tlb_base+1,会得到mmu_tlb_base为0x30000004的结果,对于指针的加减操作会将+1自动转换为+指针类型字节数
(unsigned short *)mmu_tlb_base+1的结果是0x30000002
(unsigned long)mmu_tlb_base+1的结果是0x30000001

long指针是4字节对齐,所以+1实际上地址等于+4
short指针是2字节对齐,所以+1实际上地址等于+2
long指针是1字节对齐,所以+1实际上地址等于+1

int不同编译器针对不同硬件平台会得出不同结果,有可能是32位(4字节),也有可能是16位(2字节)


----------------------------------

将一个立即数的值传给指针前必须加(long *)这样的强制转换是C语言为了防止误操作采取的一种保护措施,不同指针有不同的对齐要求,虽然立即数可以表示出地址的具体数值,但存在一个问题:有可能给一个不满足对齐要求的值给long这样有对齐要求的指针,这样会出错,如果语法上要求必须强制转换,可以提醒程序员在该位置留意转换的对齐问题