如何在FASM汇编中加载Raylib字体?调用LoadFontEx时程序崩溃
问题解决:FASM调用Raylib LoadFontEx段错误
核心错误点分析
Codepoints数组偏移计算错误
你填充codepoints时直接使用字节偏移,但codepoints是dd(4字节)类型的数组,每个元素占4字节,直接用rcx - 0x20作为字节偏移会导致数据写入错误的内存位置,LoadFontEx读取到乱码的codepoints后会触发非法内存访问。Codepoints数组容量与计数不匹配
- ASCII部分(0x20到0x7F)共95个字符,西里尔文部分(0x400到0x6C0)共705个字符,总计800个,但你定义的
codepoints仅预留512个dd元素,容量不足会导致越界写入。 - 调用LoadFontEx时传入的计数是211,和实际需要的800完全不符,会让函数读取超出数组范围的内存。
- ASCII部分(0x20到0x7F)共95个字符,西里尔文部分(0x400到0x6C0)共705个字符,总计800个,但你定义的
Font变量定义冗余(非直接错误但不规范)
64位系统下Raylib的LoadFontEx返回的是Font结构体指针(8字节),你预留64字节完全没必要,定义为8字节的qword足够。
修复后的代码
format ELF64 section ".data" writeable screenWidth: dd 800 screenHeight: dd 600 windowTitle: db "raylib [text] example - font loading", 0 ; 预留足够容量存储ASCII+西里尔文共800个codepoints codepoints: times 800 dd 0 fontFile: db "km.ttf", 0 text1: db "Окей, Okay!", 0 text2: db "С Новым Годом!", 0 ; 若启用DrawTextEx,需定义坐标向量 ; textPos: dd 100.0, 150.0 section ".bss" ; 存储Font结构体指针,64位系统下占8字节 font: rq 1 section '.text' executable public _start extrn printf extrn _exit extrn InitWindow extrn WindowShouldClose extrn CloseWindow extrn BeginDrawing extrn EndDrawing extrn ClearBackground extrn DrawText extrn DrawTextEx extrn LoadFontEx extrn UnloadFont _start: mov rdi, 400 mov rsi, 300 mov rdx, windowTitle call InitWindow init_ascii: mov rcx, 0x20 ; 起始ASCII码 init_ascii_loop: ; 计算当前字符在数组中的索引,乘以4得到字节偏移 lea rbx, [rcx - 0x20] mov [codepoints + rbx*4], ecx ; 存入32位codepoint值 inc rcx cmp rcx, 0x7F ; 到0x7F结束(包含0x7E) jne init_ascii_loop init_cyrillic: mov rcx, 0x400 ; 起始西里尔文码 init_cyrillic_loop: ; 西里尔文从数组第95个元素开始(ASCII占了95个) lea rbx, [rcx - 0x400] mov [codepoints + 95*4 + rbx*4], ecx inc rcx cmp rcx, 0x6C1 ; 到0x6C1结束(包含0x6C0) jne init_cyrillic_loop ; Load the font mov rdi, fontFile ; font file path mov rsi, 32 ; font size mov rdx, codepoints ; codepoints array mov rcx, 800 ; 总codepoints数量(95+705) call LoadFontEx mov [font], rax ; 存储返回的Font指针 .again: call WindowShouldClose test rax, rax jnz .over call BeginDrawing mov rdi, 0xFF181818 call ClearBackground mov rdi, text1 mov rsi, 100 mov rdx, 100 mov rcx, 20 mov r8, 0xFFFFFFFF call DrawText ; 启用DrawTextEx的示例(需取消注释textPos定义) ; mov rdi, [font] ; mov rsi, text1 ; mov rdx, textPos ; mov rcx, 32.0 ; mov r8, 0xFFFFFFFF ; call DrawTextEx call EndDrawing jmp .again .over: ; 卸载字体避免内存泄漏 mov rdi, [font] call UnloadFont call CloseWindow mov rdi, 0 call _exit
额外注意事项
- 确保
km.ttf文件存在于程序运行目录,否则LoadFontEx会返回空指针,后续操作也会触发段错误。 - 程序退出前调用
UnloadFont释放字体资源,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Bleb1k
相关产品推荐
相关产品推荐

