about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2019-04-06 23:05:31 -0700
committerKartik Agaram <vc@akkartik.com>2019-04-06 23:05:31 -0700
commita6d6e8ce5cef1d52079b3cbbb3c4280afd7931b0 (patch)
treeda6ced74302399770ae497aefff1efe91946c914
parent9c0f9225fbb9f5a798bf52ae2995d802eee06228 (diff)
downloadmu-a6d6e8ce5cef1d52079b3cbbb3c4280afd7931b0.tar.gz
5062
-rw-r--r--subx/apps/assortbin20704 -> 20946 bytes
-rw-r--r--subx/apps/assort.subx851
2 files changed, 460 insertions, 391 deletions
diff --git a/subx/apps/assort b/subx/apps/assort
index a0252f2f..53141ed5 100644
--- a/subx/apps/assort
+++ b/subx/apps/assort
Binary files differdiff --git a/subx/apps/assort.subx b/subx/apps/assort.subx
index fbeb34b0..e7a0061e 100644
--- a/subx/apps/assort.subx
+++ b/subx/apps/assort.subx
@@ -27,7 +27,6 @@ Entry:  # run tests if necessary, convert stdin if not
 
     # for debugging: run a single test
 #?     e8/call test-get-or-insert-segment/disp32
-#?     e8/call test-slice-equal-with-null/disp32
 #?     8b/copy                         0/mod/indirect  5/rm32/.disp32            .             .           3/r32/EBX   Num-test-failures/disp32          # copy *Num-test-failures to EBX
 #?     eb/jump  $main:end/disp8
 
@@ -132,408 +131,408 @@ $convert:end:
     5d/pop-to-EBP
     c3/return
 
-test-convert:
-    # . prolog
-    55/push-EBP
-    89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
-    # setup
-    # . clear-stream(_test-input-stream)
-    # . . push args
-    68/push  _test-input-stream/imm32
-    # . . call
-    e8/call  clear-stream/disp32
-    # . . discard args
-    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
-    # . clear-stream(_test-input-buffered-file+4)
-    # . . push args
-    b8/copy-to-EAX  _test-input-buffered-file/imm32
-    05/add-to-EAX  4/imm32
-    50/push-EAX
-    # . . call
-    e8/call  clear-stream/disp32
-    # . . discard args
-    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
-    # . clear-stream(_test-output-stream)
-    # . . push args
-    68/push  _test-output-stream/imm32
-    # . . call
-    e8/call  clear-stream/disp32
-    # . . discard args
-    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
-    # . clear-stream(_test-output-buffered-file+4)
-    # . . push args
-    b8/copy-to-EAX  _test-output-buffered-file/imm32
-    05/add-to-EAX  4/imm32
-    50/push-EAX
-    # . . call
-    e8/call  clear-stream/disp32
-    # . . discard args
-    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
-    # initialize input (meta comments in parens)
-    #   # comment 1
-    #     # comment 2 indented
-    #   == code  (new segment)
-    #   # comment 3 inside a segment
-    #   1
-    #                         (empty line)
-    #   2 3 # comment 4 inline with other contents
-    #   == data  (new segment)
-    #   4 5/imm32
-    #   == code  (existing segment but non-contiguous with previous iteration)
-    #   6 7
-    #   8 9  (multiple lines)
-    #   == code  (existing segment contiguous with previous iteration)
-    #   10 11
-    # . write(_test-input-stream, "# comment 1")
-    # . . push args
-    68/push  "# comment 1"/imm32
-    68/push  _test-input-stream/imm32
-    # . . call
-    e8/call  write/disp32
-    # . . discard args
-    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-    # . write(_test-input-stream, "\n")
-    # . . push args
-    68/push  Newline/imm32
-    68/push  _test-000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
#include "common.h"
#include "screen.h"
#include "alloc.h"
#include "vmm.h"
#include "process.h"
#include "debugprint.h"

#define KMALLOC_MINSIZE		16

extern uint32 *gKernelPageDirectory;

static char *gKernelHeap = NULL;
static uint32 gKernelHeapUsed = 0;


void initializeKernelHeap() {
    gKernelHeap = (char *) KERN_HEAP_BEGIN;

    ksbrkPage(1);
}

void *ksbrkPage(int n) {
    struct MallocHeader *chunk;
    char *p_addr;
    int i;

    if ((gKernelHeap + (n * PAGESIZE_4M)) > (char *) KERN_HEAP_END) {
        //printkf("ERROR: ksbrk(): no virtual memory left for kernel heap !\n");
        return (char *) -1;
    }

    chunk = (struct MallocHeader *) gKernelHeap;

    for (i = 0; i < n; i++) {
        p_addr = getPageFrame4M();

        //printkf("DEBUG: ksbrkPage(): got 4M on physical %x\n", p_addr);

        if ((int)(p_addr) < 0) {
            PANIC("PANIC: ksbrkPage(): no free page frame available !");
            return (char *) -1;
        }

        addPageToPd(gKernelPageDirectory, gKernelHeap, p_addr, 0); //add PG_USER to allow user programs to read kernel heap

        gKernelHeap += PAGESIZE_4M;
    }

    chunk->size = PAGESIZE_4M * n;
    chunk->used = 0;

    return chunk;
}

void *kmalloc(uint32 size) {
    if (size==0)
        return 0;

    unsigned long realsize;
    struct MallocHeader *chunk, *other;

    if ((realsize = sizeof(struct MallocHeader) + size) < KMALLOC_MINSIZE) {
        realsize = KMALLOC_MINSIZE;
    }

    chunk = (struct MallocHeader *) KERN_HEAP_BEGIN;
    while (chunk->used || chunk->size < realsize) {
        if (chunk->size == 0) {
            printkf("\nPANIC: kmalloc(): corrupted chunk on %x with null size (heap %x) !\nSystem halted\n", chunk, gKernelHeap);

            PANIC("kmalloc()");

            return 0;
        }

        chunk = (struct MallocHeader *)((char *)chunk + chunk->size);

        if (chunk == (struct MallocHeader *) gKernelHeap) {
            if ((int)(ksbrkPage((realsize / PAGESIZE_4M) + 1)) < 0) {
                PANIC("kmalloc(): no memory left for kernel !\nSystem halted\n");

                return 0;
            }
        }
        else if (chunk > (struct MallocHeader *) gKernelHeap) {
            printkf("\nPANIC: kmalloc(): chunk on %x while heap limit is on %x !\nSystem halted\n", chunk, gKernelHeap);

            PANIC("kmalloc()");

            return 0;
        }
    }


    if (chunk->size - realsize < KMALLOC_MINSIZE) {
        chunk->used = 1;
    }
    else {
        other = (struct MallocHeader *)((char *) chunk + realsize);
        other->size = chunk->size - realsize;
        other->used = 0;

        chunk->size = realsize;
        chunk->used = 1;
    }

    gKernelHeapUsed += realsize;

    return (char *) chunk + sizeof(struct MallocHeader);
}

void kfree(void *v_addr) {
    if (v_addr==(void*)0)
        return;

    struct MallocHeader *chunk, *other;

    chunk = (struct MallocHeader *)((uint32)v_addr - sizeof(struct MallocHeader));
    chunk->used = 0;

    gKernelHeapUsed -= chunk->size;

    //Merge free block with next free block
    while ((other = (struct MallocHeader *)((char *)chunk + chunk->size))
           && other < (struct MallocHeader *)gKernelHeap
           && other->used == 0) {
        chunk->size += other->size;
    }
}

static void sbrkPage(Process* process, int pageCount) {
    if (pageCount > 0) {
        for (int i = 0; i < pageCount; ++i) {
            if ((process->heapNextUnallocatedPageBegin + PAGESIZE_4M) > (char*)USER_OFFSET_END) {
                return;
            }

            char * p_addr = getPageFrame4M();

            if ((int)(p_addr) < 0) {
                //PANIC("sbrkPage(): no free page frame available !");
                return;
            }

            addPageToPd(process->pd, process->heapNextUnallocatedPageBegin, p_addr, PG_USER);

            process->heapNextUnallocatedPageBegin += PAGESIZE_4M;
        }
    }
    else if (pageCount < 0) {
        pageCount *= -1;

        for (int i = 0; i < pageCount; ++i) {
            if (process->heapNextUnallocatedPageBegin - PAGESIZE_4M >= process->heapBegin) {
                process->heapNextUnallocatedPageBegin -= PAGESIZE_4M;

                //This also releases the page frame
                removePageFromPd(process->pd, process->heapNextUnallocatedPageBegin, TRUE);
            }
        }
    }
}

void initializeProcessHeap(Process* process) {
    process->heapBegin = (char*) USER_OFFSET;
    process->heapEnd = process->heapBegin;
    process->heapNextUnallocatedPageBegin = process->heapBegin;

    //Userland programs (their code, data,..) start from USER_OFFSET
    //So we should leave some space for them by moving heap pointer.
    //As a result userspace malloc functions start from a forward point (+ USER_EXE_IMAGE).

    sbrk(process, USER_EXE_IMAGE);
}

void *sbrk(Process* process, int nBytes) {
    printkf("sbrk:1: pid:%d nBytes:%d\n", process->pid, nBytes);

    char* previousBreak = process->heapEnd;
    printkf("before: %x\n", previousBreak);

    if (nBytes > 0) {
        int remainingInThePage = process->heapNextUnallocatedPageBegin - process->heapEnd;

        //printkf("sbrk:2: remainingInThePage:%d\n", remainingInThePage);

        if (nBytes > remainingInThePage) {
            int bytesNeededInNewPages = nBytes - remainingInThePage;
            int neededNewPageCount = (bytesNeededInNewPages / PAGESIZE_4M) + 1;

            //printkf("sbrk:3: neededNewPageCount:%d\n", neededNewPageCount);

            uint32 freePages = getFreePageCount();
            if ((uint32)neededNewPageCount + 1 > freePages) {
                return (void*)-1;
            }

            sbrkPage(process, neededNewPageCount);
        }
    }
    else if (nBytes < 0) {
        char* currentPageBegin = process->heapNextUnallocatedPageBegin - PAGESIZE_4M;

        int remainingInThePage = process->heapEnd - currentPageBegin;

        //printkf("sbrk:4: remainingInThePage:%d\n", remainingInThePage);

        if (-nBytes > remainingInThePage) {
            int bytesInPreviousPages = -nBytes - remainingInThePage;
            int neededNewPageCount = (bytesInPreviousPages / PAGESIZE_4M) + 1;

            //printkf("sbrk:5: neededNewPageCount:%d\n", neededNewPageCount);

            sbrkPage(process, -neededNewPageCount);
        }
    }

    process->heapEnd += nBytes;
    printkf("after: %x\n", process->heapEnd);

    return previousBreak;
}

uint32 getKernelHeapUsed() {
    return gKernelHeapUsed;
}
'>+#? #? # . . discard args +#? #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +#? #? # }}} +#? # . flush(_test-output-buffered-file) +#? # . . push args +#? 68/push _test-output-buffered-file/imm32 +#? # . . call +#? e8/call flush/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +#? # . check-next-stream-line-equal(_test-output-stream, "== code", msg) +#? # . . push args +#? 68/push "F - test-convert-code-and-data-segments/0"/imm32 +#? 68/push "== code"/imm32 +#? 68/push _test-output-stream/imm32 +#? # . . call +#? e8/call check-next-stream-line-equal/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +#? # . check-next-stream-line-equal(_test-output-stream, "1", msg) +#? # . . push args +#? 68/push "F - test-convert-code-and-data-segments/1"/imm32 +#? 68/push "e8 20 00 00 00 # e8/call 20/disp32"/imm32 +#? 68/push _test-output-stream/imm32 +#? # . . call +#? e8/call check-next-stream-line-equal/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +#? # . check-next-stream-line-equal(_test-output-stream, "2 3 # comment 4 inline with other contents", msg) +#? # . . push args +#? 68/push "F - test-convert-code-and-data-segments/2"/imm32 +#? 68/push "2 3 # comment 4 inline with other contents"/imm32 +#? 68/push _test-output-stream/imm32 +#? # . . call +#? e8/call check-next-stream-line-equal/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +#? # . check-next-stream-line-equal(_test-output-stream, "6 7", msg) +#? # . . push args +#? 68/push "F - test-convert-code-and-data-segments/3"/imm32 +#? 68/push "6 7"/imm32 +#? 68/push _test-output-stream/imm32 +#? # . . call +#? e8/call check-next-stream-line-equal/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +#? # . check-next-stream-line-equal(_test-output-stream, "8 9", msg) +#? # . . push args +#? 68/push "F - test-convert-code-and-data-segments/4"/imm32 +#? 68/push "8 9"/imm32 +#? 68/push _test-output-stream/imm32 +#? # . . call +#? e8/call check-next-stream-line-equal/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +#? # . check-next-stream-line-equal(_test-output-stream, "10 11", msg) +#? # . . push args +#? 68/push "F - test-convert-code-and-data-segments/5"/imm32 +#? 68/push "10 11"/imm32 +#? 68/push _test-output-stream/imm32 +#? # . . call +#? e8/call check-next-stream-line-equal/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +#? # . check-next-stream-line-equal(_test-output-stream, "== data", msg) +#? # . . push args +#? 68/push "F - test-convert-code-and-data-segments/6"/imm32 +#? 68/push "== data"/imm32 +#? 68/push _test-output-stream/imm32 +#? # . . call +#? e8/call check-next-stream-line-equal/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +#? # . check-next-stream-line-equal(_test-output-stream, "4 5/imm32", msg) +#? # . . push args +#? 68/push "F - test-convert-code-and-data-segments/4"/imm32 +#? 68/push "4 5/imm32"/imm32 +#? 68/push _test-output-stream/imm32 +#? # . . call +#? e8/call check-next-stream-line-equal/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +#? # . epilog +#? 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +#? 5d/pop-to-EBP +#? c3/return read-segments: # in : (address buffered-file), table : (address stream row) # pseudocode: @@ -886,6 +885,12 @@ $get-or-insert-segment:search-loop: e8/call slice-equal?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + # . if (EAX != 0) return EAX = *(curr+4) + 3d/compare-EAX-and 0/imm32 + 74/jump-if-equal $get-or-insert-segment:mismatch/disp8 + 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 4/disp8 . # copy *(ECX+4) to EAX + eb/jump $get-or-insert-segment:end/disp8 +$get-or-insert-segment:mismatch: # curr += 8 81 0/subop/add 3/mod/direct 1/rm32/ECX . . . . . 8/imm32 # add to ECX # loop @@ -956,19 +961,23 @@ test-get-or-insert-segment: 68/push 0/imm32/read 68/push 0/imm32/write 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX - # var s/EDX : (address slice) = "code" + # EDX : (address slice) = "code" 68/push _test-code-segment-end/imm32/end 68/push _test-code-segment/imm32/start 89/copy 3/mod/direct 2/rm32/EDX . . . 4/r32/ESP . . # copy ESP to EDX - # segment/EAX = get-or-insert-segment(table, s, 8) +$test-get-or-insert-segment:first-call: + # - start with an empty table, insert one segment, verify that it was inserted + # segment/EAX = get-or-insert-segment(table, "code" slice, 10) # . . push args - 68/push 8/imm32/segment-length + 68/push 0xa/imm32/segment-length 52/push-EDX 51/push-ECX # . . call e8/call get-or-insert-segment/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + # save segment + 50/push-EAX # if (segment != 0) goto next check 3d/compare-EAX-and 0/imm32 75/jump-if-not-equal $test-get-or-insert-segment:check1/disp8 @@ -991,12 +1000,12 @@ test-get-or-insert-segment: 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP # . increment Num-test-failures ff 0/subop/increment 0/mod/indirect 5/rm32/.disp32 . . . Num-test-failures/disp32 # increment *Num-test-failures - eb/jump $test-get-or-insert-segment:end/disp8 + e9/jump $test-get-or-insert-segment:end/disp32 $test-get-or-insert-segment:check1: - # check-ints-equal(segment->length, 8, msg) + # check-ints-equal(segment->length, 10, msg) # . . push args 68/push "F - test-get-or-insert-segment/1"/imm32 - 68/push 8/imm32/segment-length + 68/push 0xa/imm32/segment-length ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 8/disp8 . # push *(EAX+8) # . . call e8/call check-ints-equal/disp32 @@ -1032,15 +1041,71 @@ $test-get-or-insert-segment:check2: $test-get-or-insert-segment:check3: # stream/EAX = *(table->data+4) 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 0x10/disp8 . # copy *(ECX+16) to EAX - # check-ints-equal(stream->length, 8, msg) + # check-ints-equal(stream->length, 10, msg) # . . push args 68/push "F - test-get-or-insert-segment/4"/imm32 - 68/push 8/imm32/row-size + 68/push 0xa/imm32/segment-size ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 8/disp8 . # push *(EAX+8) # . . call e8/call check-ints-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +$test-get-or-insert-segment:second-call: + # - insert the same segment name again, verify that it was reused + # segment2/EAX = get-or-insert-segment(table, "code" slice, 8) + # . . push args + 68/push 8/imm32/segment-length + 52/push-EDX + 51/push-ECX + # . . call + e8/call get-or-insert-segment/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + # restore old segment1 + 5a/pop-to-EDX + # check-ints-equal(segment2/EAX, segment1/EDX, msg) + # . . push args + 68/push "F - test-get-or-insert-segment/5"/imm32 + 52/push-EDX + 50/push-EAX + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + # no change to table size + # . check-ints-equal(table->write, rowsize = 8, msg) + # . . push args + 68/push "F - test-get-or-insert-segment/6"/imm32 + 68/push 8/imm32/row-size + ff 6/subop/push 0/mod/indirect 1/rm32/ECX . . . . . . # push *ECX + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +$test-get-or-insert-segment:third-call: + # - insert a new segment name, verify that it was inserted + # EDX : (address slice) = "data" + c7 0/subop/copy 0/mod/indirect 2/rm32/EDX . . . . . _test-data-segment/imm32 # copy to *EDX + c7 0/subop/copy 1/mod/*+disp8 2/rm32/EDX . . . . 4/disp8 _test-data-segment-end/imm32 # copy to *(EDX+4) + # segment2/EAX = get-or-insert-segment(table, "data" slice, 8) + # . . push args + 68/push 8/imm32/segment-length + 52/push-EDX + 51/push-ECX + # . . call + e8/call get-or-insert-segment/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + # table gets a new row + # . check-ints-equal(table->write, 2 rows = 16, msg) + # . . push args + 68/push "F - test-get-or-insert-segment/7"/imm32 + 68/push 0x10/imm32/two-rows + ff 6/subop/push 0/mod/indirect 1/rm32/ECX . . . . . . # push *ECX + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP $test-get-or-insert-segment:end: # . epilog 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP @@ -1310,4 +1375,8 @@ _test-code-segment: 63/c 6f/o 64/d 65/e _test-code-segment-end: +_test-data-segment: + 64/d 61/a 74/t 61/a +_test-data-segment-end: + # . . vim:nowrap:textwidth=0