practice practice
i had to verify how to handle saved processors registers as they are essential elements that a fault-trap-handler must deal with. so i made a simple program that pushads registers (program state at the very least) then calls a c function that reads the stack. hopefully, i can apply what i’ve learned in this activity in making my own interrupt-exception handlers sometime in the future. :p
see intel software developer’s manual 5.12.1 exception- or interrupt-handler procedure.
also see 5.15 exception and interrupt reference
first comes the main program block. it’s in asm.
; pusha_struct.asm
; just some testing stuff
; stephanie
global main
section .text
main
push ebp ; prologue
mov ebp, esp ;
extern getregs
pushad ; push all registers in operand atribute 32
call getregs ; using a struct
add esp, 0x20
xor eax, eax
leave ; epilogue
ret
section .data
then a c file where i’ll try to read the pushad registers.
/* pusha_struct.c
* practice
* read processors registers
* hopefully, i'll understand this and move on. */
#include <stdio.h>
/* from intel manual:
* pusha
* Pushes all general purpose registers onto the stack in the following
* order: (E)AX, (E)CX, (E)DX, (E)BX, (E)SP, (E)BP, (E)SI, (E)DI. The
* value of SP is the value before the actual push of SP. */
struct pusha_t
{
unsigned long edi, esi, ebp, esp, ebx, edx, ecx, eax;
};
int getregs(struct pusha_t i386regs)
{
printf("eax: 0x%08x\n", i386regs.eax);
printf("ebx: 0x%08x\n", i386regs.ebx);
printf("ecx: 0x%08x\n", i386regs.ecx);
printf("edx: 0x%08x\n", i386regs.edx);
printf("esp: 0x%08x\n", i386regs.esp);
printf("ebp: 0x%08x\n", i386regs.ebp);
printf("esi: 0x%08x\n", i386regs.esi);
printf("edi: 0x%08x\n", i386regs.edi);
return 0;
}
i also made a simple makefile because i was bored. *giggles*
CC=/usr/bin/gcc
CFLAGS=-Wall -c
NASM=/usr/bin/nasm
NASMFLAG=-f elf
LD=/usr/bin/ld
all: pusha_struct
pusha_struct: asmsrc csrc
$(CC) -o pusha pusha_struct.o pusha_struct2.o
asmsrc: pusha_struct.asm
$(NASM) $(NASMFLAG) pusha_struct.asm
csrc: pusha_struct.c
$(CC) $(CFLAGS) -o pusha_struct2.o pusha_struct.c
.PHONY: clean
clean:
@echo making clean...
@rm *.o
i examined the program under gdb by looking at “before” and “print” values of the concerned registers and they all match. except of course esp. the push instruction places the esp value before the real “push” onto stack, hence the discrepancy.
steph@heaven ~/git/null/c/asm-linkage $ gdb pusha Using host libthread_db library \"/lib/libthread_db.so.1\". steph@gdb $ b getregs Breakpoint 1 at 0x8048396 steph@gdb $ r Starting program: /home/steph/git/null/c/asm-linkage/pusha Breakpoint 1, 0x08048396 in getregs () steph@gdb $ info r eax 0x1 1 ecx 0xb7f07ff4 -1208975372 edx 0xb7f0a4dc -1208965924 ebx 0xb7f07ff4 -1208975372 esp 0xbff2b150 0xbff2b150 ebp 0xbff2b158 0xbff2b158 esi 0xb7f2cc80 -1208824704 edi 0xbff2b204 -1074613756 eip 0x8048396 0x8048396well now, that wasn’t terribly exiting was it? i still learned a lot nevertheless. i had only one thing on my mind the whole day today. condor heroes-liu yi fei.eflags 0x286 646 cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x0 0 steph@gdb $ step Single stepping until exit from function getregs, which has no line number information. eax: 0x00000001 ebx: 0xb7f07ff4 ecx: 0xb7f07ff4 edx: 0xb7f0a4dc esp: 0xbff2b180 ebp: 0xbff2b1a8 esi: 0xb7f2cc80 edi: 0xbff2b204 0x08048385 in main ()
