zoukankan      html  css  js  c++  java
  • 堆栈基指针


    http://www2.ic.uff.br/~michael/kr1999/6-multimedia/6_06-scheduling_and_policing.htm
    https://www.alibabacloud.com/blog/detailed-explanation-of-guava-ratelimiters-throttling-mechanism_594820

    https://www.quora.com/What-is-the-difference-between-token-bucket-and-leaky-bucket-algorithms

    What is the difference between token bucket and leaky bucket algorithms?

    Samples: 192K of event 'cpu-clock', 4000 Hz, Event count (approx.): 48187750000

    Percent│ ◆
    │ /root/.debug/.build-id/80/6c9856a2fdbd570dd869f2b216392efaece1b3/elf: 文件格式 elf64-x86-64 ▒
    │ ▒
    │ ▒
    │ Disassembly of section .text: ▒
    │ ▒
    │ 000000000040052d <main>: ▒
    │ main(): ▒
    │ #include <stdio.h> ▒
    │ int main(void) ▒
    │ { ▒
    │ push %rbp ;堆栈基指针 将寄存器rbp的值推入堆栈,现在rsp的值是堆栈新顶部的内存地址 ▒
    │ mov %rsp,%rbp ;堆栈顶指针 将堆栈指针rsp的值复制到基指针rbp -> rbp和rsp现在都指向堆栈的顶部 ▒
    │ sub $0x10,%rsp ▒
    │ unsigned i = 10; ▒
    │ movl $0xa,-0x4(%rbp) ;movb(8位)、movw(16位)、movl(32位)、movq(64位) ▒
    │ unsigned ii = i - 100; ▒
    │ mov -0x4(%rbp),%eax ;累加寄存器 ▒
    │ sub $0x64,%eax ▒
    │ mov %eax,-0x8(%rbp) ▒
    │ int iii = -90; ▒
    │ movl $0xffffffa6,-0xc(%rbp) ▒
    │ printf("%d,%d,%d", i, ii, iii); ▒
    │ mov -0xc(%rbp),%ecx ;计数寄存器 ▒
    │ mov -0x8(%rbp),%edx ;数据寄存器 ▒
    │ mov -0x4(%rbp),%eax ▒
    │ mov %eax,%esi ;变址寄存器 ▒
    │ mov $0x400610,%edi ▒
    │ mov $0x0,%eax ▒
    │ → callq printf@plt ▒
    │ while (1 < 11) ▒
    │ { ▒
    │ printf("%d", ii); ▒
    28.37 │39: mov -0x8(%rbp),%eax ▒
    9.28 │ mov %eax,%esi ▒
    0.18 │ mov $0x400619,%edi ▒
    │ mov $0x0,%eax ▒
    17.86 │ → callq printf@plt ▒
    │ } ▒
    44.31 │ ↑ jmp 39 ▒

    Samples: 62K of event 'cpu-clock', 4000 Hz, Event count (approx.): 15607500000
    f /home/hdp/workbench/perfUcan/a.out [Percent: local period]
    Percent│ {
    10.54 │ push %rbp
    5.12 │ mov %rsp,%rbp
    0.31 │ sub $0x20,%rsp
    │ int i = 6;
    7.13 │ movl $0x6,-0x4(%rbp)
    │ int j = 10;
    23.57 │ movl $0xa,-0x8(%rbp)
    │ unsigned k = 10;
    9.46 │ movl $0xa,-0xc(%rbp)
    │ int ii = -6;
    4.03 │ movl $0xfffffffa,-0x10(%rbp)
    │ int jj = -10;
    3.10 │ movl $0xfffffff6,-0x14(%rbp)
    │ int n = -110;
    5.43 │ movl $0xffffff92,-0x18(%rbp)
    │ printf("hi");
    3.26 │ mov $0x400630,%edi
    0.16 │ mov $0x0,%eax
    0.78 │ → callq printf@plt
    │ return 0;
    13.80 │ mov $0x0,%eax
    │ }
    1.09 │ leaveq
    12.25 │ ← retq




    https://zhuanlan.zhihu.com/p/55896356
    函数的第一行涉及rbp和rsp;这些是专用寄存器。
    rbp是指向当前栈桢底部的基指针,rsp是指向当前栈桢顶部的堆栈指针。
    (译者注:在很多翻译过来的书上,有些地方将Stack翻译为栈桢,有的地方叫堆栈,
    只要知道这里的堆栈是指Stack,Heap没关系就好)

    rbp = memory address of the base of the prev stack frame
    rsp = memory address of the top of the stack

    指针寄存器
    SP(stack pointer)
    BP(base pointer)

    堆栈的内存地址越来越低,即向地址小的地方增长。

    基指针或帧指针。它指向当前运行的函数的栈桢中的一个固定位置,并为访问函数参数和本地变量提供一个稳定的参考点(基)


    {
    MOV 指令将源操作数复制到目的操作数。作为数据传送(data transfer)指令,它几乎用在所有程序中。在它的基本格式中,第一个操作数是目的操作数,第二个操作数是源操作数:
    MOV destination,source

    其中,目的操作数的内容会发生改变,而源操作数不会改变。这种数据从右到左的移动与 C++ 或 Java 中的赋值语句相似:
    dest = source;

    在几乎所有的汇编语言指令中,左边的操作数是目标操作数,而右边的操作数是源操作数。只要按照如下原则,MOV 指令使用操作数是非常灵活的。
    两个操作数必须是同样的大小。
    两个操作数不能同时为内存操作数。
    指令指针寄存器(IP、EIP 或 RIP)不能作为目标操作数。
    }



    https://www.oschina.net/translate/the-art-of-picking-intel-registers?lang=chs&p=1
    EAX - 累加器寄存器
    EBX - 基础寄存器
    ECX - 计数器寄存器
    EDX - 数据寄存器
    ESI - 源指针
    EDI - 目的地指针
    EBP - 基本指针
    ESP - 堆栈指针

    EAX - Accumulator Register
    EBX - Base Register
    ECX - Counter Register
    EDX - Data Register
    ESI - Source Index
    EDI - Destination Index
    EBP - Base Pointer
    ESP - Stack Pointer

    在CPU中,有八个通用寄存器

    ax (add,代表相加,累加的意思)累加寄存器

    bx (base,代表基地址,存放地址的寄存器) 基址寄存器

    cx (count,个数,代表统计的意思)计数寄存器

    dx (data,数据) 数据寄存器

    SI (source) 源寄存器,存放源地址的内容的寄存器

    DI (Dest) 目标寄存器,从源寄存器中memcpy到目标寄存器中

    BP (base Point) 堆栈,理解为栈底指针,每次在栈中移动数据,出栈进栈,都会更新.记录的是当前的栈底

    SP () 堆栈栈顶指针.

    16位汇编第一讲简介
    https://www.cnblogs.com/iBinary/p/7446164.html
    32位汇编第一讲x86和8086的区别,以及OllyDbg调试器的使用
    https://www.cnblogs.com/iBinary/p/7508144.html
    一丶32位(x86也称为80386)与8086(16位)汇编的区别
    1.寄存器的改变
      AX 变为 EAX 可以这样想,16位通用寄存器前边都加个E开头

    例如:

      

    EAX EBX ECX EDX ESI EDI ESP EBP ;八个寄存器
    EIP EFLAGES ;特殊寄存器
    CS ES SS DS GS FS            ;其中GS FS是新增加的寄存器,这些段寄存器,并不是4个字节(32位的)还是以前16位的
    注意在32位下没有分段的概念的,因为寻址能力是 0- FFFFFFFF ,在当时的inter认为当初的4G已经很厉害了,那是后最好的内存才1G,放到现在看

    我们感觉4G不够用了,但也是近几年才开始用的8G

    有分区的概念,比如我们16位汇编中,给代码分段的时候,顺便分了一下区,分区是为了更好的管理代码的编写


    https://sourceware.org/gdb/current/onlinedocs/gdb/Memory.html
    u10进制 x16
    (gdb) x/16ub 0x400650
    0x400650: 104 105 0 0 1 27 3 59
    0x400658: 56 0 0 0 6 0 0 0
    (gdb) x/16xb 0x400650
    0x400650: 0x68 0x69 0x00 0x00 0x01 0x1b 0x03 0x3b
    0x400658: 0x38 0x00 0x00 0x00 0x06 0x00 0x00 0x00


    [hdp@cmd ~]$ cat /proc/version
    Linux version 3.10.0-1062.4.1.el7.x86_64 (mockbuild@kbuilder.bsys.centos.org) (gcc version 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC) ) #1 SMP Fri Oct 18 17:15:30 UTC 2019
    [hdp@cmd ~]$ cat /proc/cpuinfo
    processor : 0
    vendor_id : GenuineIntel
    cpu family : 6
    model : 79
    model name : Intel(R) Xeon(R) CPU E5-2620 v4 @ 2.10GHz
    stepping : 1
    microcode : 0xffffffff
    cpu MHz : 2095.146
    cache size : 20480 KB
    physical id : 0
    siblings : 2
    core id : 0
    cpu cores : 1
    apicid : 0
    initial apicid : 0
    fpu : yes
    fpu_exception : yes
    cpuid level : 20
    wp : yes
    flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology eagerfpu pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single ibrs ibpb stibp fsgsbase bmi1 hle avx2 smep bmi2 erms invpcid rtm rdseed adx smap xsaveopt spec_ctrl intel_stibp arch_capabilities
    bogomips : 4190.29
    clflush size : 64
    cache_alignment : 64
    address sizes : 44 bits physical, 48 bits virtual
    power management:

    processor : 1
    vendor_id : GenuineIntel
    cpu family : 6
    model : 79
    model name : Intel(R) Xeon(R) CPU E5-2620 v4 @ 2.10GHz
    stepping : 1
    microcode : 0xffffffff
    cpu MHz : 2095.146
    cache size : 20480 KB
    physical id : 0
    siblings : 2
    core id : 0
    cpu cores : 1
    apicid : 1
    initial apicid : 1
    fpu : yes
    fpu_exception : yes
    cpuid level : 20
    wp : yes
    flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology eagerfpu pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single ibrs ibpb stibp fsgsbase bmi1 hle avx2 smep bmi2 erms invpcid rtm rdseed adx smap xsaveopt spec_ctrl intel_stibp arch_capabilities
    bogomips : 4190.29
    clflush size : 64
    cache_alignment : 64
    address sizes : 44 bits physical, 48 bits virtual
    power management:

    [hdp@cmd ~]$

    https://linuxtools-rst.readthedocs.io/zh_CN/latest/tool/readelf.html


    拥有的条件
    static PyObject *
    rlock_is_owned(rlockobject *self, PyObject *Py_UNUSED(ignored))
    {
    unsigned long tid = PyThread_get_thread_ident();

    if (self->rlock_count > 0 && self->rlock_owner == tid) {
    Py_RETURN_TRUE;
    }
    Py_RETURN_FALSE;
    }

    创建
    static PyObject *
    rlock_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
    {
    rlockobject *self;

    self = (rlockobject *) type->tp_alloc(type, 0);
    if (self != NULL) {
    self->in_weakreflist = NULL;
    self->rlock_owner = 0;
    self->rlock_count = 0;

    self->rlock_lock = PyThread_allocate_lock();
    if (self->rlock_lock == NULL) {
    Py_DECREF(self);
    PyErr_SetString(ThreadError, "can't allocate lock");
    return NULL;
    }
    }

    return (PyObject *) self;
    }


    static PyObject *
    lock_PyThread_acquire_lock(lockobject *self, PyObject *args, PyObject *kwds)
    {
    _PyTime_t timeout;
    PyLockStatus r;

    if (lock_acquire_parse_args(args, kwds, &timeout) < 0)
    return NULL;

    r = acquire_timed(self->lock_lock, timeout);
    if (r == PY_LOCK_INTR) {
    return NULL;
    }

    if (r == PY_LOCK_ACQUIRED)
    self->locked = 1;
    return PyBool_FromLong(r == PY_LOCK_ACQUIRED);
    }


    如果多线程的场景下,没有在一个线程内的 锁的获取与释放的要求,那么 Rlock的作用 就是否和Lock一样?

    单线程的情况下,lock有的功能点,Rlock也有,反之不成立;
    多线程的情况下, 如果有在同一线程内的锁的释放或获取的需求,则用Rlock;
    否则,用Lock,因为Rlock的运行逻辑多于Lock,会有更多的资源消耗 性能开销。

  • 相关阅读:
    常用性能测试工具和命令汇总
    delphi try except语句 和 try finally语句用法以及区别
    delphi中 ExecSQL 与 open
    Javascript闭包
    遍历一个List的几种方法
    IDEA导入项目jar包红线、依赖问题....
    HashMap、Hashtable、ConcurrentHashMap的原理与区别
    记一次CPU飙升BUG
    创建单链表
    【剑指offer】题目二
  • 原文地址:https://www.cnblogs.com/rsapaper/p/11963074.html
Copyright © 2011-2022 走看看