`
gaofen100
  • 浏览: 1189831 次
文章分类
社区版块
存档分类
最新评论

Linux Debugging 4 - Primer on PC Architecture

 
阅读更多

1. 需要了解的汇编基础知识

通用寄存器:AX(参数传递以及函数调用返回值),BX(base),CX(计数器),DX(Data被除数)

堆栈寄存器:SP(栈顶指针),BP(栈基址指针)

字符串操作寄存器:SI(source index),DI(dest index)

指令计数器:IP(Instruction pointer)

标志寄存器:FLAGS(PUSHF/POPF)

段寄存器:CS(last 2 bits hold the current privilege level),DS,SS,ES,FS,GS

调试寄存器:DR0-3, DR6, DR7(仅在ring0可以操作)

控制寄存器:CR0(PG-bit31,PE-bit0), CR1, CR2, CR3(页表寄存器), CR4(PAE)

在64位系统中,所有的E寄存器扩展为64位的R寄存器,以及另外的R8至R15寄存器。

注意:

1) 如果程序编译时使用了-fomit-frame-pointer,则不使用BP寄存器

2) od -x a.out

3) IP 指向下一条将要执行的指令的地址,可以通过指令jmp, call, ret, sysenter/syscall, int来改变。

4) 下面的这段程序的目的是对齐ESP指针(16字节)

5) 汇编代码要从后往前读,否则很容易lost

6) 对32位程序来说,函数最好不要超过4个参数,否则多余的参数要通过栈来传递,而不是通过通用寄存器。

理论依据:四色原理与寄存器分配(http://en.wikipedia.org/wiki/Graph_coloring#Register_allocation)

7) 如果在调试时,发现esp的内容类似“xxx000”,说明产生了“page fault”.

同时,BP和SP的内容应该相差不大,如果相差很大,说明BP被破坏了,SP的内容是好的。

8) 下面的函数function,首先保存原BP值,然后用当前SP值更新BP值,使其指向新的栈基地址;然后SP-32个字节越过局部变量区。

2. 进程的内存空间分布

refer to http://blog.csdn.net/BetterManLu/archive/2010/05/09/5571663.aspx

3. 技巧

在代码中不使用assert,abort,而是"int #3",这是因为在调试时可以加断点,并且可以continue执行代码。例子如下,

更好的一种写法,

4. 虚拟内存

从虚拟地址到物理内存地址的转换包含3个步骤,

1) CR3指向PDT(Page Directory Table)的基地址, 而虚拟地址的前10位指向了该表的一个表项(Page Descriptor offset)

2) 虚拟地址的中间的10位指向了一个具体的页表(PTE, Page Table offset)

3) 最后的12位是在该页表中的偏移量,每个页表最多4K (Page offset)

注意:

1) 每个进程的地址空间为4G。

2) 在每个页表中,每项的最后12位,可以用做该页的标志位,参考http://wiki.osdev.org/Paging

3) 关于VSDO,a shared object exposed by the kernel at a fixed address in every process’ memory

4) OOM

下面是一个例子,程序占用内存太大,被系统kill掉了。(resident memory里面是数据 )

dmesg的结果显示a.out被kill了,如果这是应用服务程序,杯具了。

可以参考http://www.dbanotes.net/database/linux_outofmemory_oom_killer.html

同样的例子,修改每次分配的内存空间大小,这次失败的原因变成了malloc失败导致的segV,(resident memory里面是页表 )

检查dmesg,有如下的内容

[41521.451367] b.out[22155]: segfault at 0 rip 7f36e0c94390 rsp 7fffe9146ac8 error 6

5) 共享内存,例如libc

6) resident memory vs virtual memory


resident memory typically refers to physical RAM installed in the machine.

virtual memory is Hard Disk space reserved for the O/S to act as RAM. The O/S "swaps" data in and out of the virtual memory to place it in RAM, or to take it out of RAM. linux "swap" devices are exactly this.

shared memory refers to physical or virtual memory that is attached to more than one process - being shared.

7) TLB:Translation Lookaside Buffer

根据功能可以译为快表,直译可以翻译为旁路转换缓冲,也可以把它理解成页表缓冲。里面存放的是一些页表文件(虚拟地址到物理地址的转换表)。当处理器要在主内存寻址时,不是直接在内存的物理地址里查找的,而是通过一组虚拟地址转换到主内存的物理地址,TLB就是负责将虚拟内存地址翻译成实际的物理内存地址,而CPU寻址时会优先在TLB中进行寻址。处理器的性能就和寻址的命中率有很大的关系。
映射机制必须使一个程序能断言某个地址在其自己的进程空间或地址空间内,并且能够高效的将其转换为真实的物理地址以访问内存。一个方法是使用一个含有整个空间内所有页的入口(entry)的表(即页表),每个入口包含这个页的正确物理地址。这很明显是个相当大的数据结构,因而不得不存放于主存之中。
由于CPU首先接到的是由程序传来的虚拟内存地址,所以CPU必须先到物理内存中取页表,然后对应程序传来的虚拟页面号,在表里找到对应的物理页面号,最后才能访问实际的物理内存地址,也就是说整个过程中CPU必须访问两次物理内存(实际上访问的次数更多)。因此,为了减少CPU访问物理内存的次数,引入 TLB。

5. 物理地址扩展(PAE)

可以使机器支持4GB 以上物理内存,寻址方式变为2+9+9+12,每个进程的地址空间仍是4G。这时的CR3指向Page Directory Pointer Table。

对于PDT和PT,每个表项由32位变为8个字节,表项数目由1024变为了512(2^9),但是总的空间仍是4K。

6. 64位机器

汇编最多使用6个寄存器(r8,r9),第7个参数入栈。

寻址方式为9+9+9+9+12, 仅使用了48位。

下面的例子展示了浮点数参数是如何传递的,

使用gdb a.out显示了浮点数不是通过寄存器传递的,

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics