diff --git a/note.org b/note.org new file mode 100644 index 0000000..86cdb27 --- /dev/null +++ b/note.org @@ -0,0 +1,97 @@ +* 实验随记 +** Lab 1 +*** 练习3 + +入口就是boot/start.S的_start。 + +mrs 读取程序状态字寄存器 mpidr_el1 +掩码计算处理器位 +用 cbz 跳转主核心至主核心代码,剩下代码忙等 secondary_hang + +*** 练习4 + +#+begin_src +Idx Name Size VMA LMA File off Algn + 0 init 0000b5b0 0000000000080000 0000000000080000 00010000 2**12 + CONTENTS, ALLOC, LOAD, CODE + 1 .text 000011dc ffffff000008c000 000000000008c000 0001c000 2**3 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 2 .rodata 000000f8 ffffff0000090000 0000000000090000 00020000 2**3 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 3 .bss 00008000 ffffff0000090100 0000000000090100 000200f8 2**4 + ALLOC + 4 .comment 00000032 0000000000000000 0000000000000000 000200f8 2**0 + CONTENTS, READONLY +#+end_src + +因为内核代码高地址 0xffffff,所以 VMA 不同。 +使用 MMU 处理这个映射,位于 boot/mmu.c L126-130。 + +*** 练习6 + +初始化 fp sp 位于 start_kernel 函数(kernel/head.S) + +内核栈在 main.c 里定义,build/kernel.sym 可以查到地址 + +内核预先分配栈的总大小(sp = 栈位置 + 大小) + +*** 练习7 + +使用 info 指令查看地址:info address stack_test + +断点设置:b stack_test / b *0xffffff000008c020 + +sp 寄存器 +FP 寄存器:约定俗成通用寄存器倒数第三:$x29 + +打印内存,地址是 $x29,连续长度10,8字节一单位:x/10g $x29 + +显示寄存器:p/x $x29 + +调用一次:0xffffff0000092100 -> 0xffffff00000920e0 (-32) + +每次压入 4 个 8 字节 + +*** 练习8 + +函数 disasm:x/30i stack_test + +#+begin_src asm +stp x29, x30, [sp, #-32]! ; 开栈帧,保存调用方 FP、LR +mov x29, sp ; 设置 FP = 新SP = 老SP - 32 +str x19, [sp, #16] ; 保存寄存器 r19 +#+end_src + +官方的调用约定:https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst#611general-purpose-registers + +因为这里函数没有局部变量,所以 FP = SP + +**** 栈状态 + +========被调用方栈======== +[SP] ----> +栈上数据(这里没有) +[FP] ----> +上一栈帧FP +返回地址(LR) +---------- +局部变量(这里没有) +---------- +保存的寄存器(恰好有调用方函数的调用参数,因为调用方传参是寄存器,而这里保存了下来) +空(可能是对齐) +========调用方栈======== +上一栈帧栈上数据 +------------- +FP +LR +保存的寄存器(之前函数的调用参数) +空 + +**** 实验中显然调用参数是通过寄存器传送的,怎么能打印出参数呢? + +其实参数就在下个栈帧保存的之前的寄存器状态中。 + + +** Lab 2 + +