I'm creating a program that shows the registers called dumpRegisters. The registers need to match what is shown in the Registers window in the debugger (using Visual Studio). The registers in the window of the debugger are: EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP, EIP, EFL. 10 registers total.
I know the Irvine Library already has this procedure, but I'm creating it from scratch.
I'm able to show most of the registers. However, I'm struggling on how to display the ESP (extended stack pointer) register?
I use push and pop throughout the program, so when I call a showRegister procedure, it outputs the ESP at that point, but ESP continues to change, so the when the program exits, the ESP I showed is not the same. I've tried to push and pop esp, however, it still doesn't match depending on where I push and pop esp, sometimes it also only shows the first 4 registers.
How can I get the ESP register to match the registers window in the debugger?
dumpRegisters PROC
push eax
push edx
mov edx, OFFSET essp
mov eax, esp
INVOKE showRegister, OFFSET essp, esp
pop edx
pop eax
dumpRegisters ENDP
showRegister PROC,
regName:PTR BYTE , regValue:DWORD
;push esp
call writeString
call writeHex
Tab
;pop esp
ret
showRegister ENDP
After printing or saving other incoming args, calculate what ESP must have been before the call dumpRegsiters
(typo?) that pushed a 4-byte return address, plus whatever other pushes you did.
lea eax, [esp+12]
should be correct after 2 pushes.
You should probably start with a pushf
to save EFLAGS first, so you can use instructions that modify FLAGS like add
or sub
. Then of course adjust your offsets accordingly. Unless it turns out that the Irvine32 functions like WriteHex save/restore EFLAGS themselves, then you're probably just juggling incoming data.
You could even start with pusha
and loop through popping and printing, if you don't need to print register names with the values. One of the few use-cases for that instruction, although you still might want to calculate ESP instead of using what it pushed.
(And I guess get EIP from your return address, if you don't mind having the address after the call. If you want the address before, you have to figure out whether it was a 5-byte call rel32
, or a call through a function pointer like 2-byte call eax
.)