使用X11在x86-64汇编中实现最小化GUI:针对fasmg的优化
开发者在编写底层代码时,常面临在保持功能性的同时最小化可执行文件大小的挑战。本文探讨了如何使用X11协议在x86-64汇编中创建一个最小化的GUI。我们利用fasmg生成无需链接器的紧凑二进制文件,使用mmap进行动态内存分配,并通过宏简化系统调用。
目标是创建一个带文本的GUI窗口,比原始实现更小。重点在于为中高级开发者提供代码可读性:X11请求结构、ABI兼容性和数据复制优化。
设置开发环境
在VSCode中构建,包含发布和调试模式的任务。发布模式:DEBUG=0;调试模式:DEBUG=1,并生成DWARF符号。
{
"label": "生成发布可执行文件",
"type": "shell",
"command": "chmod",
"args": ["+x", "${fileBasenameNoExtension}"],
"dependsOn": "使用fasmg进行发布构建"
}
在Cutter中调试,使用launch.json:
{
"name": "启动Cutter",
"type": "node",
"request": "launch",
"preLaunchTask": "使用fasmg进行调试构建",
"runtimeExecutable": "Cutter.AppImage",
"runtimeArgs": [
"${fileDirname}/${fileBasenameNoExtension}",
"--analysis", "2",
"--arch", "x86",
"--bits", "64"
]
}
按Ctrl+Shift+T进行调试构建(针对.asm文件)。
调试和日志宏
仅在调试模式下动态链接libc:
include 'dynamic/import64.inc'
if DEBUG
interpreter '/lib64/ld-linux-x86-64.so.2'
needed 'libc.so.6'
import printf
end if
支持%d、%f、%e、%g、%a的变参printf宏。COUNT_ARGS_TO计算参数数量,GET_VARARG_TO按索引检索参数。
通过fasm虚拟内存将浮点/双精度转换为IEEE-754:
macro MOVQ_IMM reg, val
local bits
virtual at 0
dq val
load bits qword from 0
end virtual
mov rax, bits
movq reg, rax
end macro
主VARG_FUNC宏解析格式字符串,根据System V ABI(浮点数使用xmm0-xmm7,整数使用rsi/rdx/...)将参数分配到寄存器。DEBUG_MSG是日志的包装器。
X11请求结构
统一的FULL_LAYOUT结构包含所有必要请求:
struct FULL_LAYOUT
ridBase dd 0
ridMask dd 0
windowRootId dd 0
rootVisualId dd 0
gcId dd 0
exposed db 0
create_window_req X11_CREATE_WINDOW
draw_string_req STRING_TO_DRAW
handshake X11_HANDSHAKE
gc_request X11_CREATE_GC
addr_un SOCKADDR_UN
map_window_req X11_MAP_WINDOW
union
free rb HEAP_SIZE - ($ - create_window_req)
setup X11_SETUP
pollfd POLLFD
endu
ends
字段排序以最小化复制代码。布局在r12中,套接字在r13+中。
通用系统调用宏
MAKE_SYSCALL自动化设置寄存器(rdi、rsi、rdx、r10、r8、r9),支持ptr [c]、[c]、0:
macro MAKE_SYSCALL scall, args&
iterate arg, args
if % = 1
match =ptr [c], arg
lea rdi, [c]
else match [c], arg
mov rdi, [c]
else match =0, arg
xor rdi, rdi
else
mov rdi, arg
end match
; 类似处理rsi、rdx、r10...
end iterate
; syscall scall
end macro
大小和性能优化
- 使用mmap替代静态数据:4KB页面用于所有X11结构。
- 使用movsb进行复制:分组字段以最小化调用。
- 寄存器存储常量:r12-r15保持不变。
- 二进制中的默认值:宏仅生成使用的字段。
- 固定字体:X11自动选择“fixed”。
fasmg的优势:代码紧凑、宏支持、无需链接器。
关键要点
- X11请求结构排序以实现最优movsb复制。
- 通过虚拟内存进行IEEE-754转换的变参printf宏。
- 通用系统调用宏减少70%的样板代码。
- 4KB mmap覆盖所有结构,无需二进制中的静态数据。
- VSCode + Cutter中的调试/发布构建,便于逆向工程。
— Editorial Team
暂无评论。