美文网首页
[011][x86汇编语言]retf 等价写法 jmp far

[011][x86汇编语言]retf 等价写法 jmp far

作者: AkuRinbu | 来源:发表于2018-05-22 15:39 被阅读0次

    学习笔记

    《x86汇编语言:从实模式到保护模式》
    https://www.jianshu.com/p/d481cb547e9f

    第8章 本章习题 第1题

    • 修改用户程序c08.asm,不使用retf

    解答:使用 16位间接绝对远转移 jmp far [BX]

    • 使用 jmp far [BX] ,从指令给出的偏移地址处取出两个,分别是偏移地址和段地址
    在 header段 增加 两个标号,用于存放跳转地址
    goto2 dw 0,0
    goto1 dw 0,0
    
    ==================================
    code_1 段
    
    ;push word [es:code_2_segment]
             ;mov ax,begin
             ;push ax                          ;可以直接push begin,80386+
             
             ;retf                             ;转移到代码段2执行 
             
             
             
             ; IP
             mov ax,begin
             mov [es:goto2],ax
             
             ; CS
             mov ax,[es:code_2_segment]
             mov [es:goto2+0x02],ax
                
             jmp far [es:goto2]     
    
    
    ====================================
    code_2 段
    
    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接着执行 
             
             
              ; IP
             mov ax,continue
             mov [es:goto1],ax
             
             ; CS
             mov ax,[es:code_1_segment]
             mov [es:goto1+0x02],ax
                
             jmp far [es:goto1]     
    
    第8章 本章习题 第1题 测试运行

    e08.asm 完整源码

             ;代码清单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:                
        goto2 dw 0,0
        goto1 dw 0,0
    ;===============================================================================
    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执行 
             
             
             
             ; IP
             mov ax,begin
             mov [es:goto2],ax
             
             ; CS
             mov ax,[es:code_2_segment]
             mov [es:goto2+0x02],ax
                
             jmp far [es:goto2]     
    
      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接着执行 
             
             
              ; IP
             mov ax,continue
             mov [es:goto1],ax
             
             ; CS
             mov ax,[es:code_1_segment]
             mov [es:goto1+0x02],ax
                
             jmp far [es:goto1]     
             
             
    ;===============================================================================
    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:
    

    相关文章

      网友评论

          本文标题:[011][x86汇编语言]retf 等价写法 jmp far

          本文链接:https://www.haomeiwen.com/subject/dpbrjftx.html