时间过得有点久了,最近重新看了一下mmu部分。我发现这个问题的答案是什么了。
一开始我还是弄不懂为什么,但是后来我看了一下反编译代码,发现有这么几句:
unsigned long virtuladdr, physicaladdr;
unsigned long *mmu_tlb_base = (unsigned long *)0x30000000;
virtuladdr = 0xA0000000;
physicaladdr = 0x56000000;
*(mmu_tlb_base + (virtuladdr >> 20)) = (physicaladdr & 0xFFF00000) | MMU_SECDESC;
以上是编译前的c语言源代码
以下是编译后经过反编译的汇编代码
e0: e3a02c0a mov r2, #2560 ; 0xa00
e4: e3a0120b mov r1, #-1342177280 ; 0xb0000000
e8: e78c3102 str r3, [ip, r2, lsl #2]
第一句代码是0xa000 0000左移20位后得出的数,作为偏移码,而第三句则是将r3中的描述符放入0x3000 0000+(0xa00<<2)中,这里就是问题之处,明明代码中写的是右移20位,可是在真正存入指针所指的地址的时候,却又左移了两位,刚好就是18位。
一开始我还不明白为什么会右移20位之后又重新左移两位,后来看了一下c代码,指针的类型都是unsigned long型的,自增1的时候,地址会自增4,例如有如下定义:
unsigned long *p1=0x3000 0000;
p1++;//此时p1=0x3000 0004
或者
p1=p1+4;//此时p1=0x3000 0000+4*4 即 p1=0x3000 0000+(4<<2)
所以c代码中的:
*(mmu_tlb_base + (virtuladdr >> 20)) = (physicaladdr & 0xFFF00000) | MMU_SECDESC;
之所以virtuladdr>>20,就是因为mmu_tlb_base是unsigned long型的指针,所以左移20位后会再次乘4,即左移两位
时间过得有点久了,最近重新看了一下mmu部分。我发现这个问题的答案是什么了。
一开始我还是弄不懂为什么,但是后来我看了一下反编译代码,发现有这么几句:
unsigned long virtuladdr, physicaladdr;
unsigned long *mmu_tlb_base = (unsigned long *)0x30000000;
virtuladdr = 0xA0000000;
physicaladdr = 0x56000000;
*(mmu_tlb_base + (virtuladdr >> 20)) = (physicaladdr & 0xFFF00000) | MMU_SECDESC;
以上是编译前的c语言源代码
以下是编译后经过反编译的汇编代码
e0: e3a02c0a mov r2, #2560 ; 0xa00
e4: e3a0120b mov r1, #-1342177280 ; 0xb0000000
e8: e78c3102 str r3, [ip, r2, lsl #2]
第一句代码是0xa000 0000左移20位后得出的数,作为偏移码,而第三句则是将r3中的描述符放入0x3000 0000+(0xa00<<2)中,这里就是问题之处,明明代码中写的是右移20位,可是在真正存入指针所指的地址的时候,却又左移了两位,刚好就是18位。
一开始我还不明白为什么会右移20位之后又重新左移两位,后来看了一下c代码,指针的类型都是unsigned long型的,自增1的时候,地址会自增4,例如有如下定义:
unsigned long *p1=0x3000 0000;
p1++;//此时p1=0x3000 0004
或者
p1=p1+4;//此时p1=0x3000 0000+4*4 即 p1=0x3000 0000+(4<<2)
所以c代码中的:
*(mmu_tlb_base + (virtuladdr >> 20)) = (physicaladdr & 0xFFF00000) | MMU_SECDESC;
之所以virtuladdr>>20,就是因为mmu_tlb_base是unsigned long型的指针,所以左移20位后会再次乘4,即左移两位
举报