feat: gestion d'exception avancé avec dump des registres

This commit is contained in:
Nicolas Hordé 2018-10-03 22:50:54 +02:00
parent baf52f0594
commit 72abe00043
11 changed files with 314 additions and 127 deletions

View File

@ -41,6 +41,10 @@
#define ltr(tss) asm volatile ("ltr %%ax":: "a" (tss)) #define ltr(tss) asm volatile ("ltr %%ax":: "a" (tss))
#define str(tss) asm volatile ("str %%ax;\
mov %%ax,%0":: "m" (tss))
/******************************************************************************/ /******************************************************************************/
#define outb(port,value) \ #define outb(port,value) \

View File

@ -43,5 +43,6 @@ bool cansetflag (u32 flag);
void cpuid(u32 op, u32 *eax, u32 *ebx,u32 *ecx, u32 *edx); void cpuid(u32 op, u32 *eax, u32 *ebx,u32 *ecx, u32 *edx);
u8 getcpuinfos(cpuinfo *inf); u8 getcpuinfos(cpuinfo *inf);
u32 getESP(void); u32 getESP(void);
void dump_regs(exception_stack *stack); u32 setESP(u32 stack);
void dump_cpu(save_stack *stack);
void show_cpu(save_stack *stack);

View File

@ -77,3 +77,11 @@ typedef struct tss {
void inittr(void); void inittr(void);
void initgdt(u32 offset); void initgdt(u32 offset);
void makegdtdes(u32 base, u32 limite, u8 acces, u8 flags, gdtdes *desc); void makegdtdes(u32 base, u32 limite, u8 acces, u8 flags, gdtdes *desc);
u32 getdesbase(u16 sel);
u8 getdestype(u16 sel);
u32 getdessize(u16 sel);
u32 getdeslimit(u16 sel);
bool isdesvalid(u16 sel);
u8 getdesbit3(u16 sel);
u32 getdesdpl(u16 sel);
u16 getdesalign(u16 sel);

View File

@ -37,6 +37,29 @@
#define TIMER_FREQ 1193180 /* fréquence pour timer dans un PC ou AT */ #define TIMER_FREQ 1193180 /* fréquence pour timer dans un PC ou AT */
#define HZ 100 /* Fréquence d'horloge (ajutste logiciellement sur IBM-PC) */ #define HZ 100 /* Fréquence d'horloge (ajutste logiciellement sur IBM-PC) */
/* save pile */
typedef struct save_stack {
u32 cr4;
u32 cr3;
u32 cr2;
u32 cr0;
u32 eflags;
u32 ss;
u32 gs;
u32 fs;
u32 es;
u32 ds;
u32 eip;
u32 cs;
u32 esp;
u32 ebp;
u32 edi;
u32 esi;
u32 edx;
u32 ecx;
u32 ebx;
u32 eax;
} save_stack __attribute__ ((packed));
/* exception pile */ /* exception pile */
typedef struct exception_stack { typedef struct exception_stack {
u32 error_code; u32 error_code;
@ -72,7 +95,7 @@ struct idtr {
void initpic(void); void initpic(void);
void enableirq(u8 irq); void enableirq(u8 irq);
void disableirq(u8 irq); void disableirq(u8 irq);
void cpuerror(const u8 * src, const exception_stack *stack); void cpuerror(const u8 * src, const save_stack *stack);
#endif #endif

View File

@ -17,4 +17,6 @@ int mode();
int clear(); int clear();
int regs(); int regs();
int info(); int info();
int pagefault(); int pgfaultr();
int pgfaultw();
int divzerr();

177
lib/cpu.c
View File

@ -6,6 +6,7 @@
#include "memory.h" #include "memory.h"
#include "string.h" #include "string.h"
#include "asm.h" #include "asm.h"
#include "gdt.h"
/* Technologies supportées */ /* Technologies supportées */
@ -135,103 +136,99 @@ u32 getESP(void)
return stack; return stack;
} }
/******************************************************************************/
/* Fixe la tête de pile */
u32 setESP(u32 stack)
{
asm("movl %[param],%%esp;": [param] "=r"(stack));
}
/******************************************************************************/
/* Sauvegarde les registres CPU */
void dump_cpu(save_stack *stack)
{
save_stack new;
asm(" addl $0x50,%%esp \n \
pushl %%eax \n \
pushl %%ebx \n \
pushl %%ecx \n \
pushl %%edx \n \
pushl %%esi \n \
pushl %%edi \n \
pushl %%ebp \n \
pushl %%esp \n \
pushl %%cs \n \
pushl 0x0 \n \
pushl %%ds \n \
pushl %%es \n \
pushl %%fs \n \
pushl %%gs \n \
pushl %%ss \n \
pushf \n \
mov %%cr0, %%ebx \n \
pushl %%ebx\n \
mov %%cr2, %%ebx \n \
pushl %%ebx\n \
mov %%cr3, %%ebx \n \
pushl %%ebx\n \
mov %%cr4, %%ebx \n \
pushl %%ebx":::);
memcpy(&new, stack, sizeof(save_stack), 1);
}
/******************************************************************************/ /******************************************************************************/
/* Affiche les registres CPU */ /* Affiche les registres CPU */
void dump_regs(exception_stack *stack) void show_cpu(save_stack *stack)
{ {
cli(); printf("EAX=%Y EBX=%Y ECX=%Y EDX=%Y\r\n", stack->eax, stack->ebx, stack->ecx, stack->edx);
u32 eax = 0; printf("ESI=%Y EDI=%Y ESP=%Y EBP=%Y\r\n", stack->esi, stack->edi, stack->esp, stack->ebp);
u32 ebx = 0; printf("EIP=%Y EFL=%Y [%c%c%c%c%c%c%c%c%c]\r\n", stack->eip, stack->eflags,
u32 ecx = 0; (stack->eflags & (1 <<11)) ? 'O':'-',
u32 edx = 0; (stack->eflags & (1 <<10)) ? 'D':'-',
u32 esi = 0; (stack->eflags & (1 << 9)) ? 'I':'-',
u32 edi = 0; (stack->eflags & (1 << 8)) ? 'T':'-',
u32 ebp = 0; (stack->eflags & (1 << 7)) ? 'S':'-',
u32 esp = 0; (stack->eflags & (1 << 6)) ? 'Z':'-',
u32 eip = 0; (stack->eflags & (1 << 4)) ? 'A':'-',
u16 cs = 0; (stack->eflags & (1 << 2)) ? 'P':'-',
u16 ds = 0; (stack->eflags & (1 << 0)) ? 'C':'-');
u16 es = 0; printf("CS =%hY %Y %Y DPL=%d %cS%d [%c%c%c] %h ub\r\n",stack->cs,getdesbase(stack->cs),getdeslimit(stack->cs),getdesdpl(stack->cs),getdestype(stack->cs),getdessize(stack->cs),getdesbit3(stack->cs),getdesbit2(stack->cs),getdesbit1(stack->cs),getdesalign(stack->cs));
u16 fs = 0; printf("DS =%hY %Y %Y DPL=%d %cS%d [%c%c%c] %h ub\r\n",stack->ds,getdesbase(stack->ds),getdeslimit(stack->ds),getdesdpl(stack->ds),getdestype(stack->ds),getdessize(stack->ds),getdesbit3(stack->ds),getdesbit2(stack->ds),getdesbit1(stack->ds),getdesalign(stack->ds));
u16 gs = 0; printf("SS =%hY %Y %Y DPL=%d %cS%d [%c%c%c] %h ub\r\n",stack->ss,getdesbase(stack->ss),getdeslimit(stack->ss),getdesdpl(stack->ss),getdestype(stack->ss),getdessize(stack->ss),getdesbit3(stack->ss),getdesbit2(stack->ss),getdesbit1(stack->ss),getdesalign(stack->ss));
u16 ss = 0; printf("ES =%hY %Y %Y DPL=%d %cS%d [%c%c%c] %h ub\r\n",stack->es,getdesbase(stack->es),getdeslimit(stack->es),getdesdpl(stack->es),getdestype(stack->es),getdessize(stack->es),getdesbit3(stack->es),getdesbit2(stack->es),getdesbit1(stack->es),getdesalign(stack->es));
u32 cr0 = 0; printf("FS =%hY %Y %Y DPL=%d %cS%d [%c%c%c] %h ub\r\n",stack->fs,getdesbase(stack->fs),getdeslimit(stack->fs),getdesdpl(stack->fs),getdestype(stack->fs),getdessize(stack->fs),getdesbit3(stack->fs),getdesbit2(stack->fs),getdesbit1(stack->fs),getdesalign(stack->fs));
u32 cr1 = 0; printf("GS =%hY %Y %Y DPL=%d %cS%d [%c%c%c] %h ub\r\n",stack->gs,getdesbase(stack->gs),getdeslimit(stack->gs),getdesdpl(stack->gs),getdestype(stack->gs),getdessize(stack->gs),getdesbit3(stack->gs),getdesbit2(stack->gs),getdesbit1(stack->gs),getdesalign(stack->gs));
u32 cr2 = 0; u32 tss;
u32 cr3 = 0; str(tss);
u32 cr4 = 0; printf("TR =%hY %Y %Y DPL=%d %cS%d [%c%c%c] %h ub\r\n",stack->gs,getdesbase(tss),getdeslimit(tss),getdesdpl(tss),getdestype(tss),getdessize(tss),getdesbit3(tss),getdesbit2(tss),getdesbit1(tss),getdesalign(tss));
u32 eflags = 0; struct gdtr gdtreg;
asm("movl %%eax, %[a1] ;" "movl %%ebx, %[b1] ;" "movl %%ecx, %[c1] ;" "movl %%edx, %[d1] ;" "movl %%esi, %[e1] ;" "movl %%edi, %[f1] ;" "movl %%esp, %[g1] ;" "movl %%ebp, %[h1] ;" "movw %%cs, %[i1] ;" "movw %%ds, %[j1] ;" "movw %%es, %[k1] ;" "movw %%fs, %[l1] ;" "movw %%gs, %[m1] ;" "movw %%ss, %[n1] ;" "mov %%cr0, %%eax ;" "mov %%eax, %[o1] ;" "mov %%cr2, %%eax ;" "mov %%eax, %[p1] ;" "mov %%cr3, %%eax ;" "mov %%eax, %[q1] ;" "mov %%cr4, %%eax ;" "mov %%eax,%[r1] ;": sgdt(&gdtreg);
[a1] "=m"(eax),[b1] "=m"(ebx),[c1] "=m"(ecx),[d1] "=m"(edx),[e1] "=m"(esi), printf("GDT= %Y %Y\r\n",gdtreg.base,gdtreg.limite);
[f1] "=m"(edi),[g1] "=m"(esp),[h1] "=m"(ebp),[i1] "=m"(cs),[j1] "=m"(ds), struct idtr idtreg;
[k1] "=m"(es),[l1] "=m"(fs),[m1] "=m"(gs),[n1] "=m"(ss),[o1] "=m"(cr0), sidt(&idtreg);
[p1] "=m"(cr2),[q1] "=m"(cr3),[r1] "=m"(cr4)); printf("IDT= %Y %Y\r\n",idtreg.base,idtreg.limite);
if (stack!=0) {
eip=stack->eip;
eflags=stack->eflags;
cs=stack->cs;
esp=stack;
printf("\033[0m");
}
else
printf("\033[1mATTENTION PAS DE PILE ! REGISTRES INCERTAINS\r\n");
printf("EAX=%X EBX=%X ECX=%X EDX=%X\r\n", eax, ebx, ecx, edx);
printf("ESI=%X EDI=%X ESP=%X EBP=%X\r\n", esi, edi, esp, ebp);
printf("EIP=%X\r\n", eip);
printf
("CS=%hX DS=%hX ES=%hX FS=%hX GS=%hX SS=%hX\r\n",
(u32) cs, (u32) ds, (u32) es, (u32) fs, (u32) gs, (u32) ss);
printf("CR0=%X CR1=N/A CR2=%X CR3=%X CR4=%X\r\n", cr0, cr2, cr3,
cr4);
asm("pushf ;" "pop %[f1] ;":
[f1] "=m"(eflags));
printf("EFLAGS=%X", eflags);
if (eflags & (1 << 0)) // Carry
printf(" (C1");
else
printf(" (C0");
if (eflags & (1 << 2)) // Parity
printf(" P1");
else
printf(" P0");
if (eflags & (1 << 4)) // Adjust
printf(" A1");
else
printf(" A0");
if (eflags & (1 << 6)) // Zero
printf(" Z1");
else
printf(" Z0");
if (eflags & (1 << 7)) // Sign
printf(" S1");
else
printf(" S0");
if (eflags & (1 << 11)) // Overflow
printf(" O1)\r\n");
else
printf(" O0)\r\n");
printf("STACK\r\n"); printf("STACK\r\n");
u32 i = 0; if (abs(KERNEL_STACK_ADDR-stack->esp)>0x10000)
for (u32 *pointer = esp; pointer < KERNEL_STACK_ADDR; pointer += 4) { printf("Pile invalide !");
printf("+%d:%X\t\t%X\r\n", i++, pointer, else
(u32)(*pointer)); {
if (i > 5) { u32 i=0;
print("...\r\n"); for (u32 *pointer = stack->esp; pointer < KERNEL_STACK_ADDR; pointer ++) {
break; if (i>0 && i % 10 == 0) print("\033[10A");
} if (i>=10)
print("\033[25C");
printf("+%d:%Y - %Y\r\n", i++, pointer, (u32)(*pointer));
if (i > 20) {
print("...\r\n");
break;
}
}
for(u32 j=0;j<10-(i % 10);j++)
print("\033[01B");
} }
printf("\033[0m");
sti();
} }
/*******************************************************************************/ /*******************************************************************************/

116
lib/gdt.c
View File

@ -74,6 +74,122 @@ void initselectors(u32 executingoffset)
ret\n"::[data] "i"(SEL_KERNEL_DATA),[code] "i"(SEL_KERNEL_CODE),[stack] "i"(SEL_KERNEL_STACK),[stackoff] "i"(KERNEL_STACK_ADDR),[offset] "m"(executingoffset)); ret\n"::[data] "i"(SEL_KERNEL_DATA),[code] "i"(SEL_KERNEL_CODE),[stack] "i"(SEL_KERNEL_STACK),[stackoff] "i"(KERNEL_STACK_ADDR),[offset] "m"(executingoffset));
} }
/*******************************************************************************/
/* récupère la base d'un descripteur GDT */
u32 getdesbase(u16 sel)
{
gdtdes *entry=GDT_ADDR;
u8 index=sel/sizeof(gdtdes);
return (entry[index].base0_15+(entry[index].base16_23<<16)+(entry[index].base24_31<<24));
}
/*******************************************************************************/
/* récupère la limite d'un descripteur GDT */
u32 getdeslimit(u16 sel)
{
gdtdes *entry=GDT_ADDR;
u8 index=sel/sizeof(gdtdes);
return (entry[index].lim0_15+(entry[index].lim16_19<<16));
}
/*******************************************************************************/
/* récupère la limite d'un descripteur GDT */
u32 getdesdpl(u16 sel)
{
gdtdes *entry=GDT_ADDR;
u8 index=sel/sizeof(gdtdes);
return (entry[index].acces>>5 & 0b11);
}
/*******************************************************************************/
/* récupère le type d'un descripteur GDT */
u8 getdestype(u16 sel)
{
gdtdes *entry=GDT_ADDR;
u8 index=sel/sizeof(gdtdes);
if (((entry[index].acces & 0b10100) == 0) && ((entry[index].acces & 0b01000) > 0) && ((entry[index].acces & 0b0001) > 0) && ((entry[index].flags & 0b0110) == 0))
return 'T';
else
return (((entry[index].acces & 0b1000) > 0) ? 'C' : 'D');
}
/*******************************************************************************/
/* récupère l'info 1 d'un descripteur GDT */
u8 getdesbit1(u16 sel)
{
gdtdes *entry=GDT_ADDR;
u8 index=sel/sizeof(gdtdes);
if (((entry[index].acces & 0b10100) == 0) && ((entry[index].acces & 0b01000) > 0) && ((entry[index].acces & 0b0001) > 0) && ((entry[index].flags & 0b0110) == 0))
return (((entry[index].acces & 0b10) > 0) ? 'B' : '-');
else
return (((entry[index].acces & 0b1) > 0) ? 'A' : '-');
}
/*******************************************************************************/
/* récupère l'info 2 d'un descripteur GDT */
u8 getdesbit2(u16 sel)
{
gdtdes *entry=GDT_ADDR;
u8 index=sel/sizeof(gdtdes);
if (((entry[index].acces & 0b10100) == 0) && ((entry[index].acces & 0b01000) > 0) && ((entry[index].acces & 0b0001) > 0) && ((entry[index].flags & 0b0110) == 0))
return (((entry[index].flags & 0b1) > 0) ? 'U' : '-');
else if ((entry[index].acces & 0b1000) > 0)
return (((entry[index].acces & 0b10) > 0) ? 'R' : '-');
else
return (((entry[index].acces & 0b10) > 0) ? 'W' : 'R');
}
/*******************************************************************************/
/* récupère l'info 3 d'un descripteur GDT */
u8 getdesbit3(u16 sel)
{
gdtdes *entry=GDT_ADDR;
u8 index=sel/sizeof(gdtdes);
if ((entry[index].acces & 0b1000) > 0)
return (((entry[index].acces & 0b100) > 0) ? 'C' : '-');
else
return (((entry[index].acces & 0b100) > 0) ? 'D' : 'U');
}
/*******************************************************************************/
/* récupère l'alignement d'un descripteur GDT */
u16 getdesalign(u16 sel)
{
gdtdes *entry=GDT_ADDR;
u8 index=sel/sizeof(gdtdes);
return (((entry[index].flags & 0b1000) > 0) ? 4096: 1);
}
/*******************************************************************************/
/* récupère si descripteur GDT est valide */
bool isdesvalid(u16 sel)
{
gdtdes *entry=GDT_ADDR;
u8 index=sel/sizeof(gdtdes);
return ((entry[index].acces & 0b10000000) > 0);
}
/*******************************************************************************/
/* récupère la dimension d'un descripteur GDT */
u32 getdessize(u16 sel)
{
gdtdes *entry=GDT_ADDR;
u8 index=sel/sizeof(gdtdes);
if (((entry[index].acces & 0b10100) == 0) && ((entry[index].acces & 0b01000) > 0) && ((entry[index].acces & 0b0001) > 0) && ((entry[index].flags & 0b0110) == 0))
return 32;
else
return (((entry[index].flags & 0b1000) > 0) ? 32 : 16);
}
/*******************************************************************************/ /*******************************************************************************/
/* Créé un descripteur GDT */ /* Créé un descripteur GDT */

View File

@ -136,11 +136,12 @@ void putidt(u32 offset, u16 select, u16 type, u16 index)
/******************************************************************************/ /******************************************************************************/
/* Affiche une erreur CPU et fige l'ordinateur */ /* Affiche une erreur CPU et fige l'ordinateur */
void cpuerror(const u8 * src, const exception_stack *stack) void cpuerror(const u8 * src, const save_stack *stack)
{ {
printf("\033[31m*** ERREUR CPU : %s *** \r\n", src); printf("\033[31m*** ERREUR CPU : %s *** \r\n", src);
dump_regs(stack); show_cpu(stack);
print("<Appuyer une touche pour continuer>\r\n"); print("<Appuyer une touche pour continuer>\033[0m\r\n");
sti();
waitascii(); waitascii();
initselectors(retry_address); initselectors(retry_address);
/*while (true) { /*while (true) {
@ -168,79 +169,90 @@ void interruption()
void exception0() void exception0()
{ {
cpuerror("divide error",0x0); save_stack dump;
exception_stack_noerror *current = getESP()+0x80;
dump_cpu(&dump);
dump.eip=current->eip;
dump.cs=current->cs;
dump.esp=(current+1);
cpuerror("divide error",&dump);
} }
void exception1() void exception1()
{ {
cpuerror("debug exception",0x0); cpuerror("debug exception",NULL);
} }
void exception2() void exception2()
{ {
cpuerror("non-maskable hardware interrupt",0x0); cpuerror("non-maskable hardware interrupt",NULL);
} }
void exception3() void exception3()
{ {
cpuerror("INT3 instruction",0x0); cpuerror("INT3 instruction",NULL);
} }
void exception4() void exception4()
{ {
cpuerror("INTO instruction detected overflow",0x0); cpuerror("INTO instruction detected overflow",NULL);
} }
void exception5() void exception5()
{ {
cpuerror("BOUND instruction detected overrange",0x0); cpuerror("BOUND instruction detected overrange",NULL);
} }
void exception6() void exception6()
{ {
cpuerror("invalid instruction opcode",0x0); cpuerror("invalid instruction opcode",NULL);
} }
void exception7() void exception7()
{ {
cpuerror("no coprocessor",0x0); cpuerror("no coprocessor",NULL);
} }
void exception8() void exception8()
{ {
cpuerror("double fault",0x0); cpuerror("double fault",NULL);
} }
void exception9() void exception9()
{ {
cpuerror("coprocessor segment overrun",0x0); cpuerror("coprocessor segment overrun",NULL);
} }
void exception10() void exception10()
{ {
cpuerror("invalid task state segment (TSS)",0x0); cpuerror("invalid task state segment (TSS)",NULL);
} }
void exception11() void exception11()
{ {
cpuerror("segment not present",0x0); cpuerror("segment not present",NULL);
} }
void exception12() void exception12()
{ {
cpuerror("stack fault",0x0); cpuerror("stack fault",NULL);
} }
void exception13() void exception13()
{ {
cpuerror("general protection fault (GPF)",0x0); cpuerror("general protection fault (GPF)",NULL);
} }
void exception14() void exception14()
{ {
exception_stack *stack = getESP()+0x30; save_stack dump;
u8 *errorstring; exception_stack *current = getESP()+0x80;
switch (stack->error_code) { dump_cpu(&dump);
dump.eip=current->eip;
dump.cs=current->cs;
dump.esp=(current+1);
u8 *errorstring="page fault";
switch (current->error_code) {
case 0: case 0:
errorstring="page fault - Supervisory process tried to read a non-present page entry"; errorstring="page fault - Supervisory process tried to read a non-present page entry";
break; break;
@ -266,27 +278,27 @@ void exception14()
errorstring="Page fault - User process tried to write a page and caused a protection fault"; errorstring="Page fault - User process tried to write a page and caused a protection fault";
break; break;
} }
cpuerror(errorstring,stack); cpuerror(errorstring,&dump);
} }
void exception15() void exception15()
{ {
cpuerror("(reserved)",0x0); cpuerror("(reserved)",NULL);
} }
void exception16() void exception16()
{ {
cpuerror("coprocessor error",0x0); cpuerror("coprocessor error",NULL);
} }
void exception17() void exception17()
{ {
cpuerror("alignment check",0x0); cpuerror("alignment check",NULL);
} }
void exception18() void exception18()
{ {
cpuerror("machine check",0x0); cpuerror("machine check",NULL);
} }
/******************************************************************************/ /******************************************************************************/

View File

@ -218,7 +218,9 @@ unsigned convert(u32 keypressed)
} }
else if (key == SCAN_F9) { else if (key == SCAN_F9) {
dump_regs(); save_stack dump;
dump_cpu(&dump);
show_cpu(&dump);
} }
else if (key == SCAN_F10) { else if (key == SCAN_F10) {

View File

@ -22,7 +22,10 @@ static command commands[] = {
{"GDT" , "", &readgdt}, {"GDT" , "", &readgdt},
{"IDT" , "", &readidt}, {"IDT" , "", &readidt},
{"INFO" , "", &info}, {"INFO" , "", &info},
{"PAGEFAULT" , "", &pagefault} {"PGFAULTW" , "", &pgfaultw},
{"PGFAULTR" , "", &pgfaultr},
{"DIVZERR" , "", &divzerr}
}; };
/*******************************************************************************/ /*******************************************************************************/
@ -56,13 +59,28 @@ void shell()
} }
} }
/*******************************************************************************/
/* Génère une erreur de division par 0 */
int divzerr()
{
print("Creation d'une erreur de division par 0 !\r\n");
asm("movl $0x0,%ecx; divl %ecx");
}
/*******************************************************************************/ /*******************************************************************************/
/* Génère une erreur de page à l'adresse 0xE0000000 */ /* Génère une erreur de page à l'adresse 0xE0000000 */
int pagefault() int pgfaultw()
{ {
print("Creation d'une erreur de page !\r\n"); print("Creation d'une erreur de page !\r\n");
asm("mov $0x66666666, %eax \n \ asm("movl $0x66666666,(0xE0000000)");
mov %eax,0xE0000000"); }
/*******************************************************************************/
/* Génère une erreur de page à l'adresse 0xD0000000 */
int pgfaultr()
{
print("Creation d'une erreur de page !\r\n");
asm("movl (0xD0000000),%eax");
} }
/*******************************************************************************/ /*******************************************************************************/
@ -78,7 +96,9 @@ int info()
int regs() int regs()
{ {
dump_regs(0x0); save_stack dump;
dump_cpu(&dump);
show_cpu(&dump);
return 0; return 0;
} }

View File

@ -463,6 +463,8 @@ u32 printf(const u8 * string, ...)
break; break;
case 'x': case 'x':
case 'X': case 'X':
case 'y':
case 'Y':
if (asize==0) if (asize==0)
num = (u64) va_arg(args, u8); num = (u64) va_arg(args, u8);
else if (asize==1) else if (asize==1)
@ -474,9 +476,9 @@ u32 printf(const u8 * string, ...)
if (charadd == 0xFF) if (charadd == 0xFF)
charadd = '0'; charadd = '0';
itoa(num, &buffer, 16, sizes[asize], charadd); itoa(num, &buffer, 16, sizes[asize], charadd);
if (achar == 'X') if (achar == 'X'||achar == 'Y')
strtoupper(&buffer); strtoupper(&buffer);
print(&strbase16); if (achar == 'X') print(&strbase16);
counter += print(&buffer) + 1; counter += print(&buffer) + 1;
flag = false; flag = false;
break; break;