--- /dev/null
+; utility functions
+ cpu 8086
+ bits 16
+ section .text
+
+ global getip
+getip: push bp
+ mov bp, sp
+ mov ax, [bp + 2]
+ pop bp
+ ret
+
+ global getregs
+getregs:
+ push bp
+ mov bp, sp
+
+ mov bp, [bp + 4] ; grab regs pointer
+ mov [bp], ax
+ mov [bp + 2], bx
+ mov [bp + 4], cx
+ mov [bp + 6], dx
+ mov ax, sp
+ add ax, 6
+ mov [bp + 8], ax ; sp before the getregs call
+ mov bx, sp
+ mov ax, [bx]
+ mov [bp + 10], ax ; bp
+ mov [bp + 12], si
+ mov [bp + 14], di
+ pushf
+ pop ax
+ mov [bp + 16], ax ; cflags
+ mov ax, [bx + 2] ; caller ip
+
+ pop bp
+ ret
+
+ global getsregs
+getsregs:
+ push bp
+ mov bp, sp
+
+ mov ax, [bp + 4]
+ add ax, 8 ; point to the top of the sregs block (after ss)
+ mov sp, ax ; point sp there
+ push ss
+ push es
+ push ds
+ push cs
+
+ mov sp, bp
+ pop bp
+ ret
struct wordregs {
uint16_t ax, bx, cx, dx;
- uint16_t si, di, cflag;
+ uint16_t sp, bp;
+ uint16_t si, di, flags;
+ uint16_t ip;
} __attribute__((packed));
struct byteregs {
struct byteregs h;
};
+struct segregs {
+ uint16_t cs, ds, es, ss;
+} __attribute__((packed));
+
void int86(int n, union regs *inregs, union regs *outregs);
+uint16_t getip(void);
+void getregs(struct wordregs *regs);
+void getsregs(struct segregs *sregs);
#define FP_SEG(x) ((uint16_t)((uint32_t)(x) >> 16))
#define FP_OFFS(x) ((uint16_t)(x))
#define enable() asm("sti")
#define disable() asm("cli")
+#define halt() asm("hlt")
#define outp(p, v) \
asm volatile( \
-#include <stdarg.h>
+#include <stdio.h>
+#include <inttypes.h>
#include "dbg.h"
+#include "asmutil.h"
+__attribute__((noreturn))
void panic(const char *fmt, ...)
{
+ va_list ap;
+ struct wordregs regs;
+ struct segregs sregs;
+
+ getregs(®s);
+ regs.ip = getip(); /* replace ip with the caller's */
+ getsregs(&sregs);
+
+ printf("~~~~ PANIC ~~~~\n");
+
+ va_start(ap, fmt);
+ vprintf(fmt, ap);
+ va_end(ap);
+
+ printf("ax:%04x bx:%04x cx:%04x dx:%04x\n", regs.ax, regs.bx, regs.cx, regs.dx);
+ printf("bp:%04x si:%04x di:%04x flags:%04x\n", regs.bp, regs.si, regs.di, regs.flags);
+ printf("ss:sp %04x:%04x cs:ip %04x:%04x ds:%04x es:%04x\n", sregs.ss, regs.sp,
+ sregs.cs, regs.ip, sregs.ds, sregs.es);
+
+ for(;;) halt();
}
#ifndef DBG_H_
#define DBG_H_
-void panic(const char *fmt, ...);
+void panic(const char *fmt, ...) __attribute__((noreturn));
#endif /* DBG_H_ */
--- /dev/null
+#include "ctype.h"
+
+int isalnum(int c)
+{
+ return isalpha(c) || isdigit(c);
+}
+
+int isalpha(int c)
+{
+ return isupper(c) || islower(c);
+}
+
+int isblank(int c)
+{
+ return c == ' ' || c == '\t';
+}
+
+int isdigit(int c)
+{
+ return c >= '0' && c <= '9';
+}
+
+int isupper(int c)
+{
+ return c >= 'A' && c <= 'Z';
+}
+
+int islower(int c)
+{
+ return c >= 'a' && c <= 'z';
+}
+
+int isgraph(int c)
+{
+ return c > ' ' && c <= '~';
+}
+
+int isprint(int c)
+{
+ return isgraph(c) || c == ' ';
+}
+
+int isspace(int c)
+{
+ return isblank(c) || c == '\f' || c == '\n' || c == '\r' || c == '\v';
+}
+
+int toupper(int c)
+{
+ return c & ~0x20;
+}
+
+int tolower(int c)
+{
+ return c | 0x20;
+}
--- /dev/null
+#ifndef CTYPE_H_
+#define CTYPE_H_
+
+int isalnum(int c);
+int isalpha(int c);
+#define isascii(c) ((c) < 128)
+int isblank(int c);
+int isdigit(int c);
+int isupper(int c);
+int islower(int c);
+int isprint(int c);
+int isspace(int c);
+
+int toupper(int c);
+int tolower(int c);
+
+#endif /* CTYPE_H_ */
--- /dev/null
+#ifndef LIMITS_H_
+#define LIMITS_H_
+
+#define CHAR_BIT 8
+
+#define SHRT_MIN (-32768)
+#define SHRT_MAX 32767
+#define INT_MIN (-32768)
+#define INT_MAX 32767
+#define LONG_MIN (-2147483648)
+#define LONG_MAX 2147483647
+
+#define USHRT_MAX 65535
+#define UINT_MAX 65535
+#define ULONG_MAX 0xffffffff
+
+#define PATH_MAX 256
+
+#endif /* LIMITS_H_ */
#include <stdio.h>
+#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
+#include <ctype.h>
struct outbuf {
char *buf;
return res;
}
+int vprintf(const char *fmt, va_list ap)
+{
+ return intern_vprintf(0, fmt, ap);
+}
+
static void reset_format(struct format *fmt)
{
memset(fmt, 0, sizeof *fmt);
} else {
uval = va_arg(ap, unsigned int);
}
- count += wrint(outbuf, &fmt, uval);
+ count += wruint(outbuf, &fmt, uval);
reset_format(&fmt);
break;
reset_format(&fmt);
break;
+ case '0':
+ if(fmt.fchar != '0') {
+ fmt.fchar = '0';
+ break;
+ }
default:
- /* TODO: more format specifiers */
- reset_format(&fmt);
+ if(isdigit(c)) {
+ fmt.fwidth = strtol(fmtstr - 1, (char**)&fmtstr, 10);
+ } else {
+ reset_format(&fmt);
+ }
break;
}
}
if(fmt->flags & FMT_RALIGN) {
len = strlen(s);
- while(len-- < fmt->fwidth) {
+ while(len < fmt->fwidth--) {
wrchar(outbuf, fmt->fchar);
count++;
}
return count;
}
+static const char hexconv[] = "0123456789abcdef";
+
static int wrint(struct outbuf *outbuf, struct format *fmt, long val)
{
- return 0; /* TODO */
+ char buf[16], *ptr = buf + 15;
+ int neg = 0;
+
+ buf[15] = 0;
+
+ if(val < 0) {
+ neg = 1;
+ val = -val;
+ }
+
+ if(val == 0) {
+ *ptr++ = '0';
+ }
+
+ switch(fmt->base) {
+ case 16:
+ while(val) {
+ *--ptr = hexconv[val & 0xf];
+ val >>= 4;
+ }
+ break;
+
+ case 8:
+ while(val) {
+ *--ptr = '0' | (val & 7);
+ val >>= 3;
+ }
+ break;
+
+ default: /* assume 10 */
+ /*
+ while(val) {
+ *--ptr = '0' | (val % 10);
+ val /= 10;
+ }
+ */
+ break;
+ }
+
+ if(neg) {
+ *--ptr = '-';
+ }
+ fmt->flags |= FMT_RALIGN;
+ return wrstr(outbuf, fmt, ptr);
}
static int wruint(struct outbuf *outbuf, struct format *fmt, unsigned long val)
{
- return 0; /* TODO */
+ static const char hexconv[] = "0123456789abcdef";
+ char buf[16], *ptr = buf + 15;
+
+ buf[15] = 0;
+
+ if(val == 0) {
+ *ptr++ = '0';
+ }
+
+ switch(fmt->base) {
+ case 16:
+ while(val) {
+ *--ptr = hexconv[val & 0xf];
+ val >>= 4;
+ }
+ break;
+
+ case 8:
+ while(val) {
+ *--ptr = '0' | (val & 7);
+ val >>= 3;
+ }
+ break;
+
+ default: /* assume 10 */
+ /*
+ while(val) {
+ *--ptr = '0' | (val % 10);
+ val /= 10;
+ }
+ */
+ break;
+ }
+
+ fmt->flags |= FMT_RALIGN;
+ return wrstr(outbuf, fmt, ptr);
}
#ifndef STDIO_H_
#define STDIO_H_
+#include <stdarg.h>
#include "con.h"
#define putchar(c) con_putchar(c)
int printf(const char *fmt, ...);
+int vprintf(const char *fmt, va_list ap);
#endif /* STDIO_H_ */
--- /dev/null
+#include <stdlib.h>
+#include <ctype.h>
+#include <limits.h>
+
+int atoi(const char *str)
+{
+ return strtol(str, 0, 10);
+}
+
+long atol(const char *str)
+{
+ return strtol(str, 0, 10);
+}
+
+long strtol(const char *str, char **endp, int base)
+{
+ long acc = 0;
+ int sign = 1;
+ int valid = 0;
+ const char *start = str;
+
+ while(isspace(*str)) str++;
+
+ if(base == 0) {
+ if(str[0] == '0') {
+ if(str[1] == 'x' || str[1] == 'X') {
+ base = 16;
+ } else {
+ base = 8;
+ }
+ } else {
+ base = 10;
+ }
+ }
+
+ if(*str == '+') {
+ str++;
+ } else if(*str == '-') {
+ sign = -1;
+ str++;
+ }
+
+ while(*str) {
+ long val = LONG_MAX;
+ char c = tolower(*str);
+
+ if(isdigit(c)) {
+ val = (int)*str & 0xf;
+ } else if(c >= 'a' && c <= 'f') {
+ val = 10 + c - 'a';
+ } else {
+ break;
+ }
+ if(val >= base) {
+ break;
+ }
+ valid = 1;
+
+ acc = acc * base + val;
+ str++;
+ }
+
+ if(endp) {
+ *endp = (char*)(valid ? str : start);
+ }
+
+ return sign > 0 ? acc : -acc;
+}
+
--- /dev/null
+#ifndef STDLIB_H_
+#define STDLIB_H_
+
+#define abs(x) __builtin_abs(x)
+
+int atoi(const char *str);
+long atol(const char *str);
+long strtol(const char *str, char **endp, int base);
+
+#endif /* STDLIB_H_ */
con_init();
printf("eightysix kernel %s\n", VERSTR);
+ printf("foo: %04x\n", 0xabc);
init_intr();
}