GAS中标签地址操作:x86汇编构建IDT存储函数地址报错求解
解决x86汇编构建IDT时拆分函数地址高低位的问题
报错原因
你遇到的错误是因为GNU汇编器(GAS)不允许直接对跨段符号(.text段的handler0属于段相对符号,并非绝对地址)进行位运算操作,汇编阶段无法直接解析这类跨段的移位、与运算。
正确实现方式
针对GAS,最简洁的方法是使用内置的%hi()和%lo()宏,分别提取符号地址的高16位和低16位:
.text globl handler0 type handler0, @function .align 2 handler0: pushl $(0) jmp _alltraps .data .hword %hi(handler0) ; 提取handler0地址的高16位 .hword 0x8F00 ; IDT门属性(32位中断门,DPL=3,存在) .hword 0x0008 ; 段选择子(指向内核代码段) .hword %lo(handler0) ; 提取handler0地址的低16位
如果你的汇编器版本不支持%hi/%lo宏,也可以用.set指令将符号转换为绝对地址引用后再做位运算:
.data .set handler0_abs, handler0 ; 将handler0转为绝对地址符号 .hword ((handler0_abs >> 16) & 0xFFFF) .hword 0x8F00 .hword 0x0008 .hword (handler0_abs & 0xFFFF)
补充说明
IDT的32位中断门描述符结构为8字节,顺序依次是:
- 低16位:中断处理函数的偏移地址低16位
- 中间16位:段选择子(这里0x0008指向内核代码段)
- 接下来16位:门属性(0x8F00表示32位中断门、特权级3、存在)
- 高16位:中断处理函数的偏移地址高16位
你的代码中属性和段选择子的顺序是正确的,只需修正地址拆分方式即可。
内容的提问来源于stack exchange,提问作者ZRnQ
相关产品推荐
相关产品推荐

