INT instruction stack behavior in x86-64 (Bochs)
Posted: Thu Aug 03, 2017 5:38 am
Hello everyone, I'm an italian student, and I'm rewriting for the fourth time (I still have a lot to learn about OS development), my simple OS. I'm trying to improve this version so much, so I decided to implement long mode, and maybe graphics for the first time, after a studying pause.
I'm still working on the bootloader, so my environment consists in NASM, bochs, other universal tools like an hex-editor, running in LinuxMint 18.2 'Sonya' on a HP P6 Pavilion (2011) machine. I successfully set up Long Mode, identity paging the first 4Mb of memory, and a basic environment, like keyboard's and RTC's IRQ handler(still developing to achieve HPET), but I found something strange when debugging my system call handler (INT 80h).
My syscall handler needs some quadword data to be pushed on the stack, just before the (r_flags if I remember right) data pushed by the INT instruction. Unlike common practice, I make the callee clean the stack, by moving the stack 8 byte upwards unless it moves the byte pointed by current ESP, then adding ESP,08h . This is done for every parameter needed by the called function. The only problem of this method is that it needs to know the number of byte pushed by the INT instruction, that's a known value and shouldn't be hard to find.
However, I found only partial data on INT instruction behavior in x86-64, so I tried to check it out by the following code(relying on Bochs magic breakpoint tool):
And this is the code of the INT 81h handler:
That's very simple, when setting ESP on every 16-byte aligned address, at the breakpoints I got always the same RSP values:
In this case, and in all cases with all 8-byte aligned RSP values before the INT call, the RSP values at the breakpoints are the following:
This introduces a very dangerous misalignment in the stack, as a "useless" information is pushed and never popped.
Can anybody please explain why is this happening? Is a Bochs bug, or does long mode need to work with 16-byte aligned stack addresses, or anything else?
I'm still working on the bootloader, so my environment consists in NASM, bochs, other universal tools like an hex-editor, running in LinuxMint 18.2 'Sonya' on a HP P6 Pavilion (2011) machine. I successfully set up Long Mode, identity paging the first 4Mb of memory, and a basic environment, like keyboard's and RTC's IRQ handler(still developing to achieve HPET), but I found something strange when debugging my system call handler (INT 80h).
My syscall handler needs some quadword data to be pushed on the stack, just before the (r_flags if I remember right) data pushed by the INT instruction. Unlike common practice, I make the callee clean the stack, by moving the stack 8 byte upwards unless it moves the byte pointed by current ESP, then adding ESP,08h . This is done for every parameter needed by the called function. The only problem of this method is that it needs to know the number of byte pushed by the INT instruction, that's a known value and shouldn't be hard to find.
However, I found only partial data on INT instruction behavior in x86-64, so I tried to check it out by the following code(relying on Bochs magic breakpoint tool):
Code: Select all
;IRQ's and NMI's are previously disabled, and current ESP location saved in memory
MOV RSP,1000h ;Address totally free of useful data
XCHG BX,BX ;First Breakpoint
INT 81h ;Calls int 81h handler written for this puorpose
XCHG BX,BX ;Third Breakpoint
And this is the code of the INT 81h handler:
Code: Select all
;Performs just a breakpoint and returns
XCHG BX,BX ;Second Breakpoint
IRETQ
- 1000h
- 0FD8h
- 1000h
Code: Select all
;IRQ's and NMI's are previously disabled, and current ESP location saved in memory
MOV RSP,1000h ;Address totally free of useful data
PUSH RAX ;Pushes RAX (that is equal to 0xAAAAAAAA_AAAAAAAA)on the stack
XCHG BX,BX ;First Breakpoint
INT 81h ;Calls int 81h handler written for this puorpose
XCHG BX,BX ;Third Breakpoint
In this case, and in all cases with all 8-byte aligned RSP values before the INT call, the RSP values at the breakpoints are the following:
- 0FF8h
- 0FC8h (and not FD0 as expected)
- 0FF0h (8-bytes under the original value!!!)
This introduces a very dangerous misalignment in the stack, as a "useless" information is pushed and never popped.
Can anybody please explain why is this happening? Is a Bochs bug, or does long mode need to work with 16-byte aligned stack addresses, or anything else?