操作系统学习 (二)用户程序的加载和运行


一个编译好的用户程序,放到磁盘中,是如何被加载到内存并运行的呢。

大概的流程是加载器先把磁盘中的应用程序加载到内存并把执行权移交给应用程序。分为以下几个步骤:

 

  1. 从磁盘读取应用程序并装入内存(加载器的作用1)。

  2. 应用程序被装入内存后需要加载器对内存中的应用程序部分地址进行重定位(加载器的作用2)。

  3. 加载器将执行权移交应用程序(加载器的作用3)。

     

      前面说过,部分外围设备将自己的地址空间直接映射到内存地址空间中,这样CPU可以直接访问该内存空间来操作外围设备,譬如显卡。但这里磁盘空间是独立编址的,我们必须通过IO来访问(即端口访问),为什么CPU能直接进行端口访问磁盘,因为CPU和外围设备(这里是磁盘)之间直接进行电路焊接的。主要通过指令OUT来设置/写磁盘相关端口参数,通过指令IN来读磁盘数据。

      既然加载器通过IN/OUT方式读写磁盘数据到内存中,必须要知道磁盘数据大小即应用程序大小、放在磁盘什么位置(哪个扇区)。因此加载器和应用程序之间有个协议约定,即程序头,该程序头结构中主要信息包括程序总长度、用户程序入口点、段重定位表项个数、段重定位表。该程序头结构在编译器编译程序时自动生成。

     

      程序头结构如下(举例):

     

    SECTION header vstart=0                     ;定义用户程序头部段 ,从0地址开始

        program_length  dd program_end          ;程序总长度[0x00]

        

        ;用户程序入口点

        code_entry      dw start                ;偏移地址[0x04]

                        dd section.code_1.start ;段地址[0x06]

        

        realloc_tbl_len dw (header_end-code_1_segment)/4;段重定位表项个数[0x0a]

        ;段重定位表           

        code_1_segment  dd section.code_1.start ;[0x0c]

        code_2_segment  dd section.code_2.start ;[0x10]

        data_1_segment  dd section.data_1.start ;[0x14]

        data_2_segment  dd section.data_2.start ;[0x18]

        stack_segment   dd section.stack.start  ;[0x1c]

        

    header_end:    

     

    加载器在加载程序时,先获取程序头中内容,并从应用程序所在磁盘逻辑扇区号中开始加载到指定内存地址中,因为磁盘每个扇区只有512字节,所以加载器都以512字节为一个加载块加载到指定的内存地址中,没存地址中的每个加载块之间有个地址间隔(80860x20)。

     

    加载器加载完应用程序后,需要进行地址重定位。因为定义的各种段地址起始地址都是从0开始的,加载到内存中是存放到指定内存地址中去的。

     

    如下所示:

    SECTION header vstart=0                     ;定义用户程序头部段

        program_length  dd program_end          ;程序总长度[0x00]

        

        ;用户程序入口点

        code_entry      dw start                ;偏移地址[0x04]

                        dd section.code_1.start ;段地址[0x06]

        

        realloc_tbl_len dw (header_end-code_1_segment)/4

                                                ;段重定位表项个数[0x0a]

        

        ;段重定位表           

        code_1_segment  dd section.code_1.start ;[0x0c]

        code_2_segment  dd section.code_2.start ;[0x10]

        data_1_segment  dd section.data_1.start ;[0x14]

        data_2_segment  dd section.data_2.start ;[0x18]

        stack_segment   dd section.stack.start  ;[0x1c]

        

        header_end:  

     

    由于该段vstart = 0,所以编译后起始地址为0.其他段定义雷同。这就需要进行段地址重定位。

    段地址重定位完成后,使用jump far/near(或省略near即为near近调整) 重定位表中的应用程序的入口地址(即将CPU控制权交给应用程序)。

     

    应用程序从入口地址执行时,即需要根据不同段地址配置不同段寄存器,即使用堆栈段地址配置SS寄存器,使用堆栈段end地址赋值SP寄存器。使用数据段地址赋值DS寄存器,如果用户定义了多个数据段怎么办?在访问数据段1过程中需要访问另一个数据段2时,先将进行中的数据段(假设为数据段1 push入栈,然后重定位表中的数据段2所在的地址重新赋值给DS,然后再访问DS,访问结束后,再将原有入栈的数据段出栈恢复到DS中(或另一种方法,再次访问重定位表数据段1的地址,重新设置DS寄存器即可)。CS寄存器的设置是在加载器中进行的,试想一下,加入加载器不进行CS寄存器设置,它如何执行应用程序中的入口地址呢。


             ;代码清单8-1//加载器源代码
             ;文件名:c08_mbr.asm
             ;文件说明:硬盘主引导扇区代码(加载程序) 
             ;创建日期:2011-5-5 18:17
             
             app_lba_start equ 100           ;声明常数(用户程序起始逻辑扇区号)
                                             ;常数的声明不会占用汇编地址
                                        
    SECTION mbr align=16 vstart=0x7c00                                     
    
             ;设置堆栈段和栈指针 
             mov ax,0      
             mov ss,ax
             mov sp,ax
          
             mov ax,[cs:phy_base]            ;计算用于加载用户程序的逻辑段地址 
             mov dx,[cs:phy_base+0x02]
             mov bx,16        
             div bx            
             mov ds,ax                       ;令DS和ES指向该段以进行操作
             mov es,ax                        
        
             ;以下读取程序的起始部分 
             xor di,di
             mov si,app_lba_start            ;程序在硬盘上的起始逻辑扇区号 
             xor bx,bx                       ;加载到DS:0x0000处 
             call read_hard_disk_0
          
             ;以下判断整个程序有多大
             mov dx,[2]                      ;曾经把dx写成了ds,花了二十分钟排错 
             mov ax,[0]
             mov bx,512                      ;512字节每扇区
             div bx
             cmp dx,0
             jnz @1                          ;未除尽,因此结果比实际扇区数少1 
             dec ax                          ;已经读了一个扇区,扇区总数减1 
       @1:
             cmp ax,0                        ;考虑实际长度小于等于512个字节的情况 
             jz direct
             
             ;读取剩余的扇区
             push ds                         ;以下要用到并改变DS寄存器 
    
             mov cx,ax                       ;循环次数(剩余扇区数)
       @2:
             mov ax,ds
             add ax,0x20                     ;得到下一个以512字节为边界的段地址
             mov ds,ax  
                                  
             xor bx,bx                       ;每次读时,偏移地址始终为0x0000 
             inc si                          ;下一个逻辑扇区 
             call read_hard_disk_0
             loop @2                         ;循环读,直到读完整个功能程序 
    
             pop ds                          ;恢复数据段基址到用户程序头部段 
          
             ;计算入口点代码段基址 
       direct:
             mov dx,[0x08]
             mov ax,[0x06]
             call calc_segment_base
             mov [0x06],ax                   ;回填修正后的入口点代码段基址 
          
             ;开始处理段重定位表
             mov cx,[0x0a]                   ;需要重定位的项目数量
             mov bx,0x0c                     ;重定位表首地址
              
     realloc:
             mov dx,[bx+0x02]                ;32位地址的高16位 
             mov ax,[bx]
             call calc_segment_base
             mov [bx],ax                     ;回填段的基址
             add bx,4                        ;下一个重定位项(每项占4个字节) 
             loop realloc 
          
             jmp 	 [0x04]                  ;转移到用户程序  
     
    ;-------------------------------------------------------------------------------
    read_hard_disk_0:                        ;从硬盘读取一个逻辑扇区
                                             ;输入:DI:SI=起始逻辑扇区号
                                             ;      DS:BX=目标缓冲区地址
             push ax
             push bx
             push cx
             push dx
          
             mov dx,0x1f2
             mov al,1
             out dx,al                       ;读取的扇区数
    
             inc dx                          ;0x1f3
             mov ax,si
             out dx,al                       ;LBA地址7~0
    
             inc dx                          ;0x1f4
             mov al,ah
             out dx,al                       ;LBA地址15~8
    
             inc dx                          ;0x1f5
             mov ax,di
             out dx,al                       ;LBA地址23~16
    
             inc dx                          ;0x1f6
             mov al,0xe0                     ;LBA28模式,主盘
             or al,ah                        ;LBA地址27~24
             out dx,al
    
             inc dx                          ;0x1f7
             mov al,0x20                     ;读命令
             out dx,al
    
      .waits:
             in al,dx
             and al,0x88
             cmp al,0x08
             jnz .waits                      ;不忙,且硬盘已准备好数据传输 
    
             mov cx,256                      ;总共要读取的字数
             mov dx,0x1f0
      .readw:
             in ax,dx
             mov [bx],ax
             add bx,2
             loop .readw
    
             pop dx
             pop cx
             pop bx
             pop ax
          
             ret
    
    ;-------------------------------------------------------------------------------
    calc_segment_base:                       ;计算16位段地址
                                             ;输入:DX:AX=32位物理地址
                                             ;返回:AX=16位段基地址 
             push dx                          
             
             add ax,[cs:phy_base]
             adc dx,[cs:phy_base+0x02]
             shr ax,4
             ror dx,4
             and dx,0xf000
             or ax,dx
             
             pop dx
             
             ret
    
    ;-------------------------------------------------------------------------------
             phy_base dd 0x10000             ;用户程序被加载的物理起始地址
             
     times 510-($-$$) db 0
                      db 0x55,0xaa

             ;代码清单8-2/用户程序源代码
             ;文件名:c08.asm
             ;文件说明:用户程序 
             ;创建日期:2011-5-5 18:17
             
    ;===============================================================================
    SECTION header vstart=0                     ;定义用户程序头部段 
        program_length  dd program_end          ;程序总长度[0x00]
        
        ;用户程序入口点
        code_entry      dw start                ;偏移地址[0x04]
                        dd section.code_1.start ;段地址[0x06] 
        
        realloc_tbl_len dw (header_end-code_1_segment)/4
                                                ;段重定位表项个数[0x0a]
        
        ;段重定位表           
        code_1_segment  dd section.code_1.start ;[0x0c]
        code_2_segment  dd section.code_2.start ;[0x10]
        data_1_segment  dd section.data_1.start ;[0x14]
        data_2_segment  dd section.data_2.start ;[0x18]
        stack_segment   dd section.stack.start  ;[0x1c]
        
        header_end:                
        
    ;===============================================================================
    SECTION code_1 align=16 vstart=0         ;定义代码段1(16字节对齐) 
    put_string:                              ;显示串(0结尾)。
                                             ;输入:DS:BX=串地址
             mov cl,[bx]
             or cl,cl                        ;cl=0 ?
             jz .exit                        ;是的,返回主程序 
             call put_char
             inc bx                          ;下一个字符 
             jmp put_string
    
       .exit:
             ret
    
    ;-------------------------------------------------------------------------------
    put_char:                                ;显示一个字符
                                             ;输入:cl=字符ascii
             push ax
             push bx
             push cx
             push dx
             push ds
             push es
    
             ;以下取当前光标位置
            mov dx,0x3d4
            mov al,0x0e
            out dx,al
    		mov dx,0x3d5
             in al,dx                        ;高8位 
             mov ah,al
    
             mov dx,0x3d4
             mov al,0x0f
             out dx,al
             mov dx,0x3d5
             in al,dx                        ;低8位 
             mov bx,ax                       ;BX=代表光标位置的16位数
    
             cmp cl,0x0d                     ;回车符?
             jnz .put_0a                     ;不是。看看是不是换行等字符 
             mov ax,bx                       ;此句略显多余,但去掉后还得改书,麻烦 
             mov bl,80                       
             div bl
             mul bl
             mov bx,ax
             jmp .set_cursor
    
     .put_0a:
             cmp cl,0x0a                     ;换行符?
             jnz .put_other                  ;不是,那就正常显示字符 
             add bx,80
             jmp .roll_screen
    
     .put_other:                             ;正常显示字符
             mov ax,0xb800
             mov es,ax
             shl bx,1
             mov [es:bx],cl
    
             ;以下将光标位置推进一个字符
             shr bx,1
             add bx,1
    
     .roll_screen:
             cmp bx,2000                     ;光标超出屏幕?滚屏
             jl .set_cursor
    
             mov ax,0xb800
             mov ds,ax
             mov es,ax
             cld
             mov si,0xa0
             mov di,0x00
             mov cx,1920
             rep movsw
             mov bx,3840                     ;清除屏幕最底一行
             mov cx,80
     .cls:
             mov word[es:bx],0x0720
             add bx,2
             loop .cls
    
             mov bx,1920
    
     .set_cursor:
             mov dx,0x3d4
             mov al,0x0e
             out dx,al
             mov dx,0x3d5
             mov al,bh
             out dx,al
             mov dx,0x3d4
             mov al,0x0f
             out dx,al
             mov dx,0x3d5
             mov al,bl
             out dx,al
    
             pop es
             pop ds
             pop dx
             pop cx
             pop bx
             pop ax
    
             ret
    
    ;-------------------------------------------------------------------------------
      start:
             ;初始执行时,DS和ES指向用户程序头部段
             mov ax,[stack_segment]           ;设置到用户程序自己的堆栈 
             mov ss,ax
             mov sp,stack_end
             
             mov ax,[data_1_segment]          ;设置到用户程序自己的数据段
             mov ds,ax
    
             mov bx,msg0
             call put_string                  ;显示第一段信息 
    
             push word [es:code_2_segment]
             mov ax,begin
             push ax                          ;可以直接push begin,80386+
             
             retf                             ;转移到代码段2执行 
             
      continue:
             mov ax,[es:data_2_segment]       ;段寄存器DS切换到数据段2 
             mov ds,ax
             
             mov bx,msg1
             call put_string                  ;显示第二段信息 
    
             jmp $ 
    
    ;===============================================================================
    SECTION code_2 align=16 vstart=0          ;定义代码段2(16字节对齐)
    
      begin:
             push word [es:code_1_segment]
             mov ax,continue
             push ax                          ;可以直接push continue,80386+
             
             retf                             ;转移到代码段1接着执行 
             
    ;===============================================================================
    SECTION data_1 align=16 vstart=0
    
        msg0 db '  This is NASM - the famous Netwide Assembler. '
             db 'Back at SourceForge and in intensive development! '
             db 'Get the current versions from http://www.nasm.us/.'
             db 0x0d,0x0a,0x0d,0x0a
             db '  Example code for calculate 1+2+...+1000:',0x0d,0x0a,0x0d,0x0a
             db '     xor dx,dx',0x0d,0x0a
             db '     xor ax,ax',0x0d,0x0a
             db '     xor cx,cx',0x0d,0x0a
             db '  @@:',0x0d,0x0a
             db '     inc cx',0x0d,0x0a
             db '     add ax,cx',0x0d,0x0a
             db '     adc dx,0',0x0d,0x0a
             db '     inc cx',0x0d,0x0a
             db '     cmp cx,1000',0x0d,0x0a
             db '     jle @@',0x0d,0x0a
             db '     ... ...(Some other codes)',0x0d,0x0a,0x0d,0x0a
             db 0
    
    ;===============================================================================
    SECTION data_2 align=16 vstart=0
    
        msg1 db '  The above contents is written by LeeChung. '
             db '2011-05-06'
             db 0
    
    ;===============================================================================
    SECTION stack align=16 vstart=0
               
             resb 256
    
    stack_end:  
    
    ;===============================================================================
    SECTION trail align=16
    program_end:

     

         1                                           ;代码清单8-2//用户程序编译后执行文件
         2                                           ;文件名:c08.asm
         3                                           ;文件说明:用户程序 
         4                                           ;创建日期:2011-5-5 18:17
         5                                           
         6                                  ;===============================================================================
         7                                  SECTION header vstart=0                     ;定义用户程序头部段 
         8 00000000 [00000000]                  program_length  dd program_end          ;程序总长度[0x00]
         9                                      
        10                                      ;用户程序入口点
        11 00000004 [A600]                      code_entry      dw start                ;偏移地址[0x04]
        12 00000006 [00000000]                                  dd section.code_1.start ;段地址[0x06] 
        13                                      
        14 0000000A 0500                        realloc_tbl_len dw (header_end-code_1_segment)/4
        15                                                                              ;段重定位表项个数[0x0a]
        16                                      
        17                                      ;段重定位表           
        18 0000000C [00000000]                  code_1_segment  dd section.code_1.start ;[0x0c]
        19 00000010 [00000000]                  code_2_segment  dd section.code_2.start ;[0x10]
        20 00000014 [00000000]                  data_1_segment  dd section.data_1.start ;[0x14]
        21 00000018 [00000000]                  data_2_segment  dd section.data_2.start ;[0x18]
        22 0000001C [00000000]                  stack_segment   dd section.stack.start  ;[0x1c]
        23                                      
        24                                      header_end:                
        25                                      
        26                                  ;===============================================================================
        27                                  SECTION code_1 align=16 vstart=0         ;定义代码段1(16字节对齐) 
        28                                  put_string:                              ;显示串(0结尾)。
        29                                                                           ;输入:DS:BX=串地址
        30 00000000 8A0F                             mov cl,[bx]
        31 00000002 08C9                             or cl,cl                        ;cl=0 ?
        32 00000004 7407                             jz .exit                        ;是的,返回主程序 
        33 00000006 E80500                           call put_char
        34 00000009 43                               inc bx                          ;下一个字符 
        35 0000000A E9F3FF                           jmp put_string
        36                                  
        37                                     .exit:
        38 0000000D C3                               ret
        39                                  
        40                                  ;-------------------------------------------------------------------------------
        41                                  put_char:                                ;显示一个字符
        42                                                                           ;输入:cl=字符ascii
        43 0000000E 50                               push ax
        44 0000000F 53                               push bx
        45 00000010 51                               push cx
        46 00000011 52                               push dx
        47 00000012 1E                               push ds
        48 00000013 06                               push es
        49                                  
        50                                           ;以下取当前光标位置
        51 00000014 BAD403                           mov dx,0x3d4
        52 00000017 B00E                             mov al,0x0e
        53 00000019 EE                               out dx,al
        54                                          
        55 0000001A BAD503                  	 mov dx,0x3d5
        56 0000001D EC                               in al,dx                        ;高8位 
        57 0000001E 88C4                             mov ah,al
        58                                  
        59 00000020 BAD403                           mov dx,0x3d4
        60 00000023 B00F                             mov al,0x0f
        61 00000025 EE                               out dx,al
        62 00000026 BAD503                           mov dx,0x3d5
        63 00000029 EC                               in al,dx                        ;低8位 
        64 0000002A 89C3                             mov bx,ax                       ;BX=代表光标位置的16位数
        65                                  
        66 0000002C 80F90D                           cmp cl,0x0d                     ;回车符?
        67 0000002F 750D                             jnz .put_0a                     ;不是。看看是不是换行等字符 
        68 00000031 89D8                             mov ax,bx                       ;此句略显多余,但去掉后还得改书,麻烦 
        69 00000033 B350                             mov bl,80                       
        70 00000035 F6F3                             div bl
        71 00000037 F6E3                             mul bl
        72 00000039 89C3                             mov bx,ax
        73 0000003B E94900                           jmp .set_cursor
        74                                  
        75                                   .put_0a:
        76 0000003E 80F90A                           cmp cl,0x0a                     ;换行符?
        77 00000041 7507                             jnz .put_other                  ;不是,那就正常显示字符 
        78 00000043 81C35000                         add bx,80
        79 00000047 E91000                           jmp .roll_screen
        80                                  
        81                                   .put_other:                             ;正常显示字符
        82 0000004A B800B8                           mov ax,0xb800
        83 0000004D 8EC0                             mov es,ax
        84 0000004F D1E3                             shl bx,1
        85 00000051 26880F                           mov [es:bx],cl
        86                                  
        87                                           ;以下将光标位置推进一个字符
        88 00000054 D1EB                             shr bx,1
        89 00000056 81C30100                         add bx,1
        90                                  
        91                                   .roll_screen:
        92 0000005A 81FBD007                         cmp bx,2000                     ;光标超出屏幕?滚屏
        93 0000005E 7C27                             jl .set_cursor
        94                                  
        95 00000060 B800B8                           mov ax,0xb800
        96 00000063 8ED8                             mov ds,ax
        97 00000065 8EC0                             mov es,ax
        98 00000067 FC                               cld
        99 00000068 BEA000                           mov si,0xa0
       100 0000006B BF0000                           mov di,0x00
       101 0000006E B98007                           mov cx,1920
       102 00000071 F3A5                             rep movsw
       103 00000073 BB000F                           mov bx,3840                     ;清除屏幕最底一行
       104 00000076 B95000                           mov cx,80
       105                                   .cls:
       106 00000079 26C7072007                       mov word[es:bx],0x0720
       107 0000007E 81C30200                         add bx,2
       108 00000082 E2F5                             loop .cls
       109                                  
       110 00000084 BB8007                           mov bx,1920
       111                                  
       112                                   .set_cursor:
       113 00000087 BAD403                           mov dx,0x3d4
       114 0000008A B00E                             mov al,0x0e
       115 0000008C EE                               out dx,al
       116 0000008D BAD503                           mov dx,0x3d5
       117 00000090 88F8                             mov al,bh
       118 00000092 EE                               out dx,al
       119 00000093 BAD403                           mov dx,0x3d4
       120 00000096 B00F                             mov al,0x0f
       121 00000098 EE                               out dx,al
       122 00000099 BAD503                           mov dx,0x3d5
       123 0000009C 88D8                             mov al,bl
       124 0000009E EE                               out dx,al
       125                                  
       126 0000009F 07                               pop es
       127 000000A0 1F                               pop ds
       128 000000A1 5A                               pop dx
       129 000000A2 59                               pop cx
       130 000000A3 5B                               pop bx
       131 000000A4 58                               pop ax
       132                                  
       133 000000A5 C3                               ret
       134                                  
       135                                  ;-------------------------------------------------------------------------------
       136                                    start:
       137                                           ;初始执行时,DS和ES指向用户程序头部段
       138 000000A6 A1[1C00]                         mov ax,[stack_segment]           ;设置到用户程序自己的堆栈 
       139 000000A9 8ED0                             mov ss,ax
       140 000000AB BC[0001]                         mov sp,stack_end
       141                                           
       142 000000AE A1[1400]                         mov ax,[data_1_segment]          ;设置到用户程序自己的数据段
       143 000000B1 8ED8                             mov ds,ax
       144                                  
       145 000000B3 BB[0000]                         mov bx,msg0
       146 000000B6 E847FF                           call put_string                  ;显示第一段信息 
       147                                  
       148 000000B9 26FF36[1000]                     push word [es:code_2_segment]
       149 000000BE B8[0000]                         mov ax,begin
       150 000000C1 50                               push ax                          ;可以直接push begin,80386+
       151                                           
       152 000000C2 CB                               retf                             ;转移到代码段2执行 
       153                                           
       154                                    continue:
       155 000000C3 26A1[1800]                       mov ax,[es:data_2_segment]       ;段寄存器DS切换到数据段2 
       156 000000C7 8ED8                             mov ds,ax
       157                                           
       158 000000C9 BB[0000]                         mov bx,msg1
       159 000000CC E831FF                           call put_string                  ;显示第二段信息 
       160                                  
       161 000000CF E9FDFF                           jmp $ 
       162                                  
       163                                  ;===============================================================================
       164                                  SECTION code_2 align=16 vstart=0          ;定义代码段2(16字节对齐)
       165                                  
       166                                    begin:
       167 00000000 26FF36[0C00]                     push word [es:code_1_segment]
       168 00000005 B8[C300]                         mov ax,continue
       169 00000008 50                               push ax                          ;可以直接push continue,80386+
       170                                           
       171 00000009 CB                               retf                             ;转移到代码段1接着执行 
       172                                           
       173                                  ;===============================================================================
       174                                  SECTION data_1 align=16 vstart=0
       175                                  
       176 00000000 202054686973206973-         msg0 db '  This is NASM - the famous Netwide Assembler. '
       177 00000009 204E41534D202D2074-
       178 00000012 68652066616D6F7573-
       179 0000001B 204E65747769646520-
       180 00000024 417373656D626C6572-
       181 0000002D 2E20               
       182 0000002F 4261636B2061742053-              db 'Back at SourceForge and in intensive development! '
       183 00000038 6F75726365466F7267-
       184 00000041 6520616E6420696E20-
       185 0000004A 696E74656E73697665-
       186 00000053 20646576656C6F706D-
       187 0000005C 656E742120         
       188 00000061 476574207468652063-              db 'Get the current versions from http://www.nasm.us/.'
       189 0000006A 757272656E74207665-
       190 00000073 7273696F6E73206672-
       191 0000007C 6F6D20687474703A2F-
       192 00000085 2F7777772E6E61736D-
       193 0000008E 2E75732F2E         
       194 00000093 0D0A0D0A                         db 0x0d,0x0a,0x0d,0x0a
       195 00000097 20204578616D706C65-              db '  Example code for calculate 1+2+...+1000:',0x0d,0x0a,0x0d,0x0a
       196 000000A0 20636F646520666F72-
       197 000000A9 2063616C63756C6174-
       198 000000B2 6520312B322B2E2E2E-
       199 000000BB 2B313030303A0D0A0D-
       200 000000C4 0A                 
       201 000000C5 2020202020786F7220-              db '     xor dx,dx',0x0d,0x0a
       202 000000CE 64782C64780D0A     
       203 000000D5 2020202020786F7220-              db '     xor ax,ax',0x0d,0x0a
       204 000000DE 61782C61780D0A     
       205 000000E5 2020202020786F7220-              db '     xor cx,cx',0x0d,0x0a
       206 000000EE 63782C63780D0A     
       207 000000F5 202040403A0D0A                   db '  @@:',0x0d,0x0a
       208 000000FC 2020202020696E6320-              db '     inc cx',0x0d,0x0a
       209 00000105 63780D0A           
       210 00000109 202020202061646420-              db '     add ax,cx',0x0d,0x0a
       211 00000112 61782C63780D0A     
       212 00000119 202020202061646320-              db '     adc dx,0',0x0d,0x0a
       213 00000122 64782C300D0A       
       214 00000128 2020202020696E6320-              db '     inc cx',0x0d,0x0a
       215 00000131 63780D0A           
       216 00000135 2020202020636D7020-              db '     cmp cx,1000',0x0d,0x0a
       217 0000013E 63782C313030300D0A 
       218 00000147 20202020206A6C6520-              db '     jle @@',0x0d,0x0a
       219 00000150 40400D0A           
       220 00000154 20202020202E2E2E20-              db '     ... ...(Some other codes)',0x0d,0x0a,0x0d,0x0a
       221 0000015D 2E2E2E28536F6D6520-
       222 00000166 6F7468657220636F64-
       223 0000016F 6573290D0A0D0A     
       224 00000176 00                               db 0
       225                                  
       226                                  ;===============================================================================
       227                                  SECTION data_2 align=16 vstart=0
       228                                  
       229 00000000 20205468652061626F-         msg1 db '  The above contents is written by LeeChung. '
       230 00000009 766520636F6E74656E-
       231 00000012 747320697320777269-
       232 0000001B 7474656E206279204C-
       233 00000024 65654368756E672E20 
       234 0000002D 323031312D30352D30-              db '2011-05-06'
       235 00000036 36                 
       236 00000037 00                               db 0
       237                                  
       238                                  ;===============================================================================
       239                                  SECTION stack align=16 vstart=0
       240                                             
       241 00000000 <res 00000100>                   resb 256
       242          ******************       warning: uninitialized space declared in stack section: zeroing
       243                                  
       244                                  stack_end:  
       245                                  
       246                                  ;===============================================================================
       247                                  SECTION trail align=16
       248                                  program_end:
    

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值