独钓寒江雪

用C++的优雅,驯服Windows的狂野

x86架构作为个人计算机和服务器领域的主流计算架构,其汇编语言是理解计算机底层运行机制、进行逆向工程、性能优化及嵌入式开发的核心基础。本文将系统梳理x86架构中的常用寄存器​和常用汇编指令​,并结合实际应用场景说明其作用。

x86常用寄存器

寄存器是CPU内部的高速存储单元,用于临时存放数据、地址或控制信息。x86寄存器按功能可分为通用寄存器、段寄存器、标志寄存器、指令指针、控制寄存器、调试寄存器及浮点/SIMD寄存器等类别。

通用寄存器

(General-Purpose Registers, GPRs)
通用寄存器是最常用的寄存器,支持数据存储、算术运算、内存寻址及栈操作等功能。根据架构位宽(16/32/64位)扩展,以下为核心寄存器:

阅读全文 »

Visual Studio 的断点系统远不止”在代码行上点击左侧边栏”那么简单。掌握其高级功能可以彻底改变你的调试体验,让你能精准定位问题,而不是在无尽的代码执行中盲目搜索。本文将带你全面了解 Visual Studio 断点系统的各项高级功能。

条件断点

条件断点允许你设置特定条件,只有满足这些条件时调试器才会暂停。

支持如下格式的表达式:

1
2
3
4
5
6
7
8
9
10
// 基本条件
i > 100
name == "admin"

// 复合条件
x > 50 && y < 20 && isValid == true

// 字符串操作(C++)
strcmp(filename, "config.xml") == 0
strlen(buffer) > 255

支持的内置函数如下:

  • strlen(str):获取字符串长度
  • strcmp(str1, str2):比较两个字符串
  • strncmp(str1, str2, n):比较前n个字符
  • strstr(haystack, needle):查找子字符串
  • GetLastError():获取系统错误代码
阅读全文 »

nullptr (C++11)

nullptr 专门用于表示空指针,旨在解决传统 NULL 或 0 在类型安全性和代码清晰度上的缺陷。

nullptr 的类型为 std::nullptr_t,只能隐式转换为指针类型(包括原生指针、智能指针、托管句柄等),​不能转换为整数类型,避免了与整型 0 的混淆。

而传统 NULL 是宏(通常定义为 0 或 (void*)0),可能被误解释为整数,导致类型错误。

在函数重载场景中,nullptr 可明确选择指针版本的重载函数,避免因 NULL 被解释为整数导致的错误调用:

1
2
3
4
void foo(int);        // 整型版本
void foo(int*); // 指针版本

foo(nullptr); // 正确调用指针版本

而且在模板中可精确匹配指针类型,避免推导为整数:

1
2
3
4
5
6
7
8
9
10
#include <iostream>

template<typename T>
void check(T ptr) {
std::cout << "ptr type: " << typeid(ptr).name() << std::endl;
}

int main() {
check(nullptr); // ptr type: std::nullptr_t
}
阅读全文 »

自从接触了 JerryScript(见开源库jerryscript使用备忘),本以为再也不会用到 Lua 了,关于 Lua 的记忆已经逐渐在我的脑海中删除,但最近维护的几个老项目又都使用了 Lua,真是命运的捉弄啊。

来吧,刷新记忆!

基础

  • Lua区分大小写
  • 注释格式
    1
    2
    3
    4
    5
    -- 行注释

    --[[
    块注释
    --]]
  • 局部变量使用local声明, 其他的全部为全局变量,变量的默认值为nil
  • 只有false和nil为假,其他的全部为真
  • Lua中字符串都是不可变的常量
  • 使用..可以连接字符串
  • Lua没有整形,都是实数
  • 可以在字符串前放置操作符#来获取字符串长度,某些情况下对table也适用
  • 关系操作符: < > == >= <=,不等于使用~=,而不是!=
  • and, or, not 逻辑操作符返回的不一定是true和false,这点与C++不同,它返回的是对应表达式的运行结果
  • 支持多重赋值
1
2
-- a为0, b为1, c为nil
a,b,c = 0,1
  • 控制结构
1
2
3
4
5
6
7
if exp then
-- something
elseif exp then
-- something
else
-- something
end
1
2
3
while <exp is true> do
-- something
end
1
2
3
repeat
-- something
until <exp is true>
1
2
3
for var=exp1, exp2, exp3 do
-- something
end
1
2
3
for i,v in ipairs(a) do
-- something
end
1
2
3
for i in pairs(a) do
-- something
end
阅读全文 »

Wireshark 中有两种过滤器:

  • 捕获过滤器:用于在数据包捕获阶段过滤数据包,只捕获符合条件的数据包,这样可以减少捕获不必要的数据包,从而提高性能。
  • 显示过滤器:用于在已经捕获的数据包中过滤出符合条件的数据包进行显示,它使用的是 Wireshark 自己的语法。

捕获过滤器

在 Wireshark 的开始页面或者在捕获选型页面中选择需要捕获的网络适配器,然后输入捕获过滤器规则,设置完成之后,点击“开始”按钮即可使用该规则在对应适配器上进行网络流量抓取。

阅读全文 »

CMake 是一个开源、跨平台的构建系统生成器(Build-system Generator)。

本文是 Modern CMake 简明教程系列的下篇,上篇请移步至 《Modern CMake 简明教程(上)》,中篇请移步至 《Modern CMake 简明教程(中)》

本教程默认 CMake 最低版本为 3.16,即 cmake_minimum_required(VERSION 3.16)

集成第三方库

在项目中集成第三方库是一种非常常见的需求,CMake 提供了两种方式来集成第三方库。

第一种:直接集成第三方库的源码。

说到集成第三方库的源码,我们第一时间想到的可能就是将其源码直接拷贝到项目目录中,然后提交到 git 仓库,更加高级一点可能会使用 git submodule 的方式。但我以为这两种方式都不够优雅,无法很好的管理、更新依赖库,特别是在项目的依赖库的比较多时。

CMake 提供了两个模块(两种方式)来集成第三方库的源码:

  • FetchContent
    该模块支持在 CMake 生成项目时就下载第三方库,还会自动将第三方库添加到项目中,不需要手动调用 add_subdirectory。
  • ExternalProject
    该模板支持在构建(编译)项目时下载第三方库。显然 ExternalProject 的下载时机要晚于 FetchContent 。

第二种:使用预编译好的第三方库。

这种方式需要先单独编译安装第三方库,然后使用 find_package 查找该库,最后设置目标的相关属性,如包含目录、依赖库等。

阅读全文 »
0%