C草的编译期编程:元模版
最近一直在写time-devourer这个项目,我的多态设计的强迫症又犯了,不可避免和元模版打交道了。这篇文章简单的稍微讲一下我遇到的几个场景。 自动包装COM对象指针,生命周期结束自动调用Release。要求T必须能调用Release方法,且T必须是IUnknown的子类。 头一次写模版元编程给我肘晕了,这就是编译期编程么,害怕. ...
最近一直在写time-devourer这个项目,我的多态设计的强迫症又犯了,不可避免和元模版打交道了。这篇文章简单的稍微讲一下我遇到的几个场景。 自动包装COM对象指针,生命周期结束自动调用Release。要求T必须能调用Release方法,且T必须是IUnknown的子类。 头一次写模版元编程给我肘晕了,这就是编译期编程么,害怕. ...
目前存在一个场景:需要填充网页上的账号密码模拟登陆,但是不能触发或者给chrome的密码管理器识别到真实的账号密码。 以前其实就比较好奇这个密码管理器是如何正确抓取网页上的密码的。 经过了一天的研究,大概可以得出几个结论了,我不保证这个逻辑是正确的,但是如果有其他人需要参考我想还是能提供一些帮助的,当然也可能存在其他我没观测到的情况: ...
这个东西其实很多,但是文章里不想细讲,我就大概的讲一下,这个篇文章还是偏笔记为主。 总之全局描述符这个东西是继实模式之后保护模式推出的一种内存管理结构。 在实模式下访问内存基本就是靠“段地址+偏移地址=线性地址”这种方式来访问。 ...
由于操作系统本身时存放在硬盘中,并非能在bios引导后直接在内存中运行,所以才有了BIOS引导操作系统的这个步骤。 在主板上电之后,BIOS需要去找到引导程序的位置,这个位置固定在(0磁头0柱面1扇区)的位置,这个扇区也被称为主引导扇区(MBR)。一个扇区大小固定为512字节。也就是boot_loader的大小也必须在512字节以内。 ...
之前已经知道了函数这个玩意在计算机中的本质,本身在栈中存放其实就是一个指针的方式,而指针指向的内容就是在内存中存放的机器码。 解释到这里就已经很明显了,函数其实并不是一定要在编译期载入内存后静态,也就是固定的方式运行的。 ...
这次依然是从汇编开始分析C语言里的一些语法实现,这次还是Windows平台上为主~ 直接上最简单的: 1int z = 0; 2char s1 = (char)z; 3 4// ASM 5int* z = 0; 6// 这次就直接显示符号名吧,不看内存地址了 7// dword ptr就是数据类型声明 8mov dword ptr [z],0 9char* s1 = (char*)z; 10// movzx这个指令,下面讲解,总之就是把z移动到eax寄存器. 11movzx eax,byte ptr [z] 12// 直接粗暴的进行一个强转,al是AX的第八位,AX是EAX的低16位 13// mov指令要求操作数大小相等,byte ptr只占8个字节,所以这里用AL寄存器 14mov byte ptr [s1],al movzx这个指令简单来说就是把小字节操作数移动到大字节寄存器,同时让大字节的高位补零。 ...
感觉没什么营养,懒得写了。
繼續上一篇文章,還是那個代碼,這次我們在Linux上編譯試試,看看和windows有什麽不同。 1int add(int a, int b) { 2 return a + b; 3} 4 5int main() 6{ 7 int a = add(1, 2); 8 return 0; 9} 匯編來咯: 1 0x000055555555460e <+0>: push rbp 2 0x000055555555460f <+1>: mov rbp,rsp 3 0x0000555555554612 <+4>: sub rsp,0x10 4 0x0000555555554616 <+8>: mov esi,0x2 5 0x000055555555461b <+13>: mov edi,0x1 6 0x0000555555554620 <+18>: call 0x5555555545fa <add> 7 0x0000555555554625 <+23>: mov DWORD PTR [rbp-0x4],eax 8 0x0000555555554628 <+26>: mov eax,0x0 9 0x000055555555462d <+31>: leave 10 0x000055555555462e <+32>: ret 11 12 ;其實大差不差,前三句是保存上下文和開闢棧幀 13 ;後面把參數放進去,調用add,然後吧eax裏的返回值取出到rbp-4這個地址裏,清零 14 ;leave的看起來像是linux平臺下獨有的指令 15 ;這個指令其實基本等同于 mov rsp, rbp; pop rbp 16 ;實際上就是回復上下文 17 18 19 0x00005555555545fa <+0>: push rbp 20 0x00005555555545fb <+1>: mov rbp,rsp 21 0x00005555555545fe <+4>: mov DWORD PTR [rbp-0x4],edi 22 0x0000555555554601 <+7>: mov DWORD PTR [rbp-0x8],esi 23 0x0000555555554604 <+10>: mov edx,DWORD PTR [rbp-0x4] 24 0x0000555555554607 <+13>: mov eax,DWORD PTR [rbp-0x8] 25 0x000055555555460a <+16>: add eax,edx 26 0x000055555555460c <+18>: pop rbp 27 0x000055555555460d <+19>: ret 28 29 ;這裏也很簡單,前兩句還是保存上下文,不過這次沒有開闢棧幀 30 ;直接把兩個寄存器的值移動到内存地址裏再放在寄存器裏再計算? 31 ;這樣寫有點逆天,不過估計是debug模式完全沒有優化 32 ;最後彈出地址到棧裏返回
上次学汇编都是2年前了好像,学了一些基本的指令用法。 这次像重新捡起来了,同时想要自己写点新的玩意,目前的知识不太够呢 慢慢学吧… 这次开始读汇编和画栈结构吧~ 先从简单的开始: 1int add(int a, int b) { 2 return a + b; 3} 4 5int main() 6{ 7 int a = add(1, 2); 8 return 0; 9} 汇编如下(Windows平台): ...
最近有人问起我关于Go语言中协程的设计初衷问题,正好说一下我对这个玩意的想法,同时这个也算是面试中可能会问起的问题。 从操作系统的层面上来在,线程是由内核创建和管理,运行在内核态的一种数据结构。协程是由用户创建和管理,运行在用户态的一种数据结构。 ...