当中断将在基于X86体系结构的64位CPU中发生时,CPU将自动推动一些IRET寄存器值,然后按照堆栈
+-------------------------+
| err. code(if applicable)|
+-------------------------+
| rip |
+-------------------------+
| cs |
+-------------------------+
| rflags |
+-------------------------+
| rsp |
+-------------------------+
| ss |
+-------------------------+
现在我已经通过follwoing方式定义了CPU状态结构
struct registers { // Total 26*8 = 208 bytes which is 16 bytes aligned
// CPU state
uint64_t iret_rip; // Offset 8*0
uint64_t iret_cs; // Offset 8*1
uint64_t iret_rflags; // Offset 8*2
uint64_t iret_rsp; // Offset 8*3
uint64_t iret_ss; // Offset 8*4
uint64_t err_code; // Offset 8*5
uint64_t int_no; // Offset 8*6
// General purpose registers
uint64_t r15; // Offset 8*7
uint64_t r14; // Offset 8*8
uint64_t r13; // Offset 8*9
uint64_t r12; // Offset 8*10
uint64_t r11; // Offset 8*11
uint64_t r10; // Offset 8*12
uint64_t r9; // Offset 8*13
uint64_t r8; // Offset 8*14
uint64_t rsi; // Offset 8*15
uint64_t rdi; // Offset 8*16
uint64_t rbp; // Offset 8*17
uint64_t rdx; // Offset 8*18
uint64_t rcx; // Offset 8*19
uint64_t rbx; // Offset 8*20
uint64_t rax; // Offset 8*21
// Segment registers
uint64_t ds; // Offset 8*22
uint64_t es; // Offset 8*23
uint64_t fs; // Offset 8*24
uint64_t gs; // Offset 8*25
} __attribute__((packed));
typedef struct registers registers_t;
a
void isr_handler(registers_t *regs)
功能将管理中断服务例程。要按正确顺序在堆栈中创建上述结构以及16个字节对齐,然后调用isr_handler
函数和构造_start指针放入rdi中,所以当CPU不推动错误代码,但我推出虚拟错误代码时,我已经写下了以下宏。
%macro ISR_NOERRCODE 1
[global isr%1]
isr%1:
cli;
push 0 ; Dummy error code
push %1 ; Interrupt number
push r15 ; Save general-purpose registers in reverse order (to match RESTORE_REGISTERS)
push r14
push r13
push r12
push r11
push r10
push r9
push r8
push rsi
push rdi
push rbp
push rdx
push rcx
push rbx
push rax
mov ax, ds ; Save segment registers
push rax
mov ax, es
push rax
push fs
push gs
mov rdi, rsp ; Pass pointer to the `registers_t` structure
cld ; Clear the direction flag
call isr_handler ; Call the interrupt handler
pop gs ; Restore segment registers
pop fs
pop rax
mov es, ax
pop rax
mov ds, ax
pop rax ; Restore general-purpose registers
pop rbx
pop rcx
pop rdx
pop rbp
pop rdi
pop rsi
pop r8
pop r9
pop r10
pop r11
pop r12
pop r13
pop r14
pop r15
add rsp, 16 ; Clean up interrupt no and dummy error code
iretq ; Return from the interrupt using IRETQ (iret values remain intact)
%endmacro
不幸的是,当我试图通过测试中断时,这个宏无法使用
asm volatile ("int $0x3");
应打印在带错误代码0的中断3中,但显示带有错误代码的中断0。 这显示堆栈内存可能无法正确存储值。 错误中断代码的原因是什么?full代码
link.
我如何解决此问题,因为它没有显示正确的中断代码。
struct
中,宣布的第一个成员处于最低地址。 因此,您将它们逆转。
也是,您对CPU推动的图表不正确。 如果您从页面上向下移动(这与英特尔的手册相反)的低地址读取它,这几乎是正确的,但是错误代码应处于最低地址。为了与您的ASM代码保持一致,声明的声明应该看起来像:
struct registers
通过方式,这里是不必要的,因为所有成员的大小都是相同的(8个字节),并且结构应始终与8个字节保持一致。 编译器不会在这样的结构中插入填充物; ABI禁止它。