]> Zhao Yanbai Git Server - kernel.git/commitdiff
support read from console
authorAceVest <zhaoyanbai@126.com>
Sun, 20 Jul 2014 04:00:44 +0000 (12:00 +0800)
committerAceVest <zhaoyanbai@126.com>
Sun, 20 Jul 2014 04:00:44 +0000 (12:00 +0800)
15 files changed:
bin/shell.c
boot/multiboot.S
drivers/console.c
drivers/console.h
drivers/keyboard.c
drivers/vga.c
fs/ext2.c
fs/fs.c
fs/open.c
fs/read.c
fs/write.c
include/fs.h
include/syscall.h
kernel/syscall.c
lib/syscall.c

index 770862ef7b8f83a05839646241c66f9ec8b540d0..bca15398350cf8b7510e8a03f24299ad318857f4 100644 (file)
@@ -17,8 +17,12 @@ int systest();
 int main()
 {
 
+
     while(1)
     {
+    char buf[256];
+    read(0, buf, 256);
+    write(0, buf, 256);
 #if 0
     asm("movl $11, %eax;"   \
         "pushl $1f;"        \
index 14e8129f7186b38290b820cbe3904258d5d71212..18c4a320ce51e81e19a71491dd5078a26e8e8606 100644 (file)
@@ -112,7 +112,7 @@ main:
     movl    $init_pgd-KRNLADDR,%ebx
     movl    %ebx,%cr3
 
-    # enable PG
+    # enable PG WP
     movl    %cr0,%eax
     orl     $0x80010000,%eax
     movl    %eax,%cr0
@@ -123,29 +123,14 @@ main:
 
     ljmp    $0x08,$Label
 Label:
+
     call    check_kernel
     addl    $8,%esp
     movl    $root_task + TASK_SIZE, %esp
     call    setup_kernel
 
-
-#if 0
-    movl    $0x23, %eax
-    movw    %ax, %ds
-    movw    %ax, %es
-    movw    %ax, %fs
-    movw    %ax, %gs
-    pushl   %eax
-    pushl   $KRNLADDR
-    pushl   $0x282
-    pushl   $0x1B
-    movl    $root_task_entry, %eax
-    pushl   %eax
-    iret
-#else
     movl    $root_task_entry, %eax
     jmpl    *%eax
-#endif
 
 Die:
     jmp     Die    # Should never come to here.
index ebf1c9bb69afb137105bf376c0ec50a6e6a4f88c..045571dc16e1e5b9044e71fbc6125686aea4d2d7 100644 (file)
 
 #include<string.h>
 #include<console.h>
+#include<wait.h>
+
+cnsl_t cnsl;
+
+static bool empty(const cnsl_queue_t *q)
+{
+    return q->head == q->tail;
+}
+
+static bool full(const cnsl_queue_t *q)
+{
+    return (q->head + 1) % CNSL_QUEUE_SIZE == q->tail;
+}
+
+static void put(cnsl_queue_t *q, char c)
+{
+    if(!full(q))
+    {
+        q->data[q->head] = c;
+        q->head = (q->head + 1) % CNSL_QUEUE_SIZE;
+    }
+}
+
+static bool get(cnsl_queue_t *q, char *c)
+{
+    if(!empty(q))
+    {
+        *c = q->data[q->tail];
+        q->tail = (q->tail + 1) % CNSL_QUEUE_SIZE;
+        return true;
+    }
+
+    return false;
+}
+
+static void clear(cnsl_queue_t *q)
+{
+    q->head = q->tail = 0;
+}
+
+static void erase(cnsl_queue_t *q)
+{
+    if(empty(q))
+        return;
+
+    if(q->head == 0)
+        q->head = CNSL_QUEUE_SIZE -1;
+    else
+        q->head--;
+}
 
-cnsl_queue_t cnsl_rd_q;
-cnsl_queue_t cnsl_wr_q;
-cnsl_queue_t cnsl_sc_q;
 
 static void cnsl_queue_init(cnsl_queue_t *cq)
 {
     memset((void *)cq, 0, sizeof(*cq));
-
     cq->head = 0;
     cq->tail = 0;
     init_wait_queue(&cq->wait);
+}
 
-    //cq->data = kmalloc(CNSL_QUEUE_SIZE, 0);
+wait_queue_head_t rdwq;
 
-    printk("console queue data addr %08x\n", cq->data);
+void cnsl_init()
+{
+    cnsl_queue_init(&cnsl.rd_q);
+    cnsl_queue_init(&cnsl.wr_q);
+    cnsl_queue_init(&cnsl.sc_q);
+    init_wait_queue(&rdwq);
 }
 
-void cnsl_init()
+
+int cnsl_kbd_write(char ch)
+{
+    if(ch == '\b')
+    {
+        if(!empty(&cnsl.wr_q))
+            vga_putc(0, '\b', 0x2);
+        erase(&cnsl.wr_q);
+        erase(&cnsl.sc_q);
+    }
+    else
+    {
+        put(&cnsl.wr_q, ch);
+        put(&cnsl.sc_q, ch);
+        vga_putc(0, ch, 0x2);
+    }
+
+
+    if(ch == '\n')
+    {
+        clear(&cnsl.wr_q);
+        while(get(&cnsl.sc_q, &ch))
+            put(&cnsl.rd_q, ch);
+        wake_up(&rdwq);
+    }
+
+#if 0
+    printl(23, "rd: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
+    cnsl.rd_q.data[0],
+    cnsl.rd_q.data[1],
+    cnsl.rd_q.data[2],
+    cnsl.rd_q.data[3],
+    cnsl.rd_q.data[4],
+    cnsl.rd_q.data[5],
+    cnsl.rd_q.data[6],
+    cnsl.rd_q.data[7],
+    cnsl.rd_q.data[8],
+    cnsl.rd_q.data[9]);
+#endif
+}
+
+
+int cnsl_read(char *buf, size_t count)
 {
-    cnsl_queue_init(&cnsl_rd_q);
-    cnsl_queue_init(&cnsl_wr_q);
-    cnsl_queue_init(&cnsl_sc_q);
+    unsigned long flags;
+
+    assert(count > 0);
+    int cnt = 0;
+    for(cnt=0; cnt<count; )
+    {
+        char ch;
+        task_union * task = current;
+        DECLARE_WAIT_QUEUE(wait, task);
+        add_wait_queue(&rdwq, &wait);
+
+        while(true)
+        {
+            task->state = TASK_WAIT;
+            irq_save(flags);
+            bool r = get(&cnsl.rd_q, &ch);
+            irq_restore(flags);
+
+            if(r)
+            {
+                buf[cnt++] = ch;
+
+                task->state = TASK_RUNNING;
+                del_wait_queue(&rdwq, &wait);
+
+                if(ch == '\n')
+                    goto end;
+
+                break;
+            }
+
+            schedule();
+        }
+
+    }
+
+end:
+    buf[cnt] = 0;
+    return cnt;
 }
+
+chrdev_t cnsl_chrdev = {
+    .read = cnsl_read
+};
index a18325dfbc3aa85097ff20b64f18371f89a75f9f..26ba40c44bc6c2daa4f219f3ec1a9aa17e27a017 100644 (file)
@@ -11,7 +11,7 @@
 
 #include<wait.h>
 
-#define CNSL_QUEUE_SIZE 1024
+#define CNSL_QUEUE_SIZE 10
 
 typedef struct cnsl_queue
 {
@@ -21,6 +21,11 @@ typedef struct cnsl_queue
     char data[CNSL_QUEUE_SIZE];
 } cnsl_queue_t;
 
-extern cnsl_queue_t cnsl_rd_q;
-extern cnsl_queue_t cnsl_wr_q;
-extern cnsl_queue_t cnsl_sc_q;
+typedef struct cnsl
+{
+    cnsl_queue_t rd_q;
+    cnsl_queue_t wr_q;
+    cnsl_queue_t sc_q;
+} cnsl_t;
+
+int cnsl_kbd_write(char c);
index 1998cb35a56fd322b489289e2ef129867349fdcf..3d790f9329c801acf3ba4f4992674b7708126f92 100644 (file)
@@ -29,37 +29,56 @@ void vga_dbg_toggle();
 int debug_wait_queue_put(unsigned int v);
 void ide_dma_pci_lba48();
 
-unsigned long kbd_cnt = 0;
+
+void kbd_debug(unsigned char scan_code);
+
+char kbd_char_tbl[]={0,0,
+'1','2','3','4','5','6','7','8','9','0','-','=','\b',0,
+'q','w','e','r','t','y','u','i','o','p','[',']','\n',0,
+'a','s','d','f','g','h','j','k','l',';','\'','`',0,'\\',
+'z','x','c','v','b','n','m',',','.','/',0,0,0,' ',
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+};
+
 
 void kbd_handler(unsigned int irq, pt_regs_t * regs, void *dev_id)
 {
     unsigned char scan_code;
-    scan_code = inb(0x60);
 
-    printl(MPL_KEYBOARD, "keyboard:%d scan code %02x", kbd_cnt++, scan_code);
-
-    if(scan_code == 0x01) // Esc
-        reboot();
-    
-    printk("[%02x]", scan_code);
+    scan_code = inb(0x60);
 
-    if(scan_code == 0x09)   // 8
-        ide_dma_pci_lba48();
+    kbd_debug(scan_code);
 
-    if(scan_code == 0x0B)   // 0
+    if(0x80 & scan_code)   // break code
     {
-        asm("cli;");
-        while(1);
+        return ;
     }
 
-    if(scan_code == 0x13)   // r
-        ide_debug();
+    unsigned int inx = scan_code & 0xFF;
+    char ch = kbd_char_tbl[inx];
+    cnsl_kbd_write(ch);
+}
+
+void kbd_debug(unsigned char scan_code)
+{
+    static unsigned long kbd_cnt = 0;
+    printl(MPL_KEYBOARD, "keyboard:%d scan code %02x", kbd_cnt++, scan_code);
 
-    if(scan_code == 0x1F)   // s
-        ide_status();
+    if(scan_code == 0x01) // Esc
+        reboot();
+
+    printd("[%02x]", scan_code);
 
-    if(scan_code == 0x14)   // t
-        debug_sched();
 
     if(scan_code == 0x3B)   // F1
         vga_switch(0);
@@ -79,22 +98,18 @@ void kbd_handler(unsigned int irq, pt_regs_t * regs, void *dev_id)
     if(scan_code == 0x42)   // F8
         debug_wait_queue_put(7);
 
-    if(scan_code == 0x43);  // F9
-    if(scan_code == 0x44);  // F10
-    if(scan_code == 0x57);  // F11
+    if(scan_code == 0x43)   // F9
+        ide_dma_pci_lba48();
+    if(scan_code == 0x44)   // F10
+        ide_debug();
+    if(scan_code == 0x57)   // F11
+    {
+        asm("cli;");
+        while(1);
+    }
     if(scan_code == 0x58)   // F12
         vga_dbg_toggle();
 
-#if 1
-    cnsl_rd_q.data[0] = (char) scan_code;
-    wake_up(&cnsl_rd_q.wait);
-#endif
-}
-
-int sysc_read_kbd()
-{
-    DECLARE_WAIT_QUEUE(wait, current);
-    add_wait_queue(&cnsl_rd_q.wait, &wait);
 
-    return 0;
+    //ide_status();
 }
index 03ad7540502a5923a4477d700a14911e6044595e..c6fc7b67f09a49c8fc75dbce85a5fe1e035f9299 100644 (file)
@@ -127,11 +127,14 @@ void vga_scroll_up(vga_screen_t *s)
 
 
 
-void vga_putc(vga_screen_t *s, const unsigned char c, const unsigned char color)
+void vga_putc(unsigned int nr, unsigned char c, const unsigned char color)
 {
+    vga_screen_t *s = vga_screen + nr;
+
     vga_char_t *pv = s->base;
 
     bool need_clear = true;
+    bool need_forward = true;
     unsigned int old_offset = s->offset;
     
     switch(c)
@@ -145,10 +148,15 @@ void vga_putc(vga_screen_t *s, const unsigned char c, const unsigned char color)
     case '\t':
         set_offset(s, (xpos(s) + 1 + TAB_MASK) & ~TAB_MASK, ypos(s));
         break;
+    case '\b':
+        set_offset(s, xpos(s) - 1, ypos(s));
+        c = ' ';
+        need_forward = false;
+        // NO BREAK
     default:
         need_clear = false;
         pv[s->offset] = vga_char(c, color);
-        set_offset(s, xpos(s)+1, ypos(s));
+        set_offset(s, xpos(s)+(need_forward?1 : 0), ypos(s));
         break;
     }
 
@@ -170,11 +178,10 @@ void vga_puts(unsigned int nr, const char *buf, unsigned char color)
         return ;
 
     char *p = (char *) buf;
-    vga_screen_t *s = vga_screen + nr;
 
     while(*p)
     {
-        vga_putc(s, *p, color);
+        vga_putc(nr, *p, color);
         p++;
     }
 }
index 346f012a1117fcda48f00049157437f66ae6adca..cd8731efd65056a87fc9018adb137a532172df91 100644 (file)
--- a/fs/ext2.c
+++ b/fs/ext2.c
@@ -255,12 +255,3 @@ void ext2_setup_fs()
 
 
 
-void setup_fs()
-{
-    ext2_setup_fs();
-}
-
-unsigned int namei(const char *path)
-{
-    return ext2_search_inpath(path);
-}
diff --git a/fs/fs.c b/fs/fs.c
index 5b03ed271f50885524b681688259fe5d0e1f0134..06879b3e77500999f2c1b5b1e57eddd247740756 100644 (file)
--- a/fs/fs.c
+++ b/fs/fs.c
 #include <io.h>
 #include <printk.h>
 #include <system.h>
-#define SECT_SIZE    512
-
-#if 0
-File file_table[NR_FILES] __attribute__ ((__aligned__(PAGE_SIZE))) = {{0,},};
-extern unsigned int ext2_start_sect;
-void hd_read(dev_t dev, u64 sect_nr, void *buf, u32 count);
-void init_file_table();
-void save_boot_part(int n, pPartition p, u32 base_sect);
-void read_ext_part(u32 base, u32 offset);
-void setup_fs()
-{
-    int i, minor;
-    pPartition p;
-    unsigned char *buf;
-
-
-    init_file_table();
-
-
-    minor = DEV_MINOR(ROOT_DEV);
-    buf = (unsigned char *) get_virt_pages(1);
-    hd_read(ROOT_DEV, 0, buf, SECT_SIZE);
-
-
-    for(i=0; i<4; i++)
-    {
-        p = (pPartition)(buf+PARTS_POS) + i;
-        if(p->Type == 0)
-            continue;
-
-        //save_boot_part(i+1, p, p->AbsoluteSectNo);
-        save_boot_part(i, p, p->AbsoluteSectNo);
-
-        printk("hd%d\tbase: %08x size: %08x type:%02x",
-            i, p->AbsoluteSectNo, p->PartitionSize, p->Type);
-        if(p->Type == 0x05)
-        {
-            printk("\tExtend\n");
-            //read_ext_part(p->AbsoluteSectNo, 0);
-        }
-        else
-            printk("\n");
-    }
-
-
-    printk("ext2_start_sect: %x\n", ext2_start_sect);
 
+extern chrdev_t cnsl_chrdev;
 
-    return ;
-}
-
-void init_file_table()
-{
-    int i;
+chrdev_t *chrdev[CHRDEV_SIZE] = {
+    &cnsl_chrdev
+};
 
-    for(i=0; i<NR_FILES; i++)
-    {
-        file_table[i].count    = 0;
-        file_table[i].ino_nr    = 0;
-        file_table[i].inode    = NULL;
-    }
-}
+void ext2_setup_fs();
+unsigned int ext2_search_inpath(const char *path);
 
-void save_boot_part(int n, pPartition p, u32 base_sect)
+void setup_fs()
 {
-    if(p->Type == 0x05)
-        panic("partition should not be extended");
-
-    int minor = DEV_MINOR(ROOT_DEV);
-
-    if(minor-1 == n)
-        ext2_start_sect = base_sect;
+    ext2_setup_fs();
 }
 
-static unsigned int ext_part = 5;
-void read_ext_part(u32 base, u32 offset)
+unsigned int namei(const char *path)
 {
-    unsigned char *buf;
-    pPartition p;
-    buf = get_virt_pages(1);
-
-    //printk("^^^^^^^^^:%08x\n", base+offset);
-    hd_read(ROOT_DEV, base+offset, buf, SECT_SIZE);
-    int i;
-
-    for(i=0; i<4; i++)
-    {
-        p = (pPartition)(buf+PARTS_POS) + i;
-        if(p->Type == 0x00)
-            continue;
-
-        if(p->Type != 0x05)
-        {
-
-            //save_boot_part(ext_part, p, 0);
-            printk("  hd%d\tbase: %08x size: %08x type:%02x\n",
-                ext_part++, base+p->AbsoluteSectNo,
-                p->PartitionSize, p->Type);
-        }
-        else
-        {
-            read_ext_part(base, p->AbsoluteSectNo);
-        }
-    }
-
-    printk("\n");
-
-    free_virt_pages(buf);
+    return ext2_search_inpath(path);
 }
-#endif
index 73fb164f1a25439a93ce5ae831d19a76cc3485a2..a7dfbe929846c5add9504623fd43349dffeec167 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
 
 int sysc_open(const char *path, int flags, mode_t mode)
 {
-#if 0
-    assert(mode == 0); // unsupport now...
-    assert(flags == O_RDONLY);    // support only...
-
-    int ino_nr, i, fd;
-    pInode inode;
-
-    /* 先获取文件的i节点号 */
-    ino_nr = get_inode_nr(path);
-    if(ino_nr == EXT2_BAD_INO)
-        return -ENOENT;
-
-    /* 找到空的文件描述符句柄 */
-    for(i=0; i<NR_OPENS; i++)
-        if(current->fps[i] == NULL)
-            break;
-    if(i == NR_OPENS)
-        return -EMFILE;
-    fd = i;
-
-
-    /* 找到空的描述符或已经打开的描述符 */
-    int empt_nr, fdt_nr;
-    pFile pf;
-    empt_nr = fdt_nr = -1;
-    for(i=0, pf=file_table; i<NR_FILES; i++, pf++)
-    {
-        if(pf->ino_nr == ino_nr)
-        {
-            fdt_nr = i;
-            break;
-        }
-        else if(pf->ino_nr == 0)
-        {
-            empt_nr = i;
-        }
-    }
-
-    if(fdt_nr != -1)
-    {
-        pf = file_table+fdt_nr;
-    }
-    else if(empt_nr != -1)
-    {
-        pf = file_table+empt_nr;
-    }
-    else
-    {
-        return -EMFILE;
-    }
-
-
-    if(pf->ino_nr == ino_nr)
-    {
-        pf->count++;
-        current->fps[fd] = pf;
-        return fd;
-    }
-
-    inode = find_empty_inode();
-    if(inode == NULL)
-        return -ENOMEM;
-
-    get_inode(ino_nr, inode);
-    
-    pf->count = 1;
-    pf->ino_nr = ino_nr;
-    pf->inode = inode;
-    current->fps[fd] = pf;
-
-    return fd;
-#endif
+    return 0;
 }
index 21db99045d123b2d09b1e7e26822a58fce8403e3..7d7307b40bc5545e29e4245cfc43d4ad180b4c0b 100644 (file)
--- a/fs/read.c
+++ b/fs/read.c
 
 int sysc_read(int fd, void *buf, size_t count)
 {
-#if 0
     if(fd<0 || fd>=NR_OPENS)
         return -EBADF;
 
-    pFile fp = current->fps[fd];
-    assert(fp != NULL);
-
-    pInode    inode = fp->inode;
-    assert(inode->i_size > 0);    // 目前只能这样支持
-    if(inode->i_size > MAX_SUPT_FILE_SIZE)
-        return -EFAULT;
-
-
-    return read_file(inode, buf, count);
-#endif
+    // only support char device
+    // only support read from console.
+    // ignore fd
+    chrdev_t *p = chrdev[CHRDEV_CNSL];
+    return p->read(buf, count);
 }
index cebc502208618c0686ce59d4ecc88a6a0ff14c84..efb85e7586ae0e1a71b01da37517a2453f3de6d7 100644 (file)
@@ -15,7 +15,7 @@
  */
 
 
-extern void     vga_puts(const char *buf, unsigned char color);
+extern void vga_puts(unsigned int nr, const char *buf, unsigned char color);
 int sysc_write(int fd, const char *buf, unsigned long size)
 {
     if(size < 0) return -1;
@@ -23,7 +23,7 @@ int sysc_write(int fd, const char *buf, unsigned long size)
     switch(fd)
     {
     case 0:
-        vga_puts(buf, 0xF);
+        vga_puts(0, buf, 0xF);
         break;
     default:
         return -1;
index 43337f290004b105b190fb3c1a93d6383b44ba3b..daf312ecce10419abd74d877e736aa4459e1885c 100644 (file)
 unsigned int namei(const char *path);
 
 #define MAX_SUPT_FILE_SIZE    (EXT2_IND_BLOCK*EXT2_BLOCK_SIZE)
+
+
+
+typedef struct chrdev
+{
+    int (*read)(char *buf, size_t count);
+} chrdev_t;
+
+enum {
+    CHRDEV_CNSL,
+    CHRDEV_SIZE
+};
+
+extern chrdev_t *chrdev[];
+
+typedef struct 
+{
+    
+} file_t;
+
+
+
 #if 0
 #define NR_FILES    (PAGE_SIZE/sizeof(File))
 #define NR_INODES    (2*NR_FILES)
index 64cb5d0b0c70fc8d350b32f7c5172da0118f5202..3ea6fcfbbf75fd83fb4c54f4056ee5876c7b944c 100644 (file)
@@ -41,7 +41,6 @@ int _syscall5(int nr, unsigned long a, unsigned long b, unsigned long c, unsigne
 enum
 {
     SYSC_WRITE,
-    SYSC_READ_KBD,
     SYSC_REBOOT,
     SYSC_FORK,
     SYSC_CLONE,
index a87f14c7064fdbb78d03d7e9dbb31e72e46837d3..91084b443fa5c4096132bf72b97148bbc9ba492e 100644 (file)
@@ -67,9 +67,7 @@ void    init_sysc_handler_table()
         sysc_handler_table[nr] = (unsigned long) sym;    \
     }while(0);
 
-    /* 有没有一种宏定义可以把大写直接转成小写? */
     _sysc_(SYSC_WRITE,       sysc_write);
-    _sysc_(SYSC_READ_KBD,    sysc_read_kbd);
     _sysc_(SYSC_REBOOT,      sysc_reboot);
     _sysc_(SYSC_FORK,        sysc_fork);
     _sysc_(SYSC_EXEC,        sysc_exec);
@@ -81,7 +79,7 @@ void    init_sysc_handler_table()
     _sysc_(SYSC_TEST,        sysc_test);
 }
 
-int    sysc_bad_syscnr()
+int sysc_bad_syscnr()
 {
     int sysc_nr;
     asm("":"=a"(sysc_nr));
index b9dc9e210e95d7b7ae47851e844f5b6bb3b4c165..d781aa99132be7e79071df09e9bd930ec59f9b91 100644 (file)
@@ -9,7 +9,6 @@
 
 
 #define SYSENTER_ASM            \
-        "movl $11,%%eax;"     \
         "pushl  $1f;"           \
         "pushl    %%ecx;"       \
         "pushl    %%edx;"       \