{"id":289,"date":"2011-12-22T13:04:05","date_gmt":"2011-12-22T19:04:05","guid":{"rendered":"http:\/\/tommysprinkle.com\/txxos\/?p=289"},"modified":"2021-04-17T18:24:59","modified_gmt":"2021-04-17T23:24:59","slug":"copy-to-high-memory","status":"publish","type":"post","link":"https:\/\/tommysprinkle.com\/txxos\/?p=289","title":{"rendered":"Copy To High Memory"},"content":{"rendered":"<p>Once we have determined the highest memory address available we can copy our loader code into high memory.<\/p>\n<pre>*\r\n* RELOCATE LOADER TO HIGH MEMORY\r\n*\r\n         LA    R2,LOADER          ADDRESS OF ROUTINE TO RELOCATE\r\n         LA    R3,LOADERLN        LENGTH OF ROUTINE TO RELOCATE\r\n         LR    R4,R9              HIGH MEM ADDRESS\r\n         SR    R4,R3              BACK UP LENGTH OF CODE\r\n         S     R4,M32K            LEAVE A 32K BUFFER\r\n         N     R4,MASK            START ON A CLEAN BOUNDRY\r\n         LR    R8,R4              SAVE START ADDRESS IN R8\r\n*\r\n         LA    R1,256             MAX MVC LENGTH<\/pre>\n<p>We start by loading the address of our loader routine into Register 2 and the length of the routine into Register 3. \u00a0We copy the highest memory address into Register 4 and then subtract the length of the code. \u00a0Because we use the storage immediately following our \u00a0loader code for the disk I\/O buffer we subtract out another 32k leaving more then plenty of room. \u00a0Finally we use a logical AND to start loading on an even boundary (we at least have to start on a double word boundary to avoid alignment errors). \u00a0Finally save the beginning load address into Register 8 (so we can branch to it when relocation is completed) and we set Register 1 to 256 or the maximum length for a MVC instruction.<\/p>\n<pre>MCOPY    DS    0H\r\n         CR    R3,R1              CHECK FOR MAX LEGNTH\r\n         BL    MCOPY010           NO - SHORT MOVE\r\n*\r\n         MVC   0(256,R4),0(R2)    MOVE 256 BYTES\r\n         AR    R2,R1              NEXT AREA\r\n         AR    R4,R1                       TO MOVE\r\n         SR    R3,R1              ADJUST LENGTH\r\n         B     MCOPY              LOOP BACK\r\n*\r\n*\r\nMCOPY010 DS    0H\r\n         LTR   R3,R3              CHECK FOR ANYTHING TO MOVE\r\n         BZ    MCOPY020           ALL DONE\r\n*\r\n         BCTR  R3,0               SUBTRACT ONE FOR EXECUTE\r\n         EX    R3,MVC             COPY LAST OF DATA\r\n*\r\nMCOPY020 DS    0H\r\n         LR    R15,R8             ADDRESS OF RELOCATED LOADER\r\n         BR    R15                BRANCH TO IT<\/pre>\n<p>The copy routine is pretty straight forward. \u00a0First we check to see if we have at least 256 bytes left to copy. \u00a0If not we branch to MCOPY010 to handle a short move. \u00a0 We then copy 256 bytes of data, increment our source and target pointers, and then decrement the remaining length.<\/p>\n<p>When we finally have less than 256 bytes to copy we must first check that there is at least one byte to move. \u00a0We then subtract one from the length and use an Executed Move Characters to copy the remainder of the data.<\/p>\n<p>Finally we branch to the routine we just moved.<\/p>\n<pre> *\r\n M32K     DC    A(1024*32)         * CONSTANT 32K\r\n MASK     DC    A(X'00FFF000')     * BOUNDARY MASK\r\n MVC      MVC   0(1,R4),0(R2)      * EXECUTED INSTRUCTION<\/pre>\n<p>Finally we define our constants.<\/p>\n<p>It is important to point out that we don&#8217;t do any relocation of pointers for the routine we copy to high memory. \u00a0It is important that when we write the code for our loader we avoid using any relocatable constants. \u00a0For example if we used something like:<\/p>\n<pre>PTR      DC    A(BUFFER)<\/pre>\n<p>we would generate a relocatable constant. \u00a0Once we copied the routine to high memory the address pointer would still refer to the original location in low memory. \u00a0Instead we need to calculate the pointer address at run time and instead use something like:<\/p>\n<pre>         LA    R2,BUFFER\r\n         ST    R2,PTR \u00a0\r\nPTR \u00a0    DC \u00a0  A(0)<\/pre>\n<p>This will give us the proper value in our pointer.<\/p>\n<p>The Assembler output will help \u00a0us determine if we have used any relocatable addresses in our program. \u00a0Near the end of the assembly listing we find the Relocation\u00a0Dictionary. \u00a0It provides us with a list of all the relocatable symbols in the program and the address where it is located. \u00a0If we find any relocatable symbols that are contained within our code to be relocated we can then go back to the source and correct the problem.<\/p>\n<pre>                                     RELOCATION DICTIONARY\r\n POS.ID   REL.ID   FLAGS   ADDRESS\r\n  0001     0001      08     000005\r\n  0001     0001      08     000D81\r\n  0001     0001      08     000D89\r\n  0001     0001      08     000D91\r\n  0001     0001      08     000D99<\/pre>\n<p>[Next &#8211; <a title=\"Nucleus Load Module Loader\" href=\"http:\/\/tommysprinkle.com\/txxos\/?p=291\">Nucleus Load Module Loader<\/a>]<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Once we have determined the highest memory address available we can copy our loader code into high memory. * * RELOCATE LOADER TO HIGH MEMORY * LA R2,LOADER ADDRESS OF ROUTINE TO RELOCATE LA R3,LOADERLN LENGTH OF ROUTINE TO RELOCATE &hellip; <a href=\"https:\/\/tommysprinkle.com\/txxos\/?p=289\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"template-page-builder-no-sidebar.php","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[1],"tags":[],"class_list":["post-289","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p1CPQT-4F","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/tommysprinkle.com\/txxos\/index.php?rest_route=\/wp\/v2\/posts\/289","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tommysprinkle.com\/txxos\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tommysprinkle.com\/txxos\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tommysprinkle.com\/txxos\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tommysprinkle.com\/txxos\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=289"}],"version-history":[{"count":3,"href":"https:\/\/tommysprinkle.com\/txxos\/index.php?rest_route=\/wp\/v2\/posts\/289\/revisions"}],"predecessor-version":[{"id":493,"href":"https:\/\/tommysprinkle.com\/txxos\/index.php?rest_route=\/wp\/v2\/posts\/289\/revisions\/493"}],"wp:attachment":[{"href":"https:\/\/tommysprinkle.com\/txxos\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=289"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tommysprinkle.com\/txxos\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=289"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tommysprinkle.com\/txxos\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=289"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}