ESP and EBP change not committed after return from interrupt

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
DirectXtreme
Posts: 12
Joined: Mon Aug 06, 2012 12:19 pm
Location: Pretoria, South Africa

ESP and EBP change not committed after return from interrupt

Post by DirectXtreme »

Hello All;
This is my first post here and I am still a noob at OSDev so Il accept any advice/tips on posting. Anyway, I am currently trying to implement multitasking in my OS. I change tasks on the timer interrupt by changing the values of the registers stored on the stack before it is popped back off the stack. My IRQ handler looks like this:

Code: Select all

[extern] IRQ_HANDLER
    IRQ_COMMON_STUB:
	pusha 			;push all common registers
	
	mov ax, ds		;put data segment selector into AX
	push eax		;save eax, which is value of ds
	mov ax, 0x10		;put us back into kernel mode (ring 0)
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	call IRQ_HANDLER	;Call the high-level handler
	pop eax			;restore eax, which contains original ds in lower 16 bits (AX)
	mov ds, ax		;restore data segment selector
	mov es, ax		
	mov fs, ax
	mov gs, ax

	popa			;pop all common registers
	add esp, 8		;fix stack after popping the ISR number and Error Code
	sti
	iret]


and IRQ_HANDLER looks like this:

Code: Select all

void IRQ_HANDLER(registers_t* regs);
If I modify any other registers e.g. regs->eax the result is committed and I can perform task switching by saving and restoring the EIP of the tasks. But if I change ESP or EBP the values of these registers are not modified and the stack of the next task is not loaded.

I am completely lost so any help at this point would be greatly appreciated.
Thank you
A living being seeks above all else to discharge its strength. Life itself is will to power. Nothing else matters.

Project: HazeOS, HazeAV
User avatar
xenos
Member
Member
Posts: 1121
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

Re: ESP and EBP change not committed after return from inter

Post by xenos »

EBP should be restored from the stack by popa, but the ESP value on the stack is simply discarded by popa. (IIRC - I'm too tired to look it up right now...)
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: ESP and EBP change not committed after return from inter

Post by Combuster »

CS/SS/EIP/ESP/EFLAGS are restored by the IRET, and never by POPA. So to change ESP in userland, your registers struct will have to have ESP stored among the 5 doublewords corresponding to the interrupt return stackframe, and not to the 8 corresponding to the pushall frame.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
DirectXtreme
Posts: 12
Joined: Mon Aug 06, 2012 12:19 pm
Location: Pretoria, South Africa

Re: ESP and EBP change not committed after return from inter

Post by DirectXtreme »

XenOS wrote:EBP should be restored from the stack by popa, but the ESP value on the stack is simply discarded by popa. (IIRC - I'm too tired to look it up right now...)
I understand that but not even the new EBP is restored when the interrupt return.
A living being seeks above all else to discharge its strength. Life itself is will to power. Nothing else matters.

Project: HazeOS, HazeAV
DirectXtreme
Posts: 12
Joined: Mon Aug 06, 2012 12:19 pm
Location: Pretoria, South Africa

Re: ESP and EBP change not committed after return from inter

Post by DirectXtreme »

Combuster wrote:CS/SS/EIP/ESP/EFLAGS are restored by the IRET, and never by POPA. So to change ESP in userland, your registers struct will have to have ESP stored among the 5 doublewords corresponding to the interrupt return stackframe, and not to the 8 corresponding to the pushall frame.
My registers struct includes the 8 GPRs and the 5 DWoRDS popped when the interrupt handler is called.
A living being seeks above all else to discharge its strength. Life itself is will to power. Nothing else matters.

Project: HazeOS, HazeAV
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: ESP and EBP change not committed after return from inter

Post by gerryg400 »

Code: Select all

void IRQ_HANDLER(registers_t* regs);
This function expects to be passed a pointer to the regs structure. Where, in your code, do you put that pointer on the stack ?
If a trainstation is where trains stop, what is a workstation ?
DirectXtreme
Posts: 12
Joined: Mon Aug 06, 2012 12:19 pm
Location: Pretoria, South Africa

Re: ESP and EBP change not committed after return from inter

Post by DirectXtreme »

gerryg400 wrote:

Code: Select all

void IRQ_HANDLER(registers_t* regs);
This function expects to be passed a pointer to the regs structure. Where, in your code, do you put that pointer on the stack ?
Good point, I think I missed that. Stupid question, how would I do that, should I push ESP before I call IRQ_HANDLER?
A living being seeks above all else to discharge its strength. Life itself is will to power. Nothing else matters.

Project: HazeOS, HazeAV
User avatar
eryjus
Member
Member
Posts: 286
Joined: Fri Oct 21, 2011 9:47 pm
Libera.chat IRC: eryjus
Location: Tustin, CA USA

Re: ESP and EBP change not committed after return from inter

Post by eryjus »

I have some homework for you:

Research how high-level languages such as C handle pass-by-reference versus pass-by-value (hint: you are implementing one in ASM and prototyping another in C). You will need to understand the difference and how the compiler will build the stack based on which method you are using for each function. Once you understand that, translate that into what ASM code you would need to write to implement each.

By mixing ASM and C, you are now completely responsible for making sure you handle both sides in a consistent manner for each function -- meaning the compiler cannot keep you honest. This will more than like not be the only place you mix ASM and C in your OS, so it will become a necessary skill.
Adam

The name is fitting: Century Hobby OS -- At this rate, it's gonna take me that long!
Read about my mistakes and missteps with this iteration: Journal

"Sometimes things just don't make sense until you figure them out." -- Phil Stahlheber
DirectXtreme
Posts: 12
Joined: Mon Aug 06, 2012 12:19 pm
Location: Pretoria, South Africa

Re: ESP and EBP change not committed after return from inter

Post by DirectXtreme »

Ok, I fixed some of my code by pushing ESP before the call to the IRQ_HANDLER and popping it after. This allows my

Code: Select all

void IRQ_HANDLER(registers_t* regs);
to work. But now I can still not edit EBP or ESP. My Registers struct looks as follows:

Code: Select all

struct REGISTERS
{
    DWORD ds;
    DWORD edi, esi, ebp, esp, ebx, edx, ecx, eax;
    DWORD int_no, err_code;
    DWORD eip, cs, eflags, useresp, ss;
    
}__attribute__((packed));
The registers struct represents what the stack will look like, as far as I can tell it will look as follows:

Code: Select all

|    SS    |     {
|   ESP    |
| EFLAGS |            These are popped when the interrupt is called and will be
|    CS    |               restored on the IRET
|    EIP   |      }
|   EAX   |      {
|   ECX   |              These are popped by the PUSHA and is restored by the POPA 
|   EDX   |
|   EBX   |
|   ESP   |              Modifying this has not effect as it is discard
|   EBP   |
|   ESI   |
|   EDI   |       }
|    DS   |      {   This is pushed and popped by me   }

If anyone can see anything wrong with the above please let could you let me know.
Oh and I have a really random issue, when I set regs->ecx the change is also see in regs->useresp after the interrupt returns to the new task.
A living being seeks above all else to discharge its strength. Life itself is will to power. Nothing else matters.

Project: HazeOS, HazeAV
DirectXtreme
Posts: 12
Joined: Mon Aug 06, 2012 12:19 pm
Location: Pretoria, South Africa

Re: ESP and EBP change not committed after return from inter

Post by DirectXtreme »

Progress has been made! My IRQ handler is working properly and I can make changes to EBP and ESP in the handler. But now something weird is happening, the changes arnt committed when making changes in my task_switch function which accepts a pointer to the registers struct and is called by the IRQ handler.
A living being seeks above all else to discharge its strength. Life itself is will to power. Nothing else matters.

Project: HazeOS, HazeAV
Nable
Member
Member
Posts: 453
Joined: Tue Nov 08, 2011 11:35 am

Re: ESP and EBP change not committed after return from inter

Post by Nable »

> by pushing ESP before the call to the IRQ_HANDLER and popping it after
I hope that you don't pop it to ESP (functions are allowed to change their arguments).
DirectXtreme
Posts: 12
Joined: Mon Aug 06, 2012 12:19 pm
Location: Pretoria, South Africa

Re: ESP and EBP change not committed after return from inter

Post by DirectXtreme »

Nable wrote:> by pushing ESP before the call to the IRQ_HANDLER and popping it after
I hope that you don't pop it to ESP (functions are allowed to change their arguments).
I am popping it back into ESP because I do not change the value. Should I rather pop it into EAX for safety reasons?
A living being seeks above all else to discharge its strength. Life itself is will to power. Nothing else matters.

Project: HazeOS, HazeAV
User avatar
xenos
Member
Member
Posts: 1121
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

Re: ESP and EBP change not committed after return from inter

Post by xenos »

You can simply discard it (increase ESP by 4 instead of popping anything).
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
Nable
Member
Member
Posts: 453
Joined: Tue Nov 08, 2011 11:35 am

Re: ESP and EBP change not committed after return from inter

Post by Nable »

Should I rather pop it into EAX for safety reasons?
If I were you, I would pop to EAX or change function declaration to passing structure with regs by values instead of pointer.
Else, you can define your function as stdcall, so it will be ended with ret 4, i.e. clean argument from stack by itself.
You can simply discard it (increase ESP by 4 instead of popping anything).
AFAIK, it can be a bad idea if you care about performance: CPU's out-of-order and other execution units like when what pairs of call/ret, push/pop, interrupt/iret are balanced.
DirectXtreme
Posts: 12
Joined: Mon Aug 06, 2012 12:19 pm
Location: Pretoria, South Africa

Re: ESP and EBP change not committed after return from inter

Post by DirectXtreme »

Nable wrote:
Should I rather pop it into EAX for safety reasons?
If I were you, I would pop to EAX or change function declaration to passing structure with regs by values instead of pointer.
Else, you can define your function as stdcall, so it will be ended with ret 4, i.e. clean argument from stack by itself.
You can simply discard it (increase ESP by 4 instead of popping anything).
AFAIK, it can be a bad idea if you care about performance: CPU's out-of-order and other execution units like when what pairs of call/ret, push/pop, interrupt/iret are balanced.
Nable, +1 for bringing in the aspect of performance.
A living being seeks above all else to discharge its strength. Life itself is will to power. Nothing else matters.

Project: HazeOS, HazeAV
Post Reply