Assembly 如何在程序集中的FF0H位置写入?

Assembly 如何在程序集中的FF0H位置写入?,assembly,x86-16,Assembly,X86 16,我想在FFFF0H位置和目标F8000H处编写一条jmp指令 在那之后,我想把下面的代码放在F8000H,这样在从FFFF0H执行时,控件将通过上面的跳转传输给它 .MODEL SMALL .8086 .STACK .DATA .CODE .STARTUP LL: MOV AL, 1H IO_LOOP: OUT 0EH, AL SHL AL, 1 ;Delay MOV CX, 0FFFFH DLOOP: NOP LOOP DLOOP ;Start al

我想在FFFF0H位置和目标F8000H处编写一条
jmp
指令

在那之后,我想把下面的代码放在F8000H,这样在从FFFF0H执行时,控件将通过上面的跳转传输给它

.MODEL SMALL
.8086

.STACK

.DATA

.CODE

.STARTUP

LL:
  MOV AL, 1H

IO_LOOP:
  OUT 0EH, AL
  SHL AL, 1

  ;Delay
  MOV CX, 0FFFFH
DLOOP:
  NOP
 LOOP DLOOP

 ;Start all over again
 CMP AL, 00H
JE  LL

 ;Get back to IO cycle
JMP IO_LOOP

END
注意

地址范围0F0000h-0FFFFFh为只读。
真实情况是,在创建BIOS的卷影副本后,固件在启动时将其设置为只读,这样访问就不必一直访问PCH,默认情况下,PCH会在标准地址范围FFFF_0000H-FFFF_FFFFH处重新路由

因此,这些地址范围要么映射到只读DRAM区域,要么映射到闪存ROM,在编程之前忽略写入请求

如果您正在编写固件,那么构建链肯定支持创建可放置在ROM中任何位置的节。
解释如何使用这种工具超出了本回答和本网站的范围


不过,您似乎正在编写一个普通的DOS可执行文件,请注意下面的解决方案将不起作用。
因此,我将简单地假设您想要将一段代码从a移到B

我们需要:

  • 在两个内存区域之间移动数据的一些代码。
    这可以通过多种方式完成,编码速度最快,但速度最慢(对于小的块)是使用
    rep movsb
    cx
    字节从
    ds:si
    复制到
    es:di

  • 一种判断代码长度的方法。
    我们可以在代码的开头和结尾分别放置两个标签,比如S和E。这样,表达式E-S以字节为单位给出两个标签之间的差异,即代码的长度

  • 以下是一个可能的实现:

    .MODEL SMALL
    .8086
    
    .STACK
    
    .DATA
    
    .CODE
    
    .STARTUP
    
     ;Set up ES
     mov ax, 0f000h
     mov es, ax
    
     ;Move the first routine 
    
     mov si, OFFSET __ROUTINE_1__START__                   ;DS:SI = Start of the routine to copy
     mov di, 8000h                                         ;ES:DI = 0f000h:8000h = 0f8000h
     mov cx,  __ROUTINE_1__END__ - __ROUTINE_1__START__    ;CX = Length of the routine to copy
     rep movsb
    
     ;Copy the jump
    
     mov si, OFFSET __ROUTINE_2__START__
     mov di, 0fff0h                                        ;ES:DI = 0f000h:0fff0h = 0ffff0h
     mov cx,  5                                            ;Absolute far jump is 5 bytes
     rep movsb
    
    
     ;DO SOMETHING HERE
    
     ;
     ; ROUTINE TO MOVE
     ;
    
    __ROUTINE_1__START__:
    LL:
      MOV AL, 1H
    
    IO_LOOP:
      OUT 0EH, AL
      SHL AL, 1
    
      ;Delay
      MOV CX, 0FFFFH
    DLOOP:
      NOP
     LOOP DLOOP
    
     ;Start all over again
     CMP AL, 00H
    JE  LL
    
     ;Get back to IO cycle
    JMP IO_LOOP
    
    __ROUTINE_1__END__:
    
    __ROUTINE_2__START__:
     jmp FAR 0f000h:8000h                 ;TODO: Adjust the syntax for the assembler dialect
    
    END
    
    正如我所说的,这个解决方案不适用于您选择的地址范围,除非您在一个特殊的上下文中工作。 我还假设你知道分割是如何工作的

    我没有通过使用
    mov
    -即时存储直接存储机器代码来创建far
    jmp
    ;相反,我让汇编程序创建机器代码,然后复制它。

    它的效率较低,但可以让您轻松地更改代码

    我完全改变了你那杂乱无章的问题的措辞。你必须绝对检查我的解释是否正确,更新的问题是否仍然反映了你的需求。在我的头像上方,你可以看到一个“编辑的XX ago”链接,点击它访问修订历史记录,并最终回滚到原始问题。在左边的角落,你可以进一步编辑我的工作,如果需要的话。