# GameEngineASM - x86-64 MASM + C 混合架构游戏引擎设计 ## 1. 完整目录树 ``` GameEngineASM/ ├── GameEngineASM.sln ├── DESIGN.md │ ├── Engine/ │ ├── ASM/ -- 汇编核心 (4 files) │ │ ├── math.asm -- 向量/矩阵/四元数 SIMD 运算 │ │ ├── memory.asm -- 对齐内存分配器 │ │ ├── string_ops.asm -- 高速内存/字符串操作 │ │ └── profiling.asm -- rdtsc 性能计时 │ │ │ ├── include/ -- 共享头文件 (6 files) │ │ ├── asm_math.inc -- ASM 函数声明 (.inc for MASM) │ │ ├── asm_math.h -- C 端数学函数声明 │ │ ├── asm_memory.h -- C 端内存分配器声明 │ │ ├── asm_string.h -- C 端字符串操作声明 │ │ ├── asm_profiling.h -- C 端性能计时声明 │ │ └── engine_types.h -- 公共类型定义 (vec3, mat4, etc.) │ │ │ ├── C/ -- C 外层模块 │ │ ├── core/ -- 核心系统 (6 files) │ │ │ ├── engine.h │ │ │ ├── engine.c │ │ │ ├── platform.h │ │ │ ├── platform.c │ │ │ ├── logger.h │ │ │ └── logger.c │ │ │ │ │ ├── rendering/ -- DirectX 11 渲染 (8 files) │ │ │ ├── renderer.h │ │ │ ├── renderer.c │ │ │ ├── dx11_device.h │ │ │ ├── dx11_device.c │ │ │ ├── shader.h │ │ │ ├── shader.c │ │ │ ├── mesh.h │ │ │ └── mesh.c │ │ │ │ │ ├── ecs/ -- 实体组件系统 (6 files) │ │ │ ├── ecs.h │ │ │ ├── ecs.c │ │ │ ├── component_registry.h │ │ │ ├── component_registry.c │ │ │ ├── system_manager.h │ │ │ └── system_manager.c │ │ │ │ │ ├── physics/ -- 物理系统 (4 files) │ │ │ ├── physics.h │ │ │ ├── physics.c │ │ │ ├── collision.h │ │ │ └── collision.c │ │ │ │ │ ├── resources/ -- 资源管理 (4 files) │ │ │ ├── resource_manager.h │ │ │ ├── resource_manager.c │ │ │ ├── file_loader.h │ │ │ └── file_loader.c │ │ │ │ │ ├── scene/ -- 场景管理 (4 files) │ │ │ ├── scene.h │ │ │ ├── scene.c │ │ │ ├── scene_node.h │ │ │ └── scene_node.c │ │ │ │ │ ├── audio/ -- XAudio2 音频 (4 files) │ │ │ ├── audio.h │ │ │ ├── audio.c │ │ │ ├── audio_source.h │ │ │ └── audio_source.c │ │ │ │ │ ├── ui/ -- UI 系统 (4 files) │ │ │ ├── ui.h │ │ │ ├── ui.c │ │ │ ├── ui_widget.h │ │ │ └── ui_widget.c │ │ │ │ │ └── scripting/ -- Lua 脚本 (4 files) │ │ ├── scripting.h │ │ ├── scripting.c │ │ ├── lua_bindgen.h │ │ └── lua_bindgen.c │ │ │ └── lib/ -- 预编译库 (3 files) │ ├── lua54.lib │ ├── d3d11.lib │ └── d3dcompiler.lib │ ├── Demo/ -- 演示程序 (3 files) │ ├── main.c │ ├── demo_scene.c │ └── demo_scene.h │ └── Build/ -- 构建配置 (3 files) ├── GameEngineASM.vcxproj ├── GameEngineASM.vcxproj.filters └── GameEngineASM.props ``` **总文件数: 58 files** --- ## 2. 关键 ASM 函数签名 ### 2.1 math.asm — SIMD 数学库 ```asm ; ============================================================ ; math.asm - SSE4.1/AVX2 向量矩阵数学库 ; 与 C 互操作: Windows x64 calling convention ; 输入: RCX, RDX, R8, R9 (整数/指针), XMM0-XMM3 (浮点) ; 返回: 整数在 RAX, 浮点在 XMM0 ; ============================================================ ; --- Vector2 操作 (float x, float y) --- ; float vec2_dot(vec2 a, vec2 b) ; RCX = ptr to vec2 a, RDX = ptr to vec2 b ; Returns: XMM0 = dot product vec2_dot PROC movups xmm0, xmmword ptr [rcx] ; load a.x, a.y movups xmm1, xmmword ptr [rdx] ; load b.x, b.y mulps xmm0, xmm1 ; element-wise multiply ;水 平 求 和: xmm0 = (a.x*b.x, a.y*b.y) ; 需要水平加法 movshdup xmm1, xmm0 ; xmm1 = (a.y*b.y, a.y*b.y) addps xmm0, xmm1 ; xmm0 = (a.x*b.x + a.y*b.y, ...) ret vec2_dot ENDP ; void vec2_normalize(vec2* out, vec2 in) ; RCX = ptr out, XMM0 = in.x, XMM1 = in.y vec2_normalize PROC ; pack xmm0,xmm1 -> xmm2 unpcklps xmm2, xmm0, xmm1 ; xmm2 = (in.x, in.y) movaps xmm3, xmm2 ; save mulps xmm2, xmm2 ; square ; horizontal sum movshdup xmm4, xmm2 addps xmm2, xmm4 ; len_sq sqrtss xmm2, xmm2 ; len shufps xmm2, xmm2, 0 ; broadcast divps xmm3, xmm2 ; normalize movups xmmword ptr [rcx], xmm3 ; store ret vec2_normalize ENDP ; --- Vector3 操作 (float x, y, z, pad) --- ; float vec3_dot(vec3 a, vec3 b) vec3_dot PROC movups xmm0, xmmword ptr [rcx] movups xmm1, xmmword ptr [rdx] mulps xmm0, xmm1 ; horizontal sum 3 components movshdup xmm2, xmm0 addps xmm0, xmm2 movhlps xmm2, xmm0 addss xmm0, xmm2 ret vec3_dot ENDP ; void vec3_cross(vec3* out, vec3 a, vec3 b) ; RCX = out, XMM0 = a, XMM1 = b (packed xyz) vec3_cross PROC ; a = (ax, ay, az), b = (bx, by, bz) ; result = (ay*bz - az*by, az*bx - ax*bz, ax*by - ay*bx) movaps xmm2, xmm0 ; a movaps xmm3, xmm1 ; b shufps xmm4, xmm2, xmm2, 0C9h ; a.yzx shufps xmm5, xmm3, xmm3, 0C9h ; b.yzx mulps xmm4, xmm3 ; a.yzx * b mulps xmm5, xmm2 ; b.yzx * a subps xmm4, xmm5 ; cross ; store xyz movlps qword ptr [rcx], xmm4 shufps xmm4, xmm4, 02h movss dword ptr [rcx+8], xmm4 ret vec3_cross ENDP ; void vec3_normalize(vec3* out, vec3 v) vec3_normalize PROC movups xmm0, xmmword ptr [rcx] ; load v movaps xmm1, xmm0 mulps xmm1, xmm1 ; v*v ; horizontal sum movshdup xmm2, xmm1 addps xmm1, xmm2 movhlps xmm2, xmm1 addss xmm1, xmm2 sqrtss xmm1, xmm1 ; len shufps xmm1, xmm1, 0 ; broadcast divps xmm0, xmm1 movups xmmword ptr [rcx], xmm0 ret vec3_normalize ENDP ; void vec3_lerp(vec3* out, vec3 a, vec3 b, float t) ; RCX=out, XMM0=a(xyz), XMM1=b(xyz), XMM2=t vec3_lerp PROC subps xmm1, xmm0 ; b - a shufps xmm2, xmm2, 0 ; broadcast t mulps xmm1, xmm2 ; t * (b-a) addps xmm0, xmm1 ; a + t*(b-a) movups xmmword ptr [rcx], xmm0 ret vec3_lerp ENDP ; --- Vector4 操作 --- ; float vec4_dot(vec4 a, vec4 b) vec4_dot PROC movups xmm0, xmmword ptr [rcx] movups xmm1, xmmword ptr [rdx] mulps xmm0, xmm1 ; horizontal sum 4 movhlps xmm1, xmm0 addps xmm0, xmm1 movshdup xmm1, xmm0 addss xmm0, xmm1 ret vec4_dot ENDP ; --- Matrix4x4 操作 (16 floats, row-major) --- ; void mat4_identity(mat4* out) mat4_identity PROC vxorps xmm0, xmm0, xmm0 movups xmmword ptr [rcx], xmm0 movups xmmword ptr [rcx+16], xmm0 movups xmmword ptr [rcx+32], xmm0 movups xmmword ptr [rcx+48], xmm0 movss dword ptr [rcx], (1.0) ; [0][0] = 1 movss dword ptr [rcx+20], (1.0) ; [1][1] = 1 movss dword ptr [rcx+40], (1.0) ; [2][2] = 1 movss dword ptr [rcx+60], (1.0) ; [3][3] = 1 ret mat4_identity ENDP ; void mat4_multiply(mat4* out, mat4* a, mat4* b) ; AVX2: 8-wide FMA mat4_multiply PROC ; 保存非易失寄存器 push rbx sub rsp, 20h ; RCX = out, RDX = a, R8 = b mov rbx, rcx mov rsi, rdx mov rdi, r8 ; 对矩阵 a 的每一行, 与矩阵 b 的所有列做点积 ; 逐行处理 a vmovups ymm0, ymmword ptr [rsi] ; a row 0 (y0) vmovups ymm2, ymmword ptr [rsi+32] ; a row 1 vmovups ymm4, ymmword ptr [rsi+64] ; a row 2 vmovups ymm6, ymmword ptr [rsi+96] ; a row 3 ; 对每一列 b 计算 out 行 ; Column 0 of b vbroadcastss ymm1, dword ptr [rdi] vbroadcastss ymm3, dword ptr [rdi+4] vbroadcastss ymm5, dword ptr [rdi+8] vbroadcastss ymm7, dword ptr [rdi+12] vfmadd231ps ymm0, ymm1, ymm0 ; row0 += col0 * row0 ; ... (简化, 完整实现需 4x4=16 次 FMA) vmovups ymmword ptr [rbx], ymm0 ; ... 其余行 add rsp, 20h pop rbx ret mat4_multiply ENDP ; void mat4_transpose(mat4* out, mat4* m) mat4_transpose PROC vmovups ymm0, ymmword ptr [rdx] ; row 0,1 vmovups ymm1, ymmword ptr [rdx+32] ; row 2,3 vunpcklps ymm2, ymm0, ymm1 ; unpack low vunpckhps ymm3, ymm0, ymm1 ; unpack high vunpcklps ymm4, ymm2, ymm3 vunpckhps ymm5, ymm2, ymm3 vmovups ymmword ptr [rcx], ymm4 vmovups ymmword ptr [rcx+32], ymm5 ret mat4_transpose ENDP ; bool mat4_inverse(mat4* out, mat4* m) -- 返回是否可逆 ; 使用 SIMD 优化的 Gauss-Jordan 消元 mat4_inverse PROC ; 完整实现约 200 行, 使用 AVX2 + FMA ; 核心: 增广矩阵 [m|I] 行变换 push rbx push rbp sub rsp, 40h ; ... 完整 SIMD inverse 实现 mov al, 1 ; assume success add rsp, 40h pop rbp pop rbx ret mat4_inverse ENDP ; --- Quaternion 操作 (4 floats: x, y, z, w) --- ; void quat_multiply(quat* out, quat* a, quat* b) quat_multiply PROC movups xmm0, xmmword ptr [rcx] ; a = (ax,ay,az,aw) movups xmm1, xmmword ptr [rdx] ; b = (bx,by,bz,bw) ; Hamilton product ; result = (aw*b + bw*a + cross(a.xyz, b.xyz), aw*bw - dot(a.xyz,b.xyz)) movaps xmm2, xmm0 shufps xmm2, xmm2, 0FFh ; broadcast aw mulps xmm2, xmm1 ; aw * b movaps xmm3, xmm1 shufps xmm3, xmm3, 0FFh ; broadcast bw mulps xmm3, xmm0 ; bw * a ; cross product of xyz ; ... (同 vec3_cross) addps xmm2, xmm3 ; w = aw*bw - dot(ax*bx + ay*by + az*bz) ; store result movups xmmword ptr [rcx], xmm2 ret quat_multiply ENDP ; void quat_rotate_vec3(vec3* out, quat* q, vec3* v) ; 使用旋转公式: v' = q * v * q^-1 ; 优化公式: v' = v + 2w(q.xyz x v) + 2(q.xyz x (q.xyz x v)) quat_rotate_vec3 PROC ; ... AVX2 优化实现 ret quat_rotate_vec3 ENDP ``` ### 2.2 memory.asm — 对齐内存分配器 ```asm ; ============================================================ ; memory.asm - SIMD 对齐内存分配器 ; ============================================================ ; void* mem_aligned_alloc(size_t size, size_t alignment) ; RCX = size, RDX = alignment (must be power of 2, >= 16) ; Returns: RAX = aligned pointer (or NULL on failure) ; 实现: 分配 size + alignment + sizeof(void*), 返回对齐后的指针 ; 在对齐指针前存储原始 malloc 指针 mem_aligned_alloc PROC push rbx push rdi sub rsp, 28h mov rbx, rcx ; size mov rdi, rdx ; alignment ; total = size + alignment + 8 (for storing original ptr) lea rcx, [rbx + rdi + 8] call malloc ; 调用 CRT malloc test rax, rax jz .fail ; 计算对齐指针 mov rcx, rax add rcx, 8 ; skip storing space ; align up lea rdx, [rdi - 1] not rdx add rcx, rdx and rcx, rdx ; aligned ptr ; 存储原始指针 (aligned_ptr - 8) mov [rcx - 8], rax mov rax, rcx jmp .done .fail: xor eax, eax .done: add rsp, 28h pop rdi pop rbx ret mem_aligned_alloc ENDP ; void mem_aligned_free(void* ptr) ; RCX = aligned pointer mem_aligned_free PROC test rcx, rcx jz .done mov rcx, qword ptr [rcx - 8] ; recover original ptr call free .done: ret mem_aligned_free ENDP ; void* mem_aligned_realloc(void* ptr, size_t new_size) mem_aligned_realloc PROC ; ... 类似 alloc 但使用 realloc ret mem_aligned_realloc ENDP ``` ### 2.3 string_ops.asm — 高速字符串/内存操作 ```asm ; ============================================================ ; string_ops.asm - 高速内存/字符串操作 ; 使用 REP MOVSB (ERMS) + SSE 优化 ; ============================================================ ; void fast_memcpy(void* dst, const void* src, size_t count) ; RCX=dst, RDX=src, R8=count ; 对齐后使用 SSE2 movdqa 批量复制 fast_memcpy PROC push rdi push rsi push rbx mov rdi, rcx mov rsi, rdx mov rcx, r8 cmp rcx, 64 jb .small_copy ; 大块复制: 对齐到 16 字节后用 movdqa ; 先复制前几字节直到对齐 mov rax, rdi and rax, 0Fh jz .aligned mov rdx, 16 sub rdx, rax rep movsb sub rcx, rdx .aligned: ; 以 64 字节为单位批量复制 mov rdx, rcx shr rcx, 2 ; count / 4 (64 bytes each) jz .tail .loop_64: movdqa xmm0, xmmword ptr [rsi] movdqa xmm1, xmmword ptr [rsi+16] movdqa xmm2, xmmword ptr [rsi+32] movdqa xmm3, xmmword ptr [rsi+48] movdqa xmmword ptr [rdi], xmm0 movdqa xmmword ptr [rdi+16], xmm1 movdqa xmmword ptr [rdi+32], xmm2 movdqa xmmword ptr [rdi+48], xmm3 add rsi, 64 add rdi, 64 dec rcx jnz .loop_64 and rdx, 3Fh ; remaining bytes mov rcx, rdx .tail: rep movsb pop rbx pop rsi pop rdi ret .small_copy: rep movsb pop rbx pop rsi pop rdi ret fast_memcpy ENDP ; void fast_memset(void* dst, int val, size_t count) ; 使用 SSE2 批量填充 fast_memset PROC push rdi push rcx mov rdi, rcx mov rax, rdx mov rcx, r8 ; 广播 val 到 xmm0 的所有字节 movd xmm0, edx pshufd xmm0, xmm0, 0 cmp rcx, 32 jb .small_set ; 对齐 mov rax, rdi and rax, 0Fh jz .aligned_set mov rdx, 16 sub rdx, rax rep stosb sub rcx, rdx .aligned_set: mov rdx, rcx shr rcx, 1 ; 32 bytes per iteration .loop_set: movdqa xmmword ptr [rdi], xmm0 movdqa xmmword ptr [rdi+16], xmm0 add rdi, 32 dec rcx jnz .loop_set and rdx, 1Fh mov rcx, rdx .small_set: rep stosb pop rcx pop rdi ret fast_memset ENDP ; int fast_strcmp(const char* a, const char* b) ; SSE4.2PCMPESTRI 逐 16 字节比较 fast_strcmp PROC push rbx .loop_strcmp: movdqu xmm0, xmmword ptr [rcx] movdqu xmm1, xmmword ptr [rdx] ; SSE4.2 字符串比较: 找到第一个不匹配位置 pcmpestrm xmm0, xmm1, 18h ; EqualAny, unsigned bytes ; ... (具体利用 SSE4.2 字符串指令) ; 简化版本: 逐字节 fallback mov al, byte ptr [rcx] cmp al, byte ptr [rdx] jne .not_equal test al, al jz .equal inc rcx inc rdx jmp .loop_strcmp .not_equal: movzx eax, al movzx edx, byte ptr [rdx] sub eax, edx pop rbx ret .equal: xor eax, eax pop rbx ret fast_strcmp ENDP ; size_t fast_strlen(const char* str) fast_strlen PROC mov rax, rcx pxor xmm0, xmm0 .loop_strlen: movdqu xmm1, xmmword ptr [rax] pcmpestrm xmm1, xmm0, 08h ; Least Significant Byte, imm8=08h jc .found add rax, 16 jmp .loop_strlen .found: ; 在返回的掩码中找第一个 1 pmovmskb edx, xmm1 tzcnt edx, edx add rax, rdx sub rax, rcx ; length = end - start ret fast_strlen ENDP ``` ### 2.4 profiling.asm — rdtsc 性能计时 ```asm ; ============================================================ ; profiling.asm - rdtsc 高精度计时 ; ============================================================ ; uint64_t prof_rdtsc(void) ; 返回 TSC 值 prof_rdtsc PROC lfence rdtsc shl rdx, 32 or rax, rdx ret prof_rdtsc ENDP ; uint64_t prof_rdtscp(void) ; 无序读取, 更快但可能不精确 prof_rdtscp PROC rdtscp shl rdx, 32 or rax, rdx ret prof_rdtscp ENDP ; double prof_cycles_to_ms(uint64_t cycles) ; 将 TSC cycles 转换为毫秒 (需要 CPU 频率) ; RCX = cycles ; Returns: XMM0 = milliseconds prof_cycles_to_ms PROC vcvttsd2si rax, xmm0 ; ... 保存输入 ; 假设 CPU 频率存储在全局变量 cpu_freq_ghz vmovsd xmm0, qword ptr [cpu_freq_mhz] vcvtsi2sd xmm1, xmm1, rcx vdivsd xmm0, xmm1, xmm0 ; cycles / mhz = ms vdivsd xmm0, xmm0, (1000.0) ; / 1000 for seconds, but we want ms ; 实际: ms = cycles / (cpu_mhz * 1000) ret prof_cycles_to_ms ENDP ; void prof_calibrate_frequency(void) ; 通过 QueryPerformanceCounter 校准 TSC 频率 prof_calibrate_frequency PROC sub rsp, 28h ; QueryPerformanceFrequency lea rcx, qword ptr [freq_large] call QueryPerformanceFrequency ; 用 rdtsc 采样 call prof_rdtsc mov rbx, rax ; Sleep(100ms) mov ecx, 100 call Sleep call prof_rdtsc sub rax, rbx ; elapsed cycles ; cpu_mhz = elapsed_cycles / (freq * 0.1s) ; ... add rsp, 28h ret prof_calibrate_frequency ENDP .data cpu_freq_mhz dq 0 freq_large dq 0 ``` --- ## 3. C 端头文件 (暴露 ASM 函数) ### 3.1 engine_types.h — 公共类型 ```c #ifndef ENGINE_TYPES_H #define ENGINE_TYPES_H #include #include typedef union Vec2 { struct { float x, y; }; float m[2]; } Vec2; typedef union Vec3 { struct { float x, y, z, _pad; }; float m[4]; // 16-byte aligned } Vec3; typedef union Vec4 { struct { float x, y, z, w; }; float m[4]; } Vec4; typedef union Mat4 { float m[16]; float mm[4][4]; } Mat4; typedef union Quat { struct { float x, y, z, w; }; float m[4]; } Quat; #endif ``` ### 3.2 asm_math.h ```c #ifndef ASM_MATH_H #define ASM_MATH_H #include "engine_types.h" #ifdef __cplusplus extern "C" { #endif // Vector2 float vec2_dot(Vec2 a, Vec2 b); Vec2 vec2_add(Vec2 a, Vec2 b); Vec2 vec2_sub(Vec2 a, Vec2 b); Vec2 vec2_scale(Vec2 v, float s); Vec2 vec2_normalize(Vec2 v); float vec2_length(Vec2 v); // Vector3 float vec3_dot(Vec3 a, Vec3 b); Vec3 vec3_cross(Vec3 a, Vec3 b); Vec3 vec3_add(Vec3 a, Vec3 b); Vec3 vec3_sub(Vec3 a, Vec3 b); Vec3 vec3_scale(Vec3 v, float s); Vec3 vec3_normalize(Vec3 v); float vec3_length(Vec3 v); Vec3 vec3_lerp(Vec3 a, Vec3 b, float t); // Vector4 float vec4_dot(Vec4 a, Vec4 b); Vec4 vec4_add(Vec4 a, Vec4 b); Vec4 vec4_sub(Vec4 a, Vec4 b); Vec4 vec4_scale(Vec4 v, float s); // Matrix4x4 void mat4_identity(Mat4* out); void mat4_multiply(Mat4* out, Mat4* a, Mat4* b); void mat4_transpose(Mat4* out, Mat4* m); bool mat4_inverse(Mat4* out, Mat4* m); void mat4_translate(Mat4* out, Vec3 v); void mat4_scale(Mat4* out, Vec3 s); void mat4_rotate_x(Mat4* out, float radians); void mat4_rotate_y(Mat4* out, float radians); void mat4_rotate_z(Mat4* out, float radians); Mat4 mat4_perspective(float fov, float aspect, float near, float far); Mat4 mat4_ortho(float left, float right, float bottom, float top, float near, float far); Mat4 mat4_look_at(Vec3 eye, Vec3 center, Vec3 up); // Quaternion Quat quat_identity(void); Quat quat_multiply(Quat a, Quat b); Quat quat_normalize(Quat q); Quat quat_conjugate(Quat q); Quat quat_from_axis_angle(Vec3 axis, float angle); Vec3 quat_rotate_vec3(Quat q, Vec3 v); Mat4 quat_to_mat4(Quat q); // SSE intrinsics for direct C use (optional, for tight loops) #ifdef __SSE4_1__ #include static inline float fast_vec3_dot_sse(Vec3 a, Vec3 b) { __m128 va = _mm_load_ps(a.m); __m128 vb = _mm_load_ps(b.m); __m128 mul = _mm_mul_ps(va, vb); __m128 shuf = _mm_movehdup_ps(mul); __m128 sums = _mm_add_ps(mul, shuf); shuf = _mm_movehl_ps(shuf, sums); sums = _mm_add_ss(sums, shuf); return _mm_cvtss_f32(sums); } #endif #ifdef __cplusplus } #endif #endif ``` ### 3.3 asm_memory.h ```c #ifndef ASM_MEMORY_H #define ASM_MEMORY_H #include #include #ifdef __cplusplus extern "C" { #endif void* mem_aligned_alloc(size_t size, size_t alignment); void mem_aligned_free(void* ptr); void* mem_aligned_realloc(void* ptr, size_t new_size); size_t mem_get_alignment(void* ptr); // SIMD 块分配: 一次分配多个对齐对象 void* mem_aligned_alloc_batch(size_t count, size_t elem_size, size_t alignment); #ifdef __cplusplus } #endif #endif ``` ### 3.4 asm_string.h ```c #ifndef ASM_STRING_H #define ASM_STRING_H #include #ifdef __cplusplus extern "C" { #endif void fast_memcpy(void* dst, const void* src, size_t count); void fast_memset(void* dst, int val, size_t count); int fast_strcmp(const char* a, const char* b); int fast_strncmp(const char* a, const char* b, size_t n); size_t fast_strlen(const char* str); char* fast_strchr(const char* str, int c); char* fast_strcpy(char* dst, const char* src); #ifdef __cplusplus } #endif #endif ``` ### 3.5 asm_profiling.h ```c #ifndef ASM_PROFILING_H #define ASM_PROFILING_H #include #ifdef __cplusplus extern "C" { #endif uint64_t prof_rdtsc(void); uint64_t prof_rdtscp(void); double prof_cycles_to_ms(uint64_t cycles); uint64_t prof_calibrate_frequency(void); double prof_get_cpu_ghz(void); // 便捷宏 #define PROF_BEGIN() uint64_t _prof_start = prof_rdtsc() #define PROF_END() prof_cycles_to_ms(prof_rdtsc() - _prof_start) #ifdef __cplusplus } #endif #endif ``` --- ## 4. 构建配置 (Visual Studio MASM 集成) ### 4.1 GameEngineASM.props — MASM 属性表 ```xml /Zi /nologo /Fl /Sa $(ProjectDir)Engine\include %(PreprocessorDefinitions) ProgramDatabase FullSpeedOptimizations $(ProjectDir)Engine\include;%(AdditionalIncludeDirectories) WIN32;_WINDOWS;_DEBUG;%(PreprocessorDefinitions) MultiThreadedDebugDLL Full /arch:AVX2 /fp:fast Level4 d3d11.lib;d3dcompiler.lib;dxgi.lib;d3d11.lib;xaudio2.lib;lua54.lib;%(AdditionalDependencies) Windows true $(ProjectDir)Engine\lib;%(AdditionalLibraryDirectories) ``` ### 4.2 GameEngineASM.vcxproj — 关键片段 ```xml false ``` ### 4.3 ml64.exe 编译命令行 ``` ml64.exe /c /nologo /W3 /Zi /Fo"$(OutDir)%(FileName).obj" /Fl"$(OutDir)%(FileName).lst" %(AdditionalInputs) %(AdditionalOptions) ``` --- ## 5. 实施顺序 (按依赖关系) ### Phase 1: 基础设施 (Week 1) | 序号 | 任务 | 优先级 | 预计时间 | |------|------|--------|----------| | 1.1 | 创建项目结构和 VS 解决方案 | P0 | 2h | | 1.2 | 配置 MASM 构建规则 (.props, .vcxproj) | P0 | 2h | | 1.3 | 实现 `engine_types.h` 公共类型 | P0 | 1h | | 1.4 | 实现 `string_ops.asm` (memcpy/memset/strlen) | P0 | 4h | | 1.5 | 实现 `memory.asm` 对齐分配器 | P0 | 3h | | 1.6 | 实现 `profiling.asm` 计时器 | P0 | 2h | ### Phase 2: 数学库 (Week 1-2) | 序号 | 任务 | 优先级 | 预计时间 | |------|------|--------|----------| | 2.1 | `math.asm` — Vec2 基础操作 | P0 | 3h | | 2.2 | `math.asm` — Vec3 基础操作 | P0 | 3h | | 2.3 | `math.asm` — Vec4 基础操作 | P0 | 2h | | 2.4 | `math.asm` — Mat4 基础操作 (identity, multiply) | P0 | 6h | | 2.5 | `math.asm` — Mat4 高级操作 (inverse, look_at, perspective) | P1 | 8h | | 2.6 | `math.asm` — Quat 操作 | P1 | 4h | | 2.7 | C 端头文件 `asm_math.h` | P0 | 2h | ### Phase 3: 核心框架 (Week 2-3) | 序号 | 任务 | 优先级 | 预计时间 | |------|------|--------|----------| | 3.1 | `platform.c` — Win32 窗口管理 | P0 | 6h | | 3.2 | `engine.c` — 主循环和初始化 | P0 | 4h | | 3.3 | `dx11_device.c` — DirectX 11 设备初始化 | P0 | 6h | | 3.4 | `renderer.c` — 基础渲染管线 | P0 | 8h | | 3.5 | `shader.c` — 着色器管理 | P1 | 4h | | 3.6 | `mesh.c` — 网格和顶点缓冲 | P1 | 4h | ### Phase 4: 游戏系统 (Week 3-4) | 序号 | 任务 | 优先级 | 预计时间 | |------|------|--------|----------| | 4.1 | `ecs.c` — 实体组件系统核心 | P0 | 8h | | 4.2 | `physics.c` — 物理系统 (调用 ASM math) | P1 | 6h | | 4.3 | `collision.c` — 碰撞检测 | P1 | 6h | | 4.4 | `scene.c` — 场景图管理 | P1 | 4h | | 4.5 | `resource_manager.c` — 资源加载 | P2 | 4h | | 4.6 | `audio.c` — XAudio2 音频 | P2 | 6h | | 4.7 | `ui.c` — UI 系统 | P2 | 6h | | 4.8 | `scripting.c` — Lua 绑定 | P2 | 4h | ### Phase 5: 演示和优化 (Week 4-5) | 序号 | 任务 | 优先级 | 预计时间 | |------|------|--------|----------| | 5.1 | `Demo/main.c` — 主入口 | P0 | 2h | | 5.2 | `Demo/demo_scene.c` — 演示场景 | P1 | 6h | | 5.3 | SIMD 性能基准测试 | P1 | 4h | | 5.4 | 集成测试和调试 | P0 | 8h | **总预计工时: ~150 小时 (约 4-5 周)** --- ## 6. 文件统计 | 类别 | 文件数 | 说明 | |------|--------|------| | ASM (.asm) | 4 | 核心热路径 | | ASM include (.inc) | 1 | ASM 函数声明 | | C 头文件 (.h) | 19 | 包含公共类型和模块头文件 | | C 源文件 (.c) | 30 | 所有模块实现 | | VS 项目文件 | 3 | .sln, .vcxproj, .props | | 文档 | 1 | 本设计文档 | | 预编译库 (.lib) | 3 | lua54, d3d11, d3dcompiler | | **总计** | **61** | — | ### 按模块分布 ``` ASM 核心: 4 文件 (math, memory, string_ops, profiling) C 核心: 6 文件 (engine, platform, logger) C 渲染: 8 文件 (renderer, dx11_device, shader, mesh) C ECS: 6 文件 (ecs, component_registry, system_manager) C 物理: 4 文件 (physics, collision) C 资源: 4 文件 (resource_manager, file_loader) C 场景: 4 文件 (scene, scene_node) C 音频: 4 文件 (audio, audio_source) C UI: 4 文件 (ui, ui_widget) C 脚本: 4 文件 (scripting, lua_bindgen) 头文件: 19 文件 (含 asm_*.h 和模块 .h) 构建/文档: 7 文件 (VS 项目, 设计文档, 库文件) ``` --- ## 7. 性能预期 | 操作 | 纯 C | ASM (SSE4.1) | ASM (AVX2) | 加速比 | |------|------|-------------|------------|--------| | Vec4 Dot | ~12 ns | ~3 ns | ~2 ns | 4-6x | | Mat4 Multiply | ~80 ns | ~25 ns | ~12 ns | 4-7x | | Mat4 Inverse | ~500 ns | ~150 ns | ~80 ns | 3-6x | | Quat Multiply | ~25 ns | ~8 ns | ~5 ns | 3-5x | | memcpy 1KB | ~200 ns | ~40 ns | ~30 ns | 5-7x | | memset 1KB | ~180 ns | ~35 ns | ~25 ns | 5-7x | **注意**: 实际性能取决于 CPU 微架构、缓存状态和数据对齐情况。 --- ## 8. 关键设计决策 1. **调用约定**: 严格遵循 Windows x64 ABI, 确保 ASM/C 无缝互操作 2. **内存对齐**: 所有 SIMD 数据使用 16/32 字节对齐, 通过自定义分配器保证 3. **寄存器保存**: ASM 函数正确保存非易失寄存器 (RBX, RBP, RDI, RSI, R12-R15, XMM6-15) 4. **错误处理**: ASM 函数通过返回值 (0/-1 或 NULL) 表示失败, C 端检查 5. **调试支持**: 使用 /Zi 编译, 生成符号信息, 支持 VS 调试器单步进入 ASM 6. **可移植性**: ASM 文件仅用于 x86-64 Windows, C 代码可条件编译到其他平台